1 /** \file
2  * \brief Image Statistics and Analysis
3  *
4  * See Copyright Notice in im_lib.h
5  */
6 module im.im_process_ana;
7 
8 version(IM) :
9 
10 import core.stdc.config : c_ulong;
11 import im.im_image : imImage;
12 
13 //version(DigitalMars) version(Windows) { pragma(lib, "im.lib"); } // required anyway
14 
15 extern(C) @nogc nothrow :
16 
17 
18 /** \defgroup stats Image Statistics
19  * \par
20  * Operations to calculate some statistics over images.
21  * \par
22  * See \ref im_process_ana.h
23  * \ingroup process */
24 
25 /** Calculates the RMS error between two images (Root Mean Square Error).
26  *
27  * \verbatim im.CalcRMSError(image1: imImage, image2: imImage) -> rms: number [in Lua 5] \endverbatim
28  * \ingroup stats */
29 float imCalcRMSError(const(imImage)* image1, const(imImage)* image2);
30 
31 /** Calculates the SNR of an image and its noise (Signal Noise Ratio).
32  *
33  * \verbatim im.CalcSNR(src_image: imImage, noise_image: imImage) -> snr: number [in Lua 5] \endverbatim
34  * \ingroup stats */
35 float imCalcSNR(const(imImage)* src_image, const(imImage)* noise_image);
36 
37 /** Count the number of different colors in an image. \n
38  * Image must be IM_BYTE, but can has all color spaces except IM_CMYK.
39  * Data type can be also IM_SHORT or IM_USHORT if color space is IM_GRAY, IM_BINARY or IM_MAP.
40  * Not using OpenMP when enabled, when color space depth is greater than 1.
41  *
42  * \verbatim im.CalcCountColors(image: imImage) -> count: number [in Lua 5] \endverbatim
43  * \ingroup stats */
44 c_ulong imCalcCountColors(const(imImage)* image);
45 
46 /** Calculates the gray histogram of an image. \n
47  * Image must be (IM_BYTE, IM_SHORT or IM_USHORT)/(IM_RGB, IM_GRAY, IM_BINARY or IM_MAP). \n
48  * If the image is IM_RGB then the histogram of the luma component is calculated. \n
49  * Histogram is always 256 or 65536 positions long. \n
50  * When cumulative is different from zero it calculates the cumulative histogram.
51  *
52  * \verbatim im.CalcGrayHistogram(image: imImage, cumulative: boolean) -> histo: table of numbers [in Lua 5] \endverbatim
53  * \ingroup stats */
54 void imCalcGrayHistogram(const(imImage)* image, c_ulong* histo, int cumulative);
55 
56 /** Calculates the histogram of an image plane. \n
57  * Image can be IM_BYTE, IM_SHORT or IM_USHORT. \n
58  * Histogram is always 256 or 65536 positions long. \n
59  * Where plane is the depth plane to calculate the histogram. \n
60  * When cumulative is different from zero it calculates the cumulative histogram.
61  *
62  * \verbatim im.CalcHistogram(image: imImage, plane: number, cumulative: boolean) -> histo: table of numbers [in Lua 5] \endverbatim
63  * The returned table is zero indexed.
64  * \ingroup stats */
65 void imCalcHistogram(const(imImage)* image, c_ulong* histo, int plane, int cumulative);
66 
67 /** Calculates the histogram of a IM_BYTE data. \n
68  * Histogram is always 256 positions long. \n
69  * When cumulative is different from zero it calculates the cumulative histogram.
70  * Not available in Lua.
71  * \ingroup stats */
72 void imCalcByteHistogram(const(ubyte)* data, int count, c_ulong* histo, int cumulative);
73 
74 /** Calculates the histogram of a IM_USHORT data. \n
75  * Histogram is always 65536 positions long. \n
76  * When cumulative is different from zero it calculates the cumulative histogram. \n
77  * Not available in Lua.
78  * \ingroup stats */
79 void imCalcUShortHistogram(const(ushort)* data, int count, c_ulong* histo, int cumulative);
80 
81 /** Calculates the histogram of a IM_SHORT data. \n
82  * Histogram is always 65536 positions long. \n
83  * Zero is located at 32768 index. \n
84  * When cumulative is different from zero it calculates the cumulative histogram. \n
85  * Not available in Lua.
86  * \ingroup stats */
87 void imCalcShortHistogram(const(short)* data, int count, c_ulong* histo, int cumulative);
88 
89 /** Alocates an histogram data based on the image data type. \n
90  * Data type can be IM_BYTE, IM_SHORT or IM_USHORT. \n
91  * Not available in Lua.
92  * \ingroup stats */
93 c_ulong* imHistogramNew(int data_type, int* hcount);
94 
95 /** Releases the histogram data. \n
96  * Not available in Lua.
97  * \ingroup stats */
98 void imHistogramRelease(c_ulong* histo);
99 
100 /** Short data type stores the histogram values of negative indices starting at 0.
101  * So the real level is obtained by shifting the zero based index. \n
102  * Not available in Lua.
103  * \ingroup stats */
104 int imHistogramShift(int data_type);
105 
106 /** Returns the histogram size based on the image data type. \n
107  * Not available in Lua.
108  * \ingroup stats */
109 int imHistogramCount(int data_type);
110 
111 
112 /** \brief Numerical Statistics Structure
113  * \ingroup stats */
114 struct imStats // typedef struct _imStats imStats
115 {
116   float max;                /**< Maximum value              */
117   float min;                /**< Minimum value              */
118   c_ulong positive;   /**< Number of Positive Values  */
119   c_ulong negative;   /**< Number of Negative Values  */
120   c_ulong zeros;      /**< Number of Zeros            */
121   float mean;               /**< Mean                       */
122   float stddev;             /**< Standard Deviation         */
123 }
124 
125 /** Calculates the statistics about the image data. \n
126  * There is one stats for each depth plane. For ex: stats[0]=red stats, stats[0]=green stats, ... \n
127  * Supports all data types except complex. \n
128  *
129  * \verbatim im.CalcImageStatistics(image: imImage) -> stats: table [in Lua 5] \endverbatim
130  * Table contains the following fields: max, min, positive, negative, zeros, mean, stddev. 
131  * If image depth > 1 then table contains several tables with the previous fields, one for each plane,
132  * starting at 0.
133  * The same as the \ref imStats structure.
134  * \ingroup stats */
135 void imCalcImageStatistics(const(imImage)* image, imStats* stats);
136 
137 /** Calculates the statistics about the image histogram data.\n
138  * There is one stats for each depth plane. For ex: stats[0]=red stats, stats[0]=green stats, ... \n
139  * Only IM_BYTE, IM_SHORT and IM_USHORT images are supported.
140  *
141  * \verbatim im.CalcHistogramStatistics(image: imImage) -> stats: table [in Lua 5] \endverbatim
142  * \ingroup stats */
143 void imCalcHistogramStatistics(const(imImage)* image, imStats* stats);
144 
145 /** Calculates some extra statistics about the image histogram data.\n
146  * There is one stats for each depth plane. \n
147  * Only IM_BYTE, IM_SHORT and IM_USHORT images are supported. \n
148  * mode will be -1 if more than one max is found.
149  *
150  * \verbatim im.CalcHistoImageStatistics(image: imImage) -> median: number, mode: number [in Lua 5] \endverbatim
151  * \ingroup stats */
152 void imCalcHistoImageStatistics(const(imImage)* image, int* median, int* mode);
153 
154 /** Calculates the minimum and maximum levels
155  * ignoring a given percentage of the histogram count.\n
156  * Used by \ref imProcessExpandHistogram. \n
157  * Only IM_BYTE, IM_SHORT and IM_USHORT images are supported. \n
158  *
159  * \verbatim im.CalcPercentMinMax(image: imImage, percent: number, ignore_zero: boolean) -> min, max: number [in Lua 5] \endverbatim
160  * \ingroup stats */
161 void imCalcPercentMinMax(const(imImage)* image, float percent, int ignore_zero, int* min, int* max);
162 
163 
164 /** \defgroup analyze Image Analysis
165  * \par
166  * See \ref im_process_ana.h
167  * \ingroup process */
168 
169 /** Find white regions in binary image. \n
170  * Result is IM_GRAY/IM_USHORT type. Regions can be 4 connected or 8 connected. \n
171  * Returns the number of regions found. Background is marked as 0. \n
172  * Regions touching the border are considered only if touch_border=1.
173  * Not using OpenMP when enabled.
174  *
175  * \verbatim im.AnalyzeFindRegions(src_image: imImage, dst_image: imImage, connect: number, touch_border: boolean) -> count: number [in Lua 5] \endverbatim
176  * \verbatim im.AnalyzeFindRegionsNew(image: imImage, connect: number, touch_border: boolean) -> count: number, new_image: imImage [in Lua 5] \endverbatim
177  * \ingroup analyze */
178 int imAnalyzeFindRegions(const(imImage)* src_image, imImage* dst_image, int connect, int touch_border);
179 
180 /** Measure the actual area of all regions. Holes are not included. \n
181  * This is the number of pixels of each region. \n
182  * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n
183  * area has size the number of regions.
184  *
185  * \verbatim im.AnalyzeMeasureArea(image: imImage, [region_count: number]) -> area: table of numbers [in Lua 5] \endverbatim
186  * The returned table is zero indexed.
187  * \ingroup analyze */
188 void imAnalyzeMeasureArea(const(imImage)* image, int* area, int region_count);
189 
190 /** Measure the polygonal area limited by the perimeter line of all regions. Holes are not included. \n
191  * Notice that some regions may have polygonal area zero. \n
192  * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n
193  * perimarea has size the number of regions.
194  *
195  * \verbatim im.AnalyzeMeasurePerimArea(image: imImage, [region_count: number]) -> perimarea: table of numbers [in Lua 5] \endverbatim
196  * The returned table is zero indexed.
197  * \ingroup analyze */
198 void imAnalyzeMeasurePerimArea(const(imImage)* image, float* perimarea, int region_count);
199 
200 /** Calculate the centroid position of all regions. Holes are not included. \n
201  * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n
202  * area, cx and cy have size the number of regions. If area is NULL will be internally calculated.
203  *
204  * \verbatim im.AnalyzeMeasureCentroid(image: imImage, [area: table of numbers], [region_count: number]) -> cx: table of numbers, cy: table of numbers [in Lua 5] \endverbatim
205  * The returned tables are zero indexed.
206  * \ingroup analyze */
207 void imAnalyzeMeasureCentroid(const(imImage)* image, const(int)* area, int region_count, float* cx, float* cy);
208 
209 /** Calculate the principal major axis slope of all regions. \n
210  * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n
211  * data has size the number of regions. If area or centroid are NULL will be internally calculated. \n
212  * Principal (major and minor) axes are defined to be those axes that pass through the
213  * centroid, about which the moment of inertia of the region is, respectively maximal or minimal.
214  * Partially using OpenMP when enabled.
215  *
216  * \verbatim im.AnalyzeMeasurePrincipalAxis(image: imImage, [area: table of numbers], [cx: table of numbers], [cy: table of numbers], [region_count: number])
217                               -> major_slope: table of numbers, major_length: table of numbers, minor_slope: table of numbers, minor_length: table of numbers [in Lua 5] \endverbatim
218  * The returned tables are zero indexed.
219  * \ingroup analyze */
220 void imAnalyzeMeasurePrincipalAxis(const(imImage)* image, const(int)* area, const(float)* cx, const(float)* cy,
221                                    const int region_count, float* major_slope, float* major_length,
222                                                            float* minor_slope, float* minor_length);
223 
224 /** Measure the number of holes of all regions. Optionally computes the holes area and holes perimeter of all regions. \n
225  * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n
226  * count, area and perim has size the number of regions, if some is NULL it will be not calculated.
227  * Not using OpenMP when enabled.
228  *
229  * \verbatim im.AnalyzeMeasureHoles(image: imImage, connect: number, [region_count: number]) -> holes_count: number, holes_area: table of numbers, holes_perim: table of numbers [in Lua 5] \endverbatim
230  * The returned tables are zero indexed.
231  * \ingroup analyze */
232 void imAnalyzeMeasureHoles(const(imImage)* image, int connect, int region_count, int* holes_count, int* holes_area, float* holes_perim);
233 
234 /** Measure the total perimeter of all regions (external and internal). \n
235  * Source image is IM_GRAY/IM_USHORT type (the result of imAnalyzeFindRegions). \n
236  * It uses a half-pixel inter distance for 8 neighbors in a perimeter of a 4 connected region. \n
237  * This function can also be used to measure line length. \n
238  * perim has size the number of regions.
239  *
240  * \verbatim im.AnalyzeMeasurePerimeter(image: imImage) -> perim: table of numbers [in Lua 5] \endverbatim
241  * \ingroup analyze */
242 void imAnalyzeMeasurePerimeter(const(imImage)* image, float* perim, int region_count);
243 
244 /** Isolates the perimeter line of gray integer images. Background is defined as being black (0). \n
245  * It just checks if at least one of the 4 connected neighbors is non zero. Image borders are extended with zeros.
246  *
247  * \verbatim im.ProcessPerimeterLine(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim
248  * \verbatim im.ProcessPerimeterLineNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim
249  * \ingroup analyze */
250 void imProcessPerimeterLine(const(imImage)* src_image, imImage* dst_image);
251 
252 /** Eliminates regions that have area size outside or inside the given interval. \n
253  * Source and target are a binary images. Regions can be 4 connected or 8 connected. \n
254  * Can be done in-place. end_size can be zero to indicate no upper limit or an area with width*height size. \n
255  * When searching inside the region the limits are inclusive (<= size >=), when searching outside the limits are exclusive (> size <).
256  *
257  * \verbatim im.ProcessRemoveByArea(src_image: imImage, dst_image: imImage, connect: number, start_size: number, end_size: number, inside: boolean) [in Lua 5] \endverbatim
258  * \verbatim im.ProcessRemoveByAreaNew(image: imImage, connect: number, start_size: number, end_size: number, inside: boolean) -> new_image: imImage [in Lua 5] \endverbatim
259  * \ingroup analyze */
260 void imProcessRemoveByArea(const(imImage)* src_image, imImage* dst_image, int connect, int start_size, int end_size, int inside);
261 
262 /** Fill holes inside white regions. \n
263  * Source and target are a binary images. Regions can be 4 connected or 8 connected. \n
264  * Can be done in-place.
265  *
266  * \verbatim im.ProcessFillHoles(src_image: imImage, dst_image: imImage, connect: number) [in Lua 5] \endverbatim
267  * \verbatim im.ProcessFillHolesNew(image: imImage, connect: number) -> new_image: imImage [in Lua 5] \endverbatim
268  * \ingroup analyze */
269 void imProcessFillHoles(const(imImage)* src_image, imImage* dst_image, int connect);