9 using namespace cimg_library
;
11 /** General image processing tools. */
14 /** A struct for computing the sum of pixels in an image. */
18 /** Initialize the summer with a reference to an image. */
19 PixelSum(const CImg
<T
> &img
) : img(img
), sum(0), count(0) { }
21 /** Process a pixel by summing. */
22 void operator()(int x
, int y
)
28 const CImg
<T
> &img
; //!< The image from which the pixel values are fetched
29 T sum
; //!< The sum of the pixels
30 int count
; //!< The number of pixels summed
35 Create a rectangular zero-sum peak filter.
37 The filter is first filled with the value of \c -sign, and the
38 center value of the filter is set so that the sum is zero.
40 \param width = the width of the filter (must be odd)
41 \param sign = the sign of the peak
42 \return the filter image
46 peak_filter(int width
, int sign
= 1)
48 assert(width
% 2 == 1);
49 CImg
<T
> filter(width
, width
);
51 filter(filter
.width
/ 2, filter
.height
/ 2) -= filter
.sum();
56 /** Set all negative values of the image to zero.
57 \param img = the image to be processed
61 zero_negatives(CImg
<T
> &img
)
63 for (int i
= 0; i
< (int)img
.size(); i
++)
68 /** Weigh an image with a centered gaussian.
69 \param img = the image to weight
70 \param xc = center-x of the gaussian
71 \param yc = center-y of the gaussian
72 \param x_sigma2 = the variance in x-dimension
73 \param y_sigma2 = the variance in y-dimension
77 weight_gaussian(CImg
<T
> &img
, float xc
, float yc
,
78 float x_sigma2
, float y_sigma2
)
80 cimg_mapXY(img
, x
, y
) {
83 exponent
+= -0.5 * (xc
- x
) * (xc
- x
) / x_sigma2
;
85 exponent
+= -0.5 * (yc
- y
) * (yc
- y
) / y_sigma2
;
86 img(x
,y
) *= exp(exponent
);
91 Compute the Hough transform.
93 Each point in the resulting image correspond to a straight line
94 in the original image. The x-axis represents the angle (theta)
95 of the normal of the line, and the y-axis represents the
96 distance (rho) between the line and the center of the image.
97 The width of the result will be \c num_thetas, and the height of
98 the result will be (2 * \c max_rho + 1). The center row of the
99 Hough image corresponds to lines crossing the center of the
102 \param src = the image to transform
103 \param theta1 = the smallest value of theta
104 \param theta2 = the largest value of theta
105 \param num_thetas = the width of the resulting image
106 \param max_rho = the maximum distance considered
107 \return Hough transform of \c src
110 CImg
<T
> hough(const CImg
<T
> &src
, float theta1
, float theta2
,
111 int num_thetas
, int max_rho
)
113 int num_rhos
= max_rho
* 2 + 1;
114 int rho_center
= num_rhos
/ 2;
116 CImg
<T
> result
= CImg
<T
>(num_thetas
, num_rhos
);
119 cimg_mapXY(src
, x
, y
) {
121 // Skip non-positive pixels
125 float rho_x
= (float)x
- src
.width
/2;
126 float rho_y
= (float)y
- src
.height
/2;
127 float rho0
= std::sqrt(rho_x
* rho_x
+ rho_y
* rho_y
);
128 float theta0
= std::atan2(rho_y
, rho_x
) / M_PI
* 180;
135 // Iterate all thetas and compute corresponding rho
136 float theta_delta
= (theta2
- theta1
) / (num_thetas
- 1);
137 for (int t
= 0; t
< num_thetas
; t
++) {
138 float theta
= theta1
+ t
* theta_delta
;
139 float r
= rho0
* std::cos((theta0
- theta
) / 180 * M_PI
) + rho_center
;
140 if (r
< 0 || r
>= result
.dimy())
143 int ir
= (int)floor(r
);
146 result(t
, ir
) += src(x
, y
) * (1 - w
);
147 if (ir
+ 1 < (int)result
.height
)
148 result(t
, ir
+1) += src(x
, y
) * w
;
156 /** Median of the values in a one-dimensional row image.
158 * \note It is safe to specify ranges outside the image. The range
161 * \param img = the source image
162 * \param x1 = the start of the range
163 * \param x2 = the end of the range
165 template <typename T
>
167 median(CImg
<T
> &img
, int x1
, int x2
)
171 if (x2
>= (int)img
.width
)
174 std::vector
<T
> values(x2
- x1
+ 1);
175 for (int x
= x1
; x
<= x2
; x
++)
176 values
[x
- x1
] = img(x
);
177 return util::median(values
);
181 /** Remove a peak from a one-dimensional image.
183 * \param img = the image to process
184 * \param x0 = the location of the peak
185 * \param win = the width of the median analysis window
186 * \param value = the value to set the peak neighbourhood to
188 template <typename T
>
190 median_peak_remove(CImg
<T
> &img
, int x0
, int win
, T value
= 0)
192 // Compute the threshold to stop the removing
193 T threshold
= im::median(img
, x0
- win
, x0
+ win
);
195 // Remove values in the right neighbourhood
196 for (int i
= 0; i
< win
; i
++) {
198 if (x
>= (int)img
.width
)
200 if (img(x
) < threshold
)
205 // Remove values in the left neighbourhood
206 for (int i
= 1; i
< win
; i
++) {
210 if (img(x
) < threshold
)
216 /** Find a maximum from a one-dimensional image.
217 * \param img = the image to find maximum from
218 * \param x1 = the start of the range (default: 0)
219 * \param x2 = the end of the range (default: the last pixel of the image)
220 * \return the position of the maximum
222 template <typename T
>
224 find_max1(const CImg
<T
> &img
, int x1
= 0, int x2
= -1)
230 T best
= img(best_x
);
234 if (img(x1
) > best
) {
243 /** Find maximum along a row of a two-dimensional image.
244 * \param img = the image to search the maximum from
245 * \param y = the row to analyse
246 * \param x1 = the start of the range (default: 0)
247 * \param x2 = the end of the range (default: the last pixel of the row)
248 * \return the location of the maximum
250 template <typename T
>
252 find_max_x(const CImg
<T
> &img
, int y
, int x1
= 0, int x2
= -1)
258 T best
= img(best_x
, y
);
262 if (img(x1
, y
) > best
) {
271 /** Paste an image to another image.
272 * \param src = the image to be pasted
273 * \param tgt = the target images
274 * \param x0 = target location
275 * \param y0 = target location
276 * \return reference to the target image
278 template <typename T
>
280 paste_image(const T
&src
, T
&tgt
, int x0
, int y0
)
282 for (int x
= 0; x
< (int)src
.width
; x
++) {
283 for (int y
= 0; y
< (int)src
.height
; y
++) {
284 tgt(x0
+ x
, y0
+ y
) = src(x
, y
);
290 /** Compute the sum of each column of the image.
291 * \param img = the source image
292 * \return a one-dimensional image containing the sum of each column
295 CImg
<T
> sum_y(const CImg
<T
> &img
)
297 CImg
<T
> result(img
.width
, 1);
298 for (int x
= 0; x
< (int)img
.width
; x
++) {
300 for (int y
= 0; y
< (int)img
.height
; y
++)
307 /** Set range of values in an one-dimensional image.
309 * \note It is safe to specify ranges outside the image. The range
310 * will be clipped appropriately.
312 * \param img = the target image
313 * \param x1 = the start of the range
314 * \param x2 = the end of the range
315 * \param value = the value to set
316 * \return a reference to the target image
318 template <typename T
>
320 set_range1(CImg
<T
> &img
, int x1
= 0, int x2
= INT_MAX
, T value
= 0)
324 if (x2
> (int)img
.width
- 1)
327 for (int x
= x1
; x
<= x2
; x
++)
333 /** Compute the maximum of each row.
335 * \warning The validity of the range is not checked.
337 * \param img = the source image
338 * \param x1 = the start of the range
339 * \param x2 = the end of the range (negative: use width of image)
340 * \return a one dimensional row image containing the maximums
342 template <typename T
>
344 max_x(const CImg
<T
> &img
, int x1
= 0, int x2
= -1)
346 CImg
<T
> result(img
.height
);
351 for (int y
= 0; y
< (int)img
.height
; y
++) {
353 for (int x
= x1
+ 1; x
<= x2
; x
++) {
363 /** Compute the sum of the pixels along a line
365 * \bug The float coordinates should be handled more elegantly so
366 * that the line is processed along the longer axis and the other
367 * coordinate is computed for each middle location.
369 * \warning Does not check the image boundaries.
370 * \param img = the source image
371 * \param line = the line to sum
372 * \return The sum of the pixel values along the line.
374 template <typename T
>
376 line_sum(CImg
<T
> &img
, const geom::Line
&line
)
378 // Check single point
379 if ((int)(line
.a
.x
+ 0.5) == (int)(line
.b
.x
+ 0.5) &&
380 (int)(line
.a
.y
+ 0.5) == (int)(line
.b
.y
+ 0.5))
381 return img((int)(line
.a
.x
+ 0.5), (int)(line
.b
.y
+ 0.5));
384 float dx
= line
.b
.x
- line
.a
.x
;
385 float dy
= line
.b
.y
- line
.a
.y
;
386 float div
= cimg::max(cimg::abs(dx
), cimg::abs(dy
));
390 // Add value to points along the line
392 for (int i
= 0; i
<= div
; i
++) {
393 int x
= (int)(line
.a
.x
+ i
* dx
+ 0.5);
394 int y
= (int)(line
.a
.y
+ i
* dy
+ 0.5);