1Image2D(3)            User Contributed Perl Documentation           Image2D(3)
2
3
4

NAME

6       PDL::Image2D - Miscellaneous 2D image processing functions
7

DESCRIPTION

9       Miscellaneous 2D image processing functions - for want of anywhere else
10       to put them.
11

SYNOPSIS

13        use PDL::Image2D;
14

FUNCTIONS

16   conv2d
17         Signature: (a(m,n); kern(p,q); [o]b(m,n); int opt)
18
19       2D convolution of an array with a kernel (smoothing)
20
21       For large kernels, using a FFT routine, such as fftconvolve() in
22       "PDL::FFT", will be quicker.
23
24        $new = conv2d $old, $kernel, {OPTIONS}
25
26        $smoothed = conv2d $image, ones(3,3), {Boundary => Reflect}
27
28        Boundary - controls what values are assumed for the image when kernel
29                   crosses its edge:
30                   => Default   - periodic boundary conditions
31                                  (i.e. wrap around axis)
32                   => Reflect   - reflect at boundary
33                   => Truncate  - truncate at boundary
34                   => Replicate - repeat boundary pixel values
35
36       Unlike the FFT routines, conv2d is able to process bad values.
37
38   med2d
39         Signature: (a(m,n); kern(p,q); [o]b(m,n); double [t]tmp(pq); int opt)
40
41       2D median-convolution of an array with a kernel (smoothing)
42
43       Note: only points in the kernel >0 are included in the median, other
44       points are weighted by the kernel value (medianing lots of zeroes is
45       rather pointless)
46
47        $new = med2d $old, $kernel, {OPTIONS}
48
49        $smoothed = med2d $image, ones(3,3), {Boundary => Reflect}
50
51        Boundary - controls what values are assumed for the image when kernel
52                   crosses its edge:
53                   => Default   - periodic boundary conditions (i.e. wrap around axis)
54                   => Reflect   - reflect at boundary
55                   => Truncate  - truncate at boundary
56                   => Replicate - repeat boundary pixel values
57
58       Bad values are ignored in the calculation. If all elements within the
59       kernel are bad, the output is set bad.
60
61   med2df
62         Signature: (a(m,n); [o]b(m,n); int __p_size; int __q_size; int opt)
63
64       2D median-convolution of an array in a pxq window (smoothing)
65
66       Note: this routine does the median over all points in a rectangular
67             window and is not quite as flexible as "med2d" in this regard
68             but slightly faster instead
69
70        $new = med2df $old, $xwidth, $ywidth, {OPTIONS}
71
72        $smoothed = med2df $image, 3, 3, {Boundary => Reflect}
73
74        Boundary - controls what values are assumed for the image when kernel
75                   crosses its edge:
76                   => Default   - periodic boundary conditions (i.e. wrap around axis)
77                   => Reflect   - reflect at boundary
78                   => Truncate  - truncate at boundary
79                   => Replicate - repeat boundary pixel values
80
81       med2df does not process bad values.  It will set the bad-value flag of
82       all output ndarrays if the flag is set for any of the input ndarrays.
83
84   box2d
85         Signature: (a(n,m); [o] b(n,m); int wx; int wy; int edgezero)
86
87       fast 2D boxcar average
88
89         $smoothim = $im->box2d($wx,$wy,$edgezero=1);
90
91       The edgezero argument controls if edge is set to zero (edgezero=1) or
92       just keeps the original (unfiltered) values.
93
94       "box2d" should be updated to support similar edge options as "conv2d"
95       and "med2d" etc.
96
97       Boxcar averaging is a pretty crude way of filtering. For serious stuff
98       better filters are around (e.g., use "conv2d" with the appropriate
99       kernel). On the other hand it is fast and computational cost grows only
100       approximately linearly with window size.
101
102       box2d does not process bad values.  It will set the bad-value flag of
103       all output ndarrays if the flag is set for any of the input ndarrays.
104
105   patch2d
106         Signature: (a(m,n); int bad(m,n); [o]b(m,n))
107
108       patch bad pixels out of 2D images using a mask
109
110        $patched = patch2d $data, $bad;
111
112       $bad is a 2D mask array where 1=bad pixel 0=good pixel.  Pixels are
113       replaced by the average of their non-bad neighbours; if all neighbours
114       are bad, the original data value is copied across.
115
116       This routine does not handle bad values - use "patchbad2d" instead
117
118   patchbad2d
119         Signature: (a(m,n); [o]b(m,n))
120
121       patch bad pixels out of 2D images containing bad values
122
123        $patched = patchbad2d $data;
124
125       Pixels are replaced by the average of their non-bad neighbours; if all
126       neighbours are bad, the output is set bad.  If the input ndarray
127       contains no bad values, then a straight copy is performed (see
128       "patch2d").
129
130       patchbad2d handles bad values. The output ndarray may contain bad
131       values, depending on the pattern of bad values in the input ndarray.
132
133   max2d_ind
134         Signature: (a(m,n); [o]val(); int [o]x(); int[o]y())
135
136       Return value/position of maximum value in 2D image
137
138       Contributed by Tim Jeness
139
140       Bad values are excluded from the search. If all pixels are bad then the
141       output is set bad.
142
143   centroid2d
144         Signature: (im(m,n); x(); y(); box(); [o]xcen(); [o]ycen())
145
146       Refine a list of object positions in 2D image by centroiding in a box
147
148       $box is the full-width of the box, i.e. the window is "+/- $box/2".
149
150       Bad pixels are excluded from the centroid calculation. If all elements
151       are bad (or the pixel sum is 0 - but why would you be centroiding
152       something with negatives in...) then the output values are set bad.
153
154   crop
155       Return bounding box of given mask in an "indx" ndarray, so it can
156       broadcast.  Use other operations (such as "isgood" in PDL::Bad, or
157       "eqvec" in PDL::Primitive with a colour vector) to create a mask
158       suitable for your application.
159
160         $x1x2y1y2 = crop($image);
161
162   cc8compt
163       Connected 8-component labeling of a binary image.
164
165       Connected 8-component labeling of 0,1 image - i.e. find separate
166       segmented objects and fill object pixels with object number.
167       8-component labeling includes all neighboring pixels.  This is just a
168       front-end to ccNcompt.  See also "cc4compt".
169
170        $segmented = cc8compt( $image > $threshold );
171
172   cc4compt
173       Connected 4-component labeling of a binary image.
174
175       Connected 4-component labeling of 0,1 image - i.e. find separate
176       segmented objects and fill object pixels with object number.
177       4-component labling does not include the diagonal neighbors.  This is
178       just a front-end to ccNcompt.  See also "cc8compt".
179
180        $segmented = cc4compt( $image > $threshold );
181
182   ccNcompt
183         Signature: (a(m,n); int+ [o]b(m,n); int con)
184
185       Connected component labeling of a binary image.
186
187       Connected component labeling of 0,1 image - i.e. find separate
188       segmented objects and fill object pixels with object number.  See also
189       "cc4compt" and "cc8compt".
190
191       The connectivity parameter must be 4 or 8.
192
193        $segmented = ccNcompt( $image > $threshold, 4);
194
195        $segmented2 = ccNcompt( $image > $threshold, 8);
196
197       where the second parameter specifies the connectivity (4 or 8) of the
198       labeling.
199
200       ccNcompt ignores the bad-value flag of the input ndarrays.  It will set
201       the bad-value flag of all output ndarrays if the flag is set for any of
202       the input ndarrays.
203
204   polyfill
205       fill the area of the given polygon with the given colour.
206
207       This function works inplace, i.e. modifies "im".
208
209         polyfill($im,$ps,$colour,[\%options]);
210
211       The default method of determining which points lie inside of the
212       polygon used is not as strict as the method used in "pnpoly". Often, it
213       includes vertices and edge points. Set the "Method" option to change
214       this behaviour.
215
216       Method   -  Set the method used to determine which points lie in the
217       polygon.
218                   => Default - internal PDL algorithm
219                   => pnpoly  - use the "pnpoly" algorithm
220
221         # Make a convex 3x3 square of 1s in an image using the pnpoly algorithm
222         $ps = pdl([3,3],[3,6],[6,6],[6,3]);
223         polyfill($im,$ps,1,{'Method' =>'pnpoly'});
224
225   pnpoly
226       'points in a polygon' selection from a 2-D ndarray
227
228         $mask = $img->pnpoly($ps);
229
230         # Old style, do not use
231         $mask = pnpoly($x, $y, $px, $py);
232
233       For a closed polygon determined by the sequence of points in {$px,$py}
234       the output of pnpoly is a mask corresponding to whether or not each
235       coordinate (x,y) in the set of test points, {$x,$y}, is in the interior
236       of the polygon.  This is the 'points in a polygon' algorithm from
237       <http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html>
238       and vectorized for PDL by Karl Glazebrook.
239
240         # define a 3-sided polygon (a triangle)
241         $ps = pdl([3, 3], [20, 20], [34, 3]);
242
243         # $tri is 0 everywhere except for points in polygon interior
244         $tri = $img->pnpoly($ps);
245
246         With the second form, the x and y coordinates must also be specified.
247         B< I<THIS IS MAINTAINED FOR BACKWARD COMPATIBILITY ONLY> >.
248
249         $px = pdl( 3, 20, 34 );
250         $py = pdl( 3, 20,  3 );
251         $x = $img->xvals;      # get x pixel coords
252         $y = $img->yvals;      # get y pixel coords
253
254         # $tri is 0 everywhere except for points in polygon interior
255         $tri = pnpoly($x,$y,$px,$py);
256
257   polyfillv
258       return the (dataflowed) area of an image described by a polygon
259
260         polyfillv($im,$ps,[\%options]);
261
262       The default method of determining which points lie inside of the
263       polygon used is not as strict as the method used in "pnpoly". Often, it
264       includes vertices and edge points. Set the "Method" option to change
265       this behaviour.
266
267       Method   -  Set the method used to determine which points lie in the
268       polygon.
269                   => Default - internal PDL algorithm
270                   => pnpoly  - use the "pnpoly" algorithm
271
272         # increment intensity in area bounded by $poly using the pnpoly algorithm
273         $im->polyfillv($poly,{'Method'=>'pnpoly'})++; # legal in perl >= 5.6
274
275         # compute average intensity within area bounded by $poly using the default algorithm
276         $av = $im->polyfillv($poly)->avg;
277
278   rot2d
279         Signature: (im(m,n); float angle(); bg(); int aa(); [o] om(p,q))
280
281       rotate an image by given "angle"
282
283         # rotate by 10.5 degrees with antialiasing, set missing values to 7
284         $rot = $im->rot2d(10.5,7,1);
285
286       This function rotates an image through an "angle" between -90 and + 90
287       degrees. Uses/doesn't use antialiasing depending on the "aa" flag.
288       Pixels outside the rotated image are set to "bg".
289
290       Code modified from pnmrotate (Copyright Jef Poskanzer) with an
291       algorithm based on "A Fast Algorithm for General  Raster  Rotation"  by
292       Alan Paeth, Graphics Interface '86, pp. 77-81.
293
294       Use the "rotnewsz" function to find out about the dimension of the
295       newly created image
296
297         ($newcols,$newrows) = rotnewsz $oldn, $oldm, $angle;
298
299       PDL::Transform offers a more general interface to distortions,
300       including rotation, with various types of sampling; but rot2d is
301       faster.
302
303       rot2d ignores the bad-value flag of the input ndarrays.  It will set
304       the bad-value flag of all output ndarrays if the flag is set for any of
305       the input ndarrays.
306
307   bilin2d
308         Signature: (Int(n,m); O(q,p))
309
310       Bilinearly maps the first ndarray in the second. The interpolated
311       values are actually added to the second ndarray which is supposed to be
312       larger than the first one.
313
314       bilin2d ignores the bad-value flag of the input ndarrays.  It will set
315       the bad-value flag of all output ndarrays if the flag is set for any of
316       the input ndarrays.
317
318   rescale2d
319         Signature: (Int(m,n); O(p,q))
320
321       The first ndarray is rescaled to the dimensions of the second
322       (expanding or meaning values as needed) and then added to it in place.
323       Nothing useful is returned.
324
325       If you want photometric accuracy or automatic FITS header metadata
326       tracking, consider using PDL::Transform::map instead: it does these
327       things, at some speed penalty compared to rescale2d.
328
329       rescale2d ignores the bad-value flag of the input ndarrays.  It will
330       set the bad-value flag of all output ndarrays if the flag is set for
331       any of the input ndarrays.
332
333   fitwarp2d
334       Find the best-fit 2D polynomial to describe a coordinate
335       transformation.
336
337         ( $px, $py ) = fitwarp2d( $x, $y, $u, $v, $nf, { options } )
338
339       Given a set of points in the output plane ("$u,$v"), find the best-fit
340       (using singular-value decomposition) 2D polynomial to describe the
341       mapping back to the image plane ("$x,$y").  The order of the fit is
342       controlled by the $nf parameter (the maximum power of the polynomial is
343       "$nf - 1"), and you can restrict the terms to fit using the "FIT"
344       option.
345
346       $px and $py are "np" by "np" element ndarrays which describe a
347       polynomial mapping (of order "np-1") from the output "(u,v)" image to
348       the input "(x,y)" image:
349
350         x = sum(j=0,np-1) sum(i=0,np-1) px(i,j) * u^i * v^j
351         y = sum(j=0,np-1) sum(i=0,np-1) py(i,j) * u^i * v^j
352
353       The transformation is returned for the reverse direction (ie output to
354       input image) since that is what is required by the warp2d() routine.
355       The applywarp2d() routine can be used to convert a set of "$u,$v"
356       points given $px and $py.
357
358       Options:
359
360         FIT     - which terms to fit? default ones(byte,$nf,$nf)
361
362       FIT "FIT" allows you to restrict which terms of the polynomial to fit:
363           only those terms for which the FIT ndarray evaluates to true will
364           be evaluated.  If a 2D ndarray is sent in, then it is used for the
365           x and y polynomials; otherwise "$fit->slice(":,:,(0)")" will be
366           used for $px and "$fit->slice(":,:,(1)")" will be used for $py.
367
368       The number of points must be at least equal to the number of terms to
369       fit ("$nf*$nf" points for the default value of "FIT").
370
371         # points in original image
372         $x = pdl( 0,   0, 100, 100 );
373         $y = pdl( 0, 100, 100,   0 );
374         # get warped to these positions
375         $u = pdl( 10, 10, 90, 90 );
376         $v = pdl( 10, 90, 90, 10 );
377         #
378         # shift of origin + scale x/y axis only
379         $fit = byte( [ [1,1], [0,0] ], [ [1,0], [1,0] ] );
380         ( $px, $py ) = fitwarp2d( $x, $y, $u, $v, 2, { FIT => $fit } );
381         print "px = ${px}py = $py";
382         px =
383         [
384          [-12.5  1.25]
385          [    0     0]
386         ]
387         py =
388         [
389          [-12.5     0]
390          [ 1.25     0]
391         ]
392         #
393         # Compared to allowing all 4 terms
394         ( $px, $py ) = fitwarp2d( $x, $y, $u, $v, 2 );
395         print "px = ${px}py = $py";
396         px =
397         [
398          [         -12.5           1.25]
399          [  1.110223e-16 -1.1275703e-17]
400         ]
401         py =
402         [
403          [         -12.5  1.6653345e-16]
404          [          1.25 -5.8546917e-18]
405         ]
406
407         # A higher-degree polynomial should not affect the answer much, but
408         # will require more control points
409
410         $x = $x->glue(0,pdl(50,12.5, 37.5, 12.5, 37.5));
411         $y = $y->glue(0,pdl(50,12.5, 37.5, 37.5, 12.5));
412         $u = $u->glue(0,pdl(73,20,40,20,40));
413         $v = $v->glue(0,pdl(29,20,40,40,20));
414         ( $px3, $py3 ) = fitwarp2d( $x, $y, $u, $v, 3 );
415         print "px3 =${px3}py3 =$py3";
416         px3 =
417         [
418          [-6.4981162e+08       71034917     -726498.95]
419          [      49902244     -5415096.7      55945.388]
420          [    -807778.46      88457.191     -902.51612]
421         ]
422         py3 =
423         [
424          [-6.2732159e+08       68576392     -701354.77]
425          [      48175125     -5227679.8      54009.114]
426          [    -779821.18      85395.681     -871.27997]
427         ]
428
429         #This illustrates an important point about singular value
430         #decompositions that are used in fitwarp2d: like all SVDs, the
431         #rotation matrices are not unique, and so the $px and $py returned
432         #by fitwarp2d are not guaranteed to be the "simplest" solution.
433         #They do still work, though:
434
435         ($x3,$y3) = applywarp2d($px3,$py3,$u,$v);
436         print approx $x3,$x,1e-4;
437         [1 1 1 1 1 1 1 1 1]
438         print approx $y3,$y;
439         [1 1 1 1 1 1 1 1 1]
440
441   applywarp2d
442       Transform a set of points using a 2-D polynomial mapping
443
444         ( $x, $y ) = applywarp2d( $px, $py, $u, $v )
445
446       Convert a set of points (stored in 1D ndarrays "$u,$v") to "$x,$y"
447       using the 2-D polynomial with coefficients stored in $px and $py.  See
448       fitwarp2d() for more information on the format of $px and $py.
449
450   warp2d
451         Signature: (img(m,n); double px(np,np); double py(np,np); [o] warp(m,n); { options })
452
453       Warp a 2D image given a polynomial describing the reverse mapping.
454
455         $out = warp2d( $img, $px, $py, { options } );
456
457       Apply the polynomial transformation encoded in the $px and $py ndarrays
458       to warp the input image $img into the output image $out.
459
460       The format for the polynomial transformation is described in the
461       documentation for the fitwarp2d() routine.
462
463       At each point "x,y", the closest 16 pixel values are combined with an
464       interpolation kernel to calculate the value at "u,v".  The
465       interpolation is therefore done in the image, rather than Fourier,
466       domain.  By default, a "tanh" kernel is used, but this can be changed
467       using the "KERNEL" option discussed below (the choice of kernel depends
468       on the frequency content of the input image).
469
470       The routine is based on the "warping" command from the Eclipse data-
471       reduction package - see http://www.eso.org/eclipse/ - and for further
472       details on image resampling see Wolberg, G., "Digital Image Warping",
473       1990, IEEE Computer Society Press ISBN 0-8186-8944-7).
474
475       Currently the output image is the same size as the input one, which
476       means data will be lost if the transformation reduces the pixel scale.
477       This will (hopefully) be changed soon.
478
479         $img = rvals(byte,501,501);
480         imag $img, { JUSTIFY => 1 };
481         #
482         # use a not-particularly-obvious transformation:
483         #   x = -10 + 0.5 * $u - 0.1 * $v
484         #   y = -20 + $v - 0.002 * $u * $v
485         #
486         $px  = pdl( [ -10, 0.5 ], [ -0.1, 0 ] );
487         $py  = pdl( [ -20, 0 ], [ 1, 0.002 ] );
488         $wrp = warp2d( $img, $px, $py );
489         #
490         # see the warped image
491         imag $warp, { JUSTIFY => 1 };
492
493       The options are:
494
495         KERNEL - default value is tanh
496         NOVAL  - default value is 0
497
498       "KERNEL" is used to specify which interpolation kernel to use (to see
499       what these kernels look like, use the warp2d_kernel() routine).  The
500       options are:
501
502       tanh
503           Hyperbolic tangent: the approximation of an ideal box filter by the
504           product of symmetric tanh functions.
505
506       sinc
507           For a correctly sampled signal, the ideal filter in the fourier
508           domain is a rectangle, which produces a "sinc" interpolation kernel
509           in the spatial domain:
510
511             sinc(x) = sin(pi * x) / (pi * x)
512
513           However, it is not ideal for the "4x4" pixel region used here.
514
515       sinc2
516           This is the square of the sinc function.
517
518       lanczos
519           Although defined differently to the "tanh" kernel, the result is
520           very similar in the spatial domain.  The Lanczos function is
521           defined as
522
523             L(x) = sinc(x) * sinc(x/2)  if abs(x) < 2
524                  = 0                       otherwise
525
526       hann
527           This kernel is derived from the following function:
528
529             H(x) = a + (1-a) * cos(2*pi*x/(N-1))  if abs(x) < 0.5*(N-1)
530                  = 0                                 otherwise
531
532           with "a = 0.5" and N currently equal to 2001.
533
534       hamming
535           This kernel uses the same H(x) as the Hann filter, but with "a =
536           0.54".
537
538       "NOVAL" gives the value used to indicate that a pixel in the output
539       image does not map onto one in the input image.
540
541   warp2d_kernel
542       Return the specified kernel, as used by "warp2d"
543
544         ( $x, $k ) = warp2d_kernel( $name )
545
546       The valid values for $name are the same as the "KERNEL" option of
547       warp2d().
548
549         line warp2d_kernel( "hamming" );
550

AUTHORS

552       Copyright (C) Karl Glazebrook 1997 with additions by Robin Williams
553       (rjrw@ast.leeds.ac.uk), Tim Jeness (timj@jach.hawaii.edu), and Doug
554       Burke (burke@ifa.hawaii.edu).
555
556       All rights reserved. There is no warranty. You are allowed to
557       redistribute this software / documentation under certain conditions.
558       For details, see the file COPYING in the PDL distribution. If this file
559       is separated from the PDL distribution, the copyright notice should be
560       included in the file.
561
562
563
564perl v5.36.0                      2022-07-22                        Image2D(3)
Impressum