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); 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   cc8compt
155       Connected 8-component labeling of a binary image.
156
157       Connected 8-component labeling of 0,1 image - i.e. find separate
158       segmented objects and fill object pixels with object number.
159       8-component labeling includes all neighboring pixels.  This is just a
160       front-end to ccNcompt.  See also "cc4compt".
161
162        $segmented = cc8compt( $image > $threshold );
163
164   cc4compt
165       Connected 4-component labeling of a binary image.
166
167       Connected 4-component labeling of 0,1 image - i.e. find separate
168       segmented objects and fill object pixels with object number.
169       4-component labling does not include the diagonal neighbors.  This is
170       just a front-end to ccNcompt.  See also "cc8compt".
171
172        $segmented = cc4compt( $image > $threshold );
173
174   ccNcompt
175         Signature: (a(m,n); int+ [o]b(m,n); int con)
176
177       Connected component labeling of a binary image.
178
179       Connected component labeling of 0,1 image - i.e. find separate
180       segmented objects and fill object pixels with object number.  See also
181       "cc4compt" and "cc8compt".
182
183       The connectivity parameter must be 4 or 8.
184
185        $segmented = ccNcompt( $image > $threshold, 4);
186
187        $segmented2 = ccNcompt( $image > $threshold, 8);
188
189       where the second parameter specifies the connectivity (4 or 8) of the
190       labeling.
191
192       ccNcompt ignores the bad-value flag of the input ndarrays.  It will set
193       the bad-value flag of all output ndarrays if the flag is set for any of
194       the input ndarrays.
195
196   polyfill
197       fill the area of the given polygon with the given colour.
198
199       This function works inplace, i.e. modifies "im".
200
201         polyfill($im,$ps,$colour,[\%options]);
202
203       The default method of determining which points lie inside of the
204       polygon used is not as strict as the method used in "pnpoly". Often, it
205       includes vertices and edge points. Set the "Method" option to change
206       this behaviour.
207
208       Method   -  Set the method used to determine which points lie in the
209       polygon.
210                   => Default - internal PDL algorithm
211                   => pnpoly  - use the "pnpoly" algorithm
212
213         # Make a convex 3x3 square of 1s in an image using the pnpoly algorithm
214         $ps = pdl([3,3],[3,6],[6,6],[6,3]);
215         polyfill($im,$ps,1,{'Method' =>'pnpoly'});
216
217   pnpoly
218       'points in a polygon' selection from a 2-D ndarray
219
220         $mask = $img->pnpoly($ps);
221
222         # Old style, do not use
223         $mask = pnpoly($x, $y, $px, $py);
224
225       For a closed polygon determined by the sequence of points in {$px,$py}
226       the output of pnpoly is a mask corresponding to whether or not each
227       coordinate (x,y) in the set of test points, {$x,$y}, is in the interior
228       of the polygon.  This is the 'points in a polygon' algorithm from
229       <http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html>
230       and vectorized for PDL by Karl Glazebrook.
231
232         # define a 3-sided polygon (a triangle)
233         $ps = pdl([3, 3], [20, 20], [34, 3]);
234
235         # $tri is 0 everywhere except for points in polygon interior
236         $tri = $img->pnpoly($ps);
237
238         With the second form, the x and y coordinates must also be specified.
239         B< I<THIS IS MAINTAINED FOR BACKWARD COMPATIBILITY ONLY> >.
240
241         $px = pdl( 3, 20, 34 );
242         $py = pdl( 3, 20,  3 );
243         $x = $img->xvals;      # get x pixel coords
244         $y = $img->yvals;      # get y pixel coords
245
246         # $tri is 0 everywhere except for points in polygon interior
247         $tri = pnpoly($x,$y,$px,$py);
248
249   polyfillv
250       return the (dataflowed) area of an image described by a polygon
251
252         polyfillv($im,$ps,[\%options]);
253
254       The default method of determining which points lie inside of the
255       polygon used is not as strict as the method used in "pnpoly". Often, it
256       includes vertices and edge points. Set the "Method" option to change
257       this behaviour.
258
259       Method   -  Set the method used to determine which points lie in the
260       polygon.
261                   => Default - internal PDL algorithm
262                   => pnpoly  - use the "pnpoly" algorithm
263
264         # increment intensity in area bounded by $poly using the pnpoly algorithm
265         $im->polyfillv($poly,{'Method'=>'pnpoly'})++; # legal in perl >= 5.6
266
267         # compute average intensity within area bounded by $poly using the default algorithm
268         $av = $im->polyfillv($poly)->avg;
269
270   rot2d
271         Signature: (im(m,n); float angle(); bg(); int aa(); [o] om(p,q))
272
273       rotate an image by given "angle"
274
275         # rotate by 10.5 degrees with antialiasing, set missing values to 7
276         $rot = $im->rot2d(10.5,7,1);
277
278       This function rotates an image through an "angle" between -90 and + 90
279       degrees. Uses/doesn't use antialiasing depending on the "aa" flag.
280       Pixels outside the rotated image are set to "bg".
281
282       Code modified from pnmrotate (Copyright Jef Poskanzer) with an
283       algorithm based on "A Fast Algorithm for General  Raster  Rotation"  by
284       Alan Paeth, Graphics Interface '86, pp. 77-81.
285
286       Use the "rotnewsz" function to find out about the dimension of the
287       newly created image
288
289         ($newcols,$newrows) = rotnewsz $oldn, $oldm, $angle;
290
291       PDL::Transform offers a more general interface to distortions,
292       including rotation, with various types of sampling; but rot2d is
293       faster.
294
295       rot2d ignores the bad-value flag of the input ndarrays.  It will set
296       the bad-value flag of all output ndarrays if the flag is set for any of
297       the input ndarrays.
298
299   bilin2d
300         Signature: (Int(n,m); O(q,p))
301
302       Bilinearly maps the first ndarray in the second. The interpolated
303       values are actually added to the second ndarray which is supposed to be
304       larger than the first one.
305
306       bilin2d ignores the bad-value flag of the input ndarrays.  It will set
307       the bad-value flag of all output ndarrays if the flag is set for any of
308       the input ndarrays.
309
310   rescale2d
311         Signature: (Int(m,n); O(p,q))
312
313       The first ndarray is rescaled to the dimensions of the second
314       (expanding or meaning values as needed) and then added to it in place.
315       Nothing useful is returned.
316
317       If you want photometric accuracy or automatic FITS header metadata
318       tracking, consider using PDL::Transform::map instead: it does these
319       things, at some speed penalty compared to rescale2d.
320
321       rescale2d ignores the bad-value flag of the input ndarrays.  It will
322       set the bad-value flag of all output ndarrays if the flag is set for
323       any of the input ndarrays.
324
325   fitwarp2d
326       Find the best-fit 2D polynomial to describe a coordinate
327       transformation.
328
329         ( $px, $py ) = fitwarp2d( $x, $y, $u, $v, $nf, { options } )
330
331       Given a set of points in the output plane ("$u,$v"), find the best-fit
332       (using singular-value decomposition) 2D polynomial to describe the
333       mapping back to the image plane ("$x,$y").  The order of the fit is
334       controlled by the $nf parameter (the maximum power of the polynomial is
335       "$nf - 1"), and you can restrict the terms to fit using the "FIT"
336       option.
337
338       $px and $py are "np" by "np" element ndarrays which describe a
339       polynomial mapping (of order "np-1") from the output "(u,v)" image to
340       the input "(x,y)" image:
341
342         x = sum(j=0,np-1) sum(i=0,np-1) px(i,j) * u^i * v^j
343         y = sum(j=0,np-1) sum(i=0,np-1) py(i,j) * u^i * v^j
344
345       The transformation is returned for the reverse direction (ie output to
346       input image) since that is what is required by the warp2d() routine.
347       The applywarp2d() routine can be used to convert a set of "$u,$v"
348       points given $px and $py.
349
350       Options:
351
352         FIT     - which terms to fit? default ones(byte,$nf,$nf)
353
354       FIT "FIT" allows you to restrict which terms of the polynomial to fit:
355           only those terms for which the FIT ndarray evaluates to true will
356           be evaluated.  If a 2D ndarray is sent in, then it is used for the
357           x and y polynomials; otherwise "$fit->slice(":,:,(0)")" will be
358           used for $px and "$fit->slice(":,:,(1)")" will be used for $py.
359
360       The number of points must be at least equal to the number of terms to
361       fit ("$nf*$nf" points for the default value of "FIT").
362
363         # points in original image
364         $x = pdl( 0,   0, 100, 100 );
365         $y = pdl( 0, 100, 100,   0 );
366         # get warped to these positions
367         $u = pdl( 10, 10, 90, 90 );
368         $v = pdl( 10, 90, 90, 10 );
369         #
370         # shift of origin + scale x/y axis only
371         $fit = byte( [ [1,1], [0,0] ], [ [1,0], [1,0] ] );
372         ( $px, $py ) = fitwarp2d( $x, $y, $u, $v, 2, { FIT => $fit } );
373         print "px = ${px}py = $py";
374         px =
375         [
376          [-12.5  1.25]
377          [    0     0]
378         ]
379         py =
380         [
381          [-12.5     0]
382          [ 1.25     0]
383         ]
384         #
385         # Compared to allowing all 4 terms
386         ( $px, $py ) = fitwarp2d( $x, $y, $u, $v, 2 );
387         print "px = ${px}py = $py";
388         px =
389         [
390          [         -12.5           1.25]
391          [  1.110223e-16 -1.1275703e-17]
392         ]
393         py =
394         [
395          [         -12.5  1.6653345e-16]
396          [          1.25 -5.8546917e-18]
397         ]
398
399         # A higher-degree polynomial should not affect the answer much, but
400         # will require more control points
401
402         $x = $x->glue(0,pdl(50,12.5, 37.5, 12.5, 37.5));
403         $y = $y->glue(0,pdl(50,12.5, 37.5, 37.5, 12.5));
404         $u = $u->glue(0,pdl(73,20,40,20,40));
405         $v = $v->glue(0,pdl(29,20,40,40,20));
406         ( $px3, $py3 ) = fitwarp2d( $x, $y, $u, $v, 3 );
407         print "px3 =${px3}py3 =$py3";
408         px3 =
409         [
410          [-6.4981162e+08       71034917     -726498.95]
411          [      49902244     -5415096.7      55945.388]
412          [    -807778.46      88457.191     -902.51612]
413         ]
414         py3 =
415         [
416          [-6.2732159e+08       68576392     -701354.77]
417          [      48175125     -5227679.8      54009.114]
418          [    -779821.18      85395.681     -871.27997]
419         ]
420
421         #This illustrates an important point about singular value
422         #decompositions that are used in fitwarp2d: like all SVDs, the
423         #rotation matrices are not unique, and so the $px and $py returned
424         #by fitwarp2d are not guaranteed to be the "simplest" solution.
425         #They do still work, though:
426
427         ($x3,$y3) = applywarp2d($px3,$py3,$u,$v);
428         print approx $x3,$x,1e-4;
429         [1 1 1 1 1 1 1 1 1]
430         print approx $y3,$y;
431         [1 1 1 1 1 1 1 1 1]
432
433   applywarp2d
434       Transform a set of points using a 2-D polynomial mapping
435
436         ( $x, $y ) = applywarp2d( $px, $py, $u, $v )
437
438       Convert a set of points (stored in 1D ndarrays "$u,$v") to "$x,$y"
439       using the 2-D polynomial with coefficients stored in $px and $py.  See
440       fitwarp2d() for more information on the format of $px and $py.
441
442   warp2d
443         Signature: (img(m,n); double px(np,np); double py(np,np); [o] warp(m,n); { options })
444
445       Warp a 2D image given a polynomial describing the reverse mapping.
446
447         $out = warp2d( $img, $px, $py, { options } );
448
449       Apply the polynomial transformation encoded in the $px and $py ndarrays
450       to warp the input image $img into the output image $out.
451
452       The format for the polynomial transformation is described in the
453       documentation for the fitwarp2d() routine.
454
455       At each point "x,y", the closest 16 pixel values are combined with an
456       interpolation kernel to calculate the value at "u,v".  The
457       interpolation is therefore done in the image, rather than Fourier,
458       domain.  By default, a "tanh" kernel is used, but this can be changed
459       using the "KERNEL" option discussed below (the choice of kernel depends
460       on the frequency content of the input image).
461
462       The routine is based on the "warping" command from the Eclipse data-
463       reduction package - see http://www.eso.org/eclipse/ - and for further
464       details on image resampling see Wolberg, G., "Digital Image Warping",
465       1990, IEEE Computer Society Press ISBN 0-8186-8944-7).
466
467       Currently the output image is the same size as the input one, which
468       means data will be lost if the transformation reduces the pixel scale.
469       This will (hopefully) be changed soon.
470
471         $img = rvals(byte,501,501);
472         imag $img, { JUSTIFY => 1 };
473         #
474         # use a not-particularly-obvious transformation:
475         #   x = -10 + 0.5 * $u - 0.1 * $v
476         #   y = -20 + $v - 0.002 * $u * $v
477         #
478         $px  = pdl( [ -10, 0.5 ], [ -0.1, 0 ] );
479         $py  = pdl( [ -20, 0 ], [ 1, 0.002 ] );
480         $wrp = warp2d( $img, $px, $py );
481         #
482         # see the warped image
483         imag $warp, { JUSTIFY => 1 };
484
485       The options are:
486
487         KERNEL - default value is tanh
488         NOVAL  - default value is 0
489
490       "KERNEL" is used to specify which interpolation kernel to use (to see
491       what these kernels look like, use the warp2d_kernel() routine).  The
492       options are:
493
494       tanh
495           Hyperbolic tangent: the approximation of an ideal box filter by the
496           product of symmetric tanh functions.
497
498       sinc
499           For a correctly sampled signal, the ideal filter in the fourier
500           domain is a rectangle, which produces a "sinc" interpolation kernel
501           in the spatial domain:
502
503             sinc(x) = sin(pi * x) / (pi * x)
504
505           However, it is not ideal for the "4x4" pixel region used here.
506
507       sinc2
508           This is the square of the sinc function.
509
510       lanczos
511           Although defined differently to the "tanh" kernel, the result is
512           very similar in the spatial domain.  The Lanczos function is
513           defined as
514
515             L(x) = sinc(x) * sinc(x/2)  if abs(x) < 2
516                  = 0                       otherwise
517
518       hann
519           This kernel is derived from the following function:
520
521             H(x) = a + (1-a) * cos(2*pi*x/(N-1))  if abs(x) < 0.5*(N-1)
522                  = 0                                 otherwise
523
524           with "a = 0.5" and N currently equal to 2001.
525
526       hamming
527           This kernel uses the same H(x) as the Hann filter, but with "a =
528           0.54".
529
530       "NOVAL" gives the value used to indicate that a pixel in the output
531       image does not map onto one in the input image.
532
533   warp2d_kernel
534       Return the specified kernel, as used by "warp2d"
535
536         ( $x, $k ) = warp2d_kernel( $name )
537
538       The valid values for $name are the same as the "KERNEL" option of
539       warp2d().
540
541         line warp2d_kernel( "hamming" );
542

AUTHORS

544       Copyright (C) Karl Glazebrook 1997 with additions by Robin Williams
545       (rjrw@ast.leeds.ac.uk), Tim Jeness (timj@jach.hawaii.edu), and Doug
546       Burke (burke@ifa.hawaii.edu).
547
548       All rights reserved. There is no warranty. You are allowed to
549       redistribute this software / documentation under certain conditions.
550       For details, see the file COPYING in the PDL distribution. If this file
551       is separated from the PDL distribution, the copyright notice should be
552       included in the file.
553
554
555
556perl v5.34.0                      2022-02-28                        Image2D(3)
Impressum