10 #include <cvd/internal/pixel_operations.h> 11 #include <cvd/utility.h> 12 #include <cvd/vision_exceptions.h> 14 #if defined(CVD_HAVE_TOON) 15 #include <TooN/TooN.h> 16 #include <TooN/helpers.h> 50 for(
int r = 0; r < out.size().y; r++)
52 float r_in = r * scale;
53 int r_i = floor(r_in);
54 float r_delta = r_in - floor(r_in);
59 for(; c < out.size().x - 4; c += 4)
61 float c_in1 = c * scale;
62 int c_i1 = floor(c_in1);
63 float c_delta1 = c_in1 - floor(c_in1);
64 auto r11 = in[r_i][c_i1] * (1 - c_delta1) + in[r_i][c_i1 + 1] * c_delta1;
65 auto r21 = in[r_i + 1][c_i1] * (1 - c_delta1) + in[r_i + 1][c_i1 + 1] * c_delta1;
67 float c_in2 = (c + 1) * scale;
68 int c_i2 = floor(c_in2);
69 float c_delta2 = c_in2 - floor(c_in2);
70 auto r12 = in[r_i][c_i2] * (1 - c_delta2) + in[r_i][c_i2 + 1] * c_delta2;
71 auto r22 = in[r_i + 1][c_i2] * (1 - c_delta2) + in[r_i + 1][c_i2 + 1] * c_delta2;
73 float c_in3 = (c + 2) * scale;
74 int c_i3 = floor(c_in3);
75 float c_delta3 = c_in3 - floor(c_in3);
76 auto r13 = in[r_i][c_i3] * (1 - c_delta3) + in[r_i][c_i3 + 1] * c_delta3;
77 auto r23 = in[r_i + 1][c_i3] * (1 - c_delta3) + in[r_i + 1][c_i3 + 1] * c_delta3;
79 float c_in4 = (c + 3) * scale;
80 int c_i4 = floor(c_in4);
81 float c_delta4 = c_in4 - floor(c_in4);
82 auto r14 = in[r_i][c_i4] * (1 - c_delta4) + in[r_i][c_i4 + 1] * c_delta4;
83 auto r24 = in[r_i + 1][c_i4] * (1 - c_delta4) + in[r_i + 1][c_i4 + 1] * c_delta4;
85 out[r][c] = r11 * (1 - r_delta) + r21 * r_delta;
86 out[r][c + 1] = r12 * (1 - r_delta) + r22 * r_delta;
87 out[r][c + 2] = r13 * (1 - r_delta) + r23 * r_delta;
88 out[r][c + 3] = r14 * (1 - r_delta) + r24 * r_delta;
91 for(; c < out.size().x; c++)
93 float c_in1 = c * scale;
94 int c_i1 = floor(c_in1);
95 float c_delta1 = c_in1 - floor(c_in1);
96 auto r11 = in[r_i][c_i1] * (1 - c_delta1) + in[r_i][c_i1 + 1] * c_delta1;
97 auto r21 = in[r_i + 1][c_i1] * (1 - c_delta1) + in[r_i + 1][c_i1 + 1] * c_delta1;
99 out[r][c] = r11 * (1 - r_delta) + r21 * r_delta;
129 current_ptr = &reduced;
136 current_ptr = &reduced;
152 typedef typename Pixel::traits<C>::wider_type sum_type;
153 if((in.
size() / 3 * 2) != out.
size())
156 for(
int yy = 0, y = 0; y < in.
size().
y - 2; y += 3, yy += 2)
157 for(
int xx = 0, x = 0; x < in.
size().
x - 2; x += 3, xx += 2)
163 sum_type a(in[y][x]);
164 sum_type b(in[y][x + 1]);
165 sum_type c(in[y][x + 2]);
166 sum_type d(in[y + 1][x]);
167 sum_type e(in[y + 1][x + 1]);
168 sum_type f(in[y + 1][x + 2]);
169 sum_type g(in[y + 2][x]);
170 sum_type h(in[y + 2][x + 1]);
171 sum_type i(in[y + 2][x + 2]);
173 out[yy][xx] =
static_cast<C
>((a * 4 + b * 2 + d * 2 + e) / 9);
174 out[yy][xx + 1] =
static_cast<C
>((c * 4 + b * 2 + f * 2 + e) / 9);
175 out[yy + 1][xx] =
static_cast<C
>((g * 4 + h * 2 + d * 2 + e) / 9);
176 out[yy + 1][xx + 1] =
static_cast<C
>((i * 4 + h * 2 + f * 2 + e) / 9);
208 typedef typename Pixel::traits<T>::wider_type sum_type;
212 for(
int yo = 0; yo < out.
size().
y; yo++)
213 for(
int xo = 0; xo < out.
size().
x; xo++)
214 out[yo][xo] = static_cast<T>((sum_type(in[yo * 2][xo * 2]) + in[yo * 2 + 1][xo * 2] + in[yo * 2][xo * 2 + 1] + in[yo * 2 + 1][xo * 2 + 1]) / 4);
243 for(; octaves > 0; --octaves)
281 double sum[c] = { 0 };
282 double sumSq[c] = { 0 };
283 const T* p = im.
data();
284 const T* end = im.
data() + im.totalsize();
287 for(
int k = 0; k < c; k++)
295 for(
int k = 0; k < c; k++)
297 double m = sum[k] / im.totalsize();
299 sumSq[k] /= im.totalsize();
313 inline S operator()(
const S& s)
const 322 template <
class S,
class T>
325 typedef typename Pixel::Component<S>::type SComp;
326 typedef typename Pixel::Component<T>::type TComp;
327 typedef typename Pixel::traits<SComp>::wider_type diff_type;
330 for(
int y = 0; y < I.
size().y; y++)
331 for(
int x = 0; x < I.
size().x; x++)
333 Pixel::Component<T>::get(grad[y][x], 0) = Pixel::scalar_convert<TComp, SComp, diff_type>(diff_type(I[y][x + 1]) - I[y][x - 1]);
334 Pixel::Component<T>::get(grad[y][x], 1) = Pixel::scalar_convert<TComp, SComp, diff_type>(diff_type(I[y + 1][x]) - I[y - 1][x]);
347 template <
class S,
class T>
355 #ifndef DOXYGEN_IGNORE_INTERNAL 359 template <
class T,
class S,
typename Precision>
360 inline void sample(
const BasicImage<S>& im, Precision x, Precision y, T& result)
362 typedef typename Pixel::Component<S>::type SComp;
363 typedef typename Pixel::Component<T>::type TComp;
364 const int lx = (int)x;
365 const int ly = (int)y;
368 for(
unsigned int i = 0; i < Pixel::Component<T>::count; i++)
375 template <
class T,
class S,
typename Precision>
376 inline T sample(
const BasicImage<S>& im, Precision x, Precision y)
379 sample(im, x, y, result);
383 inline void sample(
const BasicImage<float>& im,
double x,
double y,
float& result)
385 const int lx = (int)x;
386 const int ly = (int)y;
387 const int w = im.row_stride();
388 const float* base = im[ly] + lx;
389 const float a = base[0];
390 const float b = base[1];
391 const float c = base[w];
392 const float d = base[w + 1];
393 const float e = a - b;
396 result = (float)(x * (y * (e - c + d) - e) + y * (c - a) + a);
399 #if defined(CVD_HAVE_TOON) 411 template <
typename T,
typename S,
typename P>
412 int transform(
const BasicImage<S>& in,
BasicImage<T>& out,
const TooN::Matrix<2, 2, P>& M,
const TooN::Vector<2, P>& inOrig,
const TooN::Vector<2, P>& outOrig,
const T defaultValue = T())
414 const int w = out.
size().x, h = out.
size().y, iw = in.
size().x, ih = in.
size().y;
415 const TooN::Vector<2, P> across = M.T()[0];
416 const TooN::Vector<2, P> down = M.T()[1];
418 const TooN::Vector<2, P> p0 = inOrig - M * outOrig;
419 const TooN::Vector<2, P> p1 = p0 + w * across;
420 const TooN::Vector<2, P> p2 = p0 + h * down;
421 const TooN::Vector<2, P> p3 = p0 + w * across + h * down;
427 P min_x = p0[0], min_y = p0[1];
428 P max_x = min_x, max_y = min_y;
432 min_x += w * across[0];
434 max_x += w * across[0];
436 min_x += h * down[0];
438 max_x += h * down[0];
440 min_y += w * across[1];
442 max_y += w * across[1];
444 min_y += h * down[1];
446 max_y += h * down[1];
449 const TooN::Vector<2, P> carriage_return = down - w * across;
453 if(min_x >= 0 && min_y >= 0 && max_x < iw - 1 && max_y < ih - 1)
455 TooN::Vector<2, P> p = p0;
456 for(
int i = 0; i < h; ++i, p += carriage_return)
457 for(
int j = 0; j < w; ++j, p += across)
458 sample(in, p[0], p[1], out[i][j]);
464 const P x_bound = iw - 1;
465 const P y_bound = ih - 1;
467 TooN::Vector<2, P> p = p0;
468 for(
int i = 0; i < h; ++i, p += carriage_return)
470 for(
int j = 0; j < w; ++j, p += across)
473 if(0 <= p[0] && 0 <= p[1] && p[0] < x_bound && p[1] < y_bound)
474 sample(in, p[0], p[1], out[i][j]);
477 out[i][j] = defaultValue;
489 TooN::Vector<3> base = Minv.T()[2];
490 TooN::Vector<2> offset;
491 offset[0] = in.
size().x / 2;
492 offset[1] = in.
size().y / 2;
493 offset -= TooN::project(base);
494 TooN::Vector<3> across = Minv.T()[0];
495 TooN::Vector<3> down = Minv.T()[1];
496 double w = in.
size().x - 1;
497 double h = in.
size().y - 1;
498 int ow = out.
size().x;
499 int oh = out.
size().y;
500 base -= down * (oh / 2) + across * (ow / 2);
501 for(
int row = 0; row < oh; row++, base += down)
503 TooN::Vector<3> x = base;
504 for(
int col = 0; col < ow; col++, x += across)
506 TooN::Vector<2> p = project(x) + offset;
507 if(p[0] >= 0 && p[0] <= w - 1 && p[1] >= 0 && p[1] <= h - 1)
508 sample(in, p[0], p[1], out[row][col]);
516 template <
typename T,
typename CAM1,
typename CAM2>
520 for(
int y = 0; y < size.
y; ++y)
522 for(
int x = 0; x < size.
x; ++x)
524 TooN::Vector<2> l = cam_in.project(cam_out.unproject(TooN::makeVector(x, y)));
525 if(l[0] >= 0 && l[0] <= in.
size().x - 1 && l[1] >= 0 && l[1] <= in.
size().y - 1)
527 sample(in, l[0], l[1], out[y][x]);
538 template <
typename T,
typename CAM1,
typename CAM2>
542 warp(in, cam_in, result, cam_out);
549 template <
typename T,
typename CAM1,
typename CAM2>
553 warp(in, cam_in, result, cam_out);
564 CVD_ASSERT(in.
size().transpose() == out.
size());
565 for(
int r = 0; r < in.
size().
y; r++)
566 for(
int c = 0; c < in.
size().
x; c++)
567 out[c][r] = in[r][c];
574 CVD_ASSERT(in.
size().transpose() == out.
size());
576 if(in.
size().
area() *
static_cast<int>(
sizeof(T)) < bytes || in.
size().
x == 1 || in.
size().
y == 1)
577 simpleTranspose(in, out);
583 const int width_left = in.
size().
x / 2;
584 const int width_right = in.
size().
x - width_left;
587 const ImageRef right_start { width_left, 0 };
589 recursiveTranspose(in.sub_image(
ImageRef(0, 0), left_chunk), out.sub_image(
ImageRef(0, 0), left_chunk.transpose()));
590 recursiveTranspose(in.sub_image(right_start, right_chunk), out.sub_image(right_start.transpose(), right_chunk.transpose()));
594 const int height_top = in.
size().
y / 2;
595 const int height_bottom = in.
size().
y - height_top;
598 ImageRef bottom_start { 0, height_top };
600 recursiveTranspose(in.sub_image(
ImageRef(0, 0), top_chunk), out.sub_image(
ImageRef(0, 0), top_chunk.transpose()));
601 recursiveTranspose(in.sub_image(bottom_start, bottom_chunk), out.sub_image(bottom_start.transpose(), bottom_chunk.transpose()));
610 CVD_ASSERT(in.
size().transpose() == out.
size());
611 Internal::recursiveTranspose(in, out);
618 Internal::recursiveTranspose(in, out);
626 for(
int r = 0; r < in.
size().
y / 2; r++)
627 for(
int c = 0; c < in.
size().
x; c++)
629 std::swap(in[r][c], in[in.
size().
y - 1 - r][c]);
643 for(
int r = 0; r < in.
size().
y; r++)
644 std::reverse(in[r], in[r] + in.
size().
x);
656 inline T median3(T a, T b, T c)
659 return std::max(b, std::min(a, c));
661 return std::max(a, std::min(b, c));
665 inline void sort3(T& a, T& b, T& c)
677 T median_3x3(
const T* p,
const int w)
679 T a = p[-w - 1], b = p[-w], c = p[-w + 1], d = p[-1], e = p[0], f = p[1], g = p[w - 1], h = p[w], i = p[w + 1];
683 e = median3(b, e, h);
684 g = std::max(std::max(a, d), g);
685 c = std::min(c, std::min(f, i));
686 return median3(c, e, g);
690 void median_filter_3x3(
const T* p,
const int w,
const int n, T* out)
692 T a = p[-w - 1], b = p[-w], d = p[-1], e = p[0], g = p[w - 1], h = p[w];
695 for(
int j = 0; j < n; ++j, ++p, ++out)
697 T c = p[-w + 1], f = p[1], i = p[w + 1];
699 *out = median3(std::min(std::min(g, h), i),
701 std::max(std::max(a, b), c));
716 const int s = I.row_stride();
717 const int n = I.
size().x - 2;
718 for(
int i = 1; i + 1 < I.
size().y; ++i)
719 median::median_filter_3x3(I[i] + 1, s, n, out[i] + 1);
728 #endif // CVD_VISION_H_ void stats(const BasicImage< T > &im, T &mean, T &stddev)
computes mean and stddev of intensities in an image.
Definition: vision.h:277
Input images have incompatible dimensions.
Definition: vision_exceptions.h:26
void gradient(const BasicImage< S > &im, BasicImage< T > &out)
computes the gradient image from an image.
Definition: vision.h:348
Image< C > fastApproximateDownSample(const BasicImage< C > &in, double scale)
Downsample an image using some fast hacks.
Definition: vision.h:121
constexpr int area() const
Area (product of x and y; signed)
Definition: image_ref.h:213
All classes and functions are within the CVD namespace.
Definition: argb.h:6
ImageRef size() const
What is the size of this image?
Definition: image.h:557
void threshold(BasicImage< T > &im, const T &minimum, const T &hi)
thresholds an image by setting all pixel values below a minimum to 0 and all values above to a given ...
Definition: vision.h:256
void flipHorizontal(SubImage< T > &&in)
flips an image horizontally in place.
Definition: vision.h:641
void halfSample(const BasicImage< T > &in, BasicImage< T > &out)
subsamples an image to half its size by averaging 2x2 pixel blocks
Definition: vision.h:206
ConstPointerType data() const
Returns the raw image data.
Definition: image.h:535
int x
The x co-ordinate.
Definition: image_ref.h:172
a functor multiplying pixels with constant value.
Definition: vision.h:307
Image< C > linearInterpolationDownsample(const BasicImage< C > &in, float scale)
Downsample an image using linear interpolation.
Definition: vision.h:41
Definition: image_ref.h:29
void zeroBorders(BasicImage< T > &I)
Set the one-pixel border (top, bottom, sides) of an image to zero values.
Definition: utility.h:109
void flipVertical(SubImage< T > &&in)
flips an image vertically in place.
Definition: vision.h:624
void zeroPixel(T &pixel)
Set a pixel to the default value (typically 0) For multi-component pixels, this zeros all components ...
Definition: utility.h:100
int y
The y co-ordinate.
Definition: image_ref.h:173
A full image which manages its own data.
Definition: image.h:623
Definition: builtin_components.h:38
void twoThirdsSample(const BasicImage< C > &in, BasicImage< C > &out)
Subsamples an image to 2/3 of its size by averaging 3x3 blocks into 2x2 blocks.
Definition: vision.h:150