1 /*
2 Copyright (c) 2019 Ferhat Kurtulmuş
3 Boost Software License - Version 1.0 - August 17th, 2003
4 Permission is hereby granted, free of charge, to any person or organization
5 obtaining a copy of the software and accompanying documentation covered by
6 this license (the "Software") to use, reproduce, display, distribute,
7 execute, and transmit the Software, and to prepare derivative works of the
8 Software, and to permit third-parties to whom the Software is furnished to
9 do so, all subject to the following:
10 The copyright notices in the Software and this entire statement, including
11 the above license grant, this restriction and the following disclaimer,
12 must be included in all copies of the Software, in whole or in part, and
13 all derivative works of the Software, unless such copies or derivative
14 works are solely in the form of machine-executable object code generated by
15 a source language processor.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
19 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
20 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
21 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24 
25 module opencvd.imgproc;
26 
27 import std.stdio;
28 import std..string;
29 import std.typecons;
30 import std.conv;
31 import std.math: PI;
32 import core.stdc.stdlib;
33 
34 import opencvd.cvcore;
35 
36 private extern (C) @nogc nothrow {
37 
38     double ArcLength(Contour curve, bool is_closed);
39     Contour ApproxPolyDP(Contour curve, double epsilon, bool closed);
40     void CvtColor(Mat src, Mat dst, int code);
41     void EqualizeHist(Mat src, Mat dst);
42     void CalcHist(Mats mats, IntVector chans, Mat mask, Mat hist, IntVector sz, FloatVector rng, bool acc);
43     void CalcHist1(Mat dst, int nimages, int* channels,
44         Mat mask, Mat hist, int dims, int* histSize, const float** ranges, bool uniform, bool accumulate);
45     void CalcHist2(Mat dst, Mat mask, Mat hist, int* histSize);
46     void ConvexHull(Contour points, Mat hull, bool clockwise, bool returnPoints);
47     Points ConvexHull2(Contour points, bool clockwise);
48     IntVector ConvexHull3(Contour points, bool clockwise);
49     void ConvexityDefects(Contour points, Mat hull, Mat result);
50     void BilateralFilter(Mat src, Mat dst, int d, double sc, double ss);
51     void Blur(Mat src, Mat dst, Size ps);
52     void BoxFilter(Mat src, Mat dst, int ddepth, Size ps);
53     void SqBoxFilter(Mat src, Mat dst, int ddepth, Size ps);
54     void Dilate(Mat src, Mat dst, Mat kernel);
55     void Dilate2(Mat src, Mat dst, Mat kernel, Point anchor, int iterations);
56     void Erode(Mat src, Mat dst, Mat kernel);
57     void Erode2(Mat src, Mat dst, Mat kernel, Point anchor, int iterations);
58     void MatchTemplate(Mat image, Mat templ, Mat result, int method, Mat mask);
59     Moment Moments(Mat src, bool binaryImage);
60     void PyrDown(Mat src, Mat dst, Size dstsize, int borderType);
61     void PyrUp(Mat src, Mat dst, Size dstsize, int borderType);
62     Rect BoundingRect(Contour con);
63     void BoxPoints(RotatedRect rect, Mat boxPts);
64     double ContourArea(Contour con);
65     RotatedRect MinAreaRect(Points points);
66     void MinEnclosingCircle(Points points, Point2f* center, float* radius);
67     Contours FindContours(Mat src, int mode, int method);
68     Contours FindContoursWithHier(Mat src, Hierarchy* chierarchy, int mode, int method);
69     int ConnectedComponents(Mat src, Mat dst, int connectivity, int ltype, int ccltype);
70     int ConnectedComponentsWithStats(Mat src, Mat labels, Mat stats, Mat centroids, int connectivity, int ltype, int ccltype);
71 
72     void GaussianBlur(Mat src, Mat dst, Size ps, double sX, double sY, int bt);
73     void Laplacian(Mat src, Mat dst, int dDepth, int kSize, double scale, double delta, int borderType);
74     void Scharr(Mat src, Mat dst, int dDepth, int dx, int dy, double scale, double delta,
75                 int borderType);
76     Mat GetStructuringElement(int shape, Size ksize);
77     Mat GetStructuringElementWithAnchor(int shape, Size ksize, Point anchor);
78     void MorphologyEx(Mat src, Mat dst, int op, Mat kernel);
79     void MedianBlur(Mat src, Mat dst, int ksize);
80     
81     void Canny(Mat src, Mat edges, double t1, double t2);
82     void Canny2(Mat dx, Mat dy, Mat edges, double threshold1, double threshold2, bool L2gradient);
83     void Canny3(Mat image, Mat edges, double threshold1, double threshold2, int apertureSize, bool L2gradient);
84     void CornerSubPix(Mat img, Mat corners, Size winSize, Size zeroZone, TermCriteria criteria);
85     void GoodFeaturesToTrack(Mat img, Mat corners, int maxCorners, double quality, double minDist);
86     void HoughCircles(Mat src, Mat circles, int method, double dp, double minDist);
87     void HoughCirclesWithParams(Mat src, Mat circles, int method, double dp, double minDist,
88                                 double param1, double param2, int minRadius, int maxRadius);
89     Vec3fs HoughCircles3(Mat image, int method, double dp,
90               double minDist, double param1, double param2, int minRadius, int maxRadius);
91     void HoughLines(Mat src, Mat lines, double rho, double theta, int threshold);
92     void HoughLinesP(Mat src, Mat lines, double rho, double theta, int threshold);
93     void HoughLinesP2(Mat image, Vec4is *lines, double rho, double theta,
94         int threshold, double minLineLength, double maxLineGap);
95     void HoughLinesPWithParams(Mat src, Mat lines, double rho, double theta, int threshold, double minLineLength, double maxLineGap);
96     void HoughLinesPointSet(Mat points, Mat lines, int lines_max, int threshold,
97                             double min_rho, double  max_rho, double rho_step,
98                             double min_theta, double max_theta, double theta_step);
99     void HoughLines2(Mat image, Vec2fs *lines, double rho, double theta,
100         int threshold, double srn, double stn, double min_theta, double max_theta);
101     void Threshold(Mat src, Mat dst, double thresh, double maxvalue, int typ);
102     void AdaptiveThreshold(Mat src, Mat dst, double maxValue, int adaptiveTyp, int typ, int blockSize,
103                            double c);
104                            
105     void ArrowedLine(Mat img, Point pt1, Point pt2, Scalar color, int thickness);
106     void Circle(Mat img, Point center, int radius, Scalar color, int thickness);
107     void Circle2(Mat img, Point center, int radius, Scalar color, int thickness, int shift);
108     void Ellipse(Mat img, Point center, Point axes, double angle, double
109                  startAngle, double endAngle, Scalar color, int thickness);
110     void Line(Mat img, Point pt1, Point pt2, Scalar color, int thickness);
111     void Line2(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int lineType, int shift);
112     void Rectangle(Mat img, Rect rect, Scalar color, int thickness);
113     void Rectangle2(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int lineType, int shift);
114     void FillPoly(Mat img, Contours points, Scalar color);
115     Size GetTextSize(const char* text, int fontFace, double fontScale, int thickness);
116     void PutText(Mat img, const char* text, Point org, int fontFace, double fontScale,
117                  Scalar color, int thickness);
118     void Resize(Mat src, Mat dst, Size sz, double fx, double fy, int interp);
119     Mat GetRotationMatrix2D(Point center, double angle, double scale);
120     void WarpAffine(Mat src, Mat dst, Mat rot_mat, Size dsize);
121     void WarpAffineWithParams(Mat src, Mat dst, Mat rot_mat, Size dsize, int flags, int borderMode,
122                               Scalar borderValue);
123     void WarpPerspective(Mat src, Mat dst, Mat m, Size dsize);
124     void ApplyColorMap(Mat src, Mat dst, int colormap);
125     void ApplyCustomColorMap(Mat src, Mat dst, Mat colormap);
126     Mat GetPerspectiveTransform(Contour src, Contour dst);
127     void DrawContours(Mat src, Contours contours, int contourIdx, Scalar color, int thickness);
128     void DrawContours2(
129         Mat image,
130         Contours contours,
131         int contourIdx,
132         Scalar color,
133         int thickness,
134         int lineType,
135         Hierarchy hierarchy,
136         int maxLevel,
137         Point offset
138     );
139     void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType);
140     void SpatialGradient(Mat src, Mat dx, Mat dy, int ksize, int borderType);
141     void Remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation, int borderMode, Scalar borderValue);
142     void Filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor, double delta, int borderType);
143     void SepFilter2D(Mat src, Mat dst, int ddepth, Mat kernelX, Mat kernelY, Point anchor, double delta, int borderType);
144     void LogPolar(Mat src, Mat dst, Point center, double m, int flags);
145     void FitLine(Contour points, Mat line, int distType, double param, double reps, double aeps);
146     
147     void Watershed(Mat src, Mat markers);
148     int FloodFill(Mat image, Mat mask, Point seedPoint, Scalar  newVal,
149             Rect rect, Scalar loDiff, Scalar upDiff, int flags);
150     int FloodFill2(Mat image, Point seedPoint, Scalar newVal, Rect rect, Scalar loDiff, Scalar upDiff, int flags);
151     void DistanceTransform(Mat src, Mat dst, Mat labels, int distanceType,
152         int maskSize, int labelType);
153     void DistanceTransform2(Mat src, Mat dst, int distanceType, int maskSize, int dstType);
154     
155     Subdiv2D Subdiv2d_New();
156     Subdiv2D Subdiv2d_NewFromRect(Rect r);
157     void Subdiv2D_Close(Subdiv2D sd);
158     void Subdiv2D_Insert(Subdiv2D sd, Point2f p);
159     void Subdiv2D_InsertMultiple(Subdiv2D sd, Point2fs ptvec);
160     Vec6fs Subdiv2D_GetTriangleList(Subdiv2D sd);
161     Point2fss Subdiv2D_GetVoronoiFacetList(Subdiv2D sd, IntVector idx, Point2fs* faceCenters);
162     int Subdiv2D_EdgeOrg(Subdiv2D sd, int edge, Point2f* orgpt);
163     int Subdiv2D_EdgeDst(Subdiv2D sd, int edge, Point2f* dstpt);
164     int Subdiv2D_NextEdge(Subdiv2D sd, int edge);
165     int Subdiv2D_RotateEdge(Subdiv2D sd, int edge, int rotate);
166     int Subdiv2D_SymEdge(Subdiv2D sd, int edge);
167     int Subdiv2D_GetEdge(Subdiv2D sd, int edge, int nextEdgeType);
168     Vec4fs Subdiv2D_GetEdgeList(Subdiv2D sd);
169     IntVector Subdiv2D_GetLeadingEdgeList(Subdiv2D sd);
170     int Subdiv2D_Locate(Subdiv2D sd, Point2f pt, ref int edge, ref int vertex);
171     Point2f Subdiv2D_GetVertex(Subdiv2D sd, int vertex, int* firstEdge);
172     void Subdiv2D_InitDelaunay(Subdiv2D sd, Rect bRect);
173     
174     void FillConvexPoly(Mat img, Points points, Scalar color, int lineType, int shift);
175     void FillConvexPoly2f(Mat img, Point2fs points, Scalar color, int lineType, int shift);
176     void Polylines(Mat img, Points pts, bool isClosed, Scalar color, int thickness, int lineType, int shift);
177     void Polylines2ss(Mat img, Pointss flist, bool isClosed, Scalar color, int thickness, int lineType, int shift);
178     void Polylines2f(Mat img, Point2fs pts, bool isClosed, Scalar color, int thickness, int lineType, int shift);
179     void Polylines2fss(Mat img, Point2fss pts, bool isClosed, Scalar color, int thickness, int lineType, int shift);
180     
181     RotatedRect FitEllipse(Points points);
182     RotatedRect FitEllipse2(Mat points);
183     RotatedRect FitEllipseAMS(Points points);
184     RotatedRect FitEllipseAMS2(Mat points);
185     RotatedRect FitEllipseDirect(Points points);
186     RotatedRect FitEllipseDirect2(Mat points);
187     void Ellipse2(Mat img, RotatedRect box, Scalar color, int thickness, int lineType);
188     
189     void PyrMeanShiftFiltering(Mat src, Mat dst, double sp, double sr, int maxLevel, TermCriteria termcrit);
190     
191     CLAHE CLAHE_Create();
192     CLAHE CLAHE_CreateWithParams(double clipLimit, Size tileGridSize);
193     void CLAHE_Close(CLAHE c);
194     void CLAHE_Apply(CLAHE c, Mat src, Mat dst);
195     double CLAHE_GetClipLimit(CLAHE c);
196     Size CLAHE_GetTilesGridSize(CLAHE c);
197     void CLAHE_SetClipLimit(CLAHE c, double clipLimit);
198     void CLAHE_SetTilesGridSize (CLAHE c, Size tileGridSize);
199     
200     double MinEnclosingTriangle(Mat points, Mat triangle);
201     double CompareHist(Mat H1, Mat H2, int method);
202 }
203 
204 double arcLength(Point[] curve, bool is_closed){
205     return ArcLength(Contour(curve.ptr, curve.length.to!int), is_closed);
206 }
207 
208 Point[] approxPolyDP(Point[] curve, double epsilon, bool isClosed){
209     Contour cret = ApproxPolyDP(Contour(curve.ptr, curve.length.to!int), epsilon, isClosed);
210     Point[] ret = cret.points[0..cret.length].dup;
211     Points_Close(cret);
212     return ret;
213 }
214 
215 void cvtColor(Mat src, Mat dst, int code){
216     CvtColor(src, dst, code);
217 }
218 
219 void equalizeHist(Mat src, Mat dst){
220     EqualizeHist(src, dst);
221 }
222 
223 void calcHist(Mats mats, int[] chans, Mat mask, Mat hist, IntVector sz, FloatVector rng, bool acc){
224     CalcHist(mats, IntVector(chans.ptr, chans.length.to!int), mask, hist, sz, rng, acc);
225 }
226 
227 void calcHist(Mat images, int nimages, int[] channels,
228             Mat mask, Mat hist, int dims, int[] histSize, float[][] _ranges, bool uniform = true, bool accumulate = false){
229     
230     float** __ranges = cast(float**)malloc(channels.length*(float*).sizeof);
231     
232     foreach(i; 0..channels.length){
233         float[] rng = [_ranges[i][0], _ranges[i][1]];
234         __ranges[i] = rng.ptr;
235     }
236     
237     CalcHist1(images, nimages, channels.ptr, mask, hist, dims, histSize.ptr, cast(const float**)__ranges, uniform, accumulate);
238     free(__ranges);
239 }
240 
241 void calcHist(Mat dst, Mat mask, Mat hist, int* histSize){
242     CalcHist2(dst, mask, hist, histSize);
243 }
244 
245 void convexHull(Point[] points, Mat hull, bool clockwise, bool returnPoints){
246     ConvexHull(Contour(points.ptr, cast(int)points.length), hull, clockwise, returnPoints);
247 }
248 
249 Point[] convexHull(Point[] points, bool clockwise = true){
250     Points pts = ConvexHull2(Contour(points.ptr, cast(int)points.length), clockwise);
251     Point[] ret = pts.points[0..pts.length].dup;
252     Points_Close(pts);
253     return ret;
254 }
255 
256 int[] convexHullIdx(Point[] points, bool clockwise = true){
257     IntVector iv = ConvexHull3(Contour(points.ptr, cast(int)points.length), clockwise);
258     int[] ret = iv.val[0..iv.length].dup;
259     Close_IntVector(iv);
260     return ret;
261 }
262 
263 void convexityDefects(Point[] points, Mat hull, Mat result){
264     ConvexityDefects(Contour(points.ptr, points.length.to!int), hull, result);
265 }
266 
267 void bilateralFilter(Mat src, Mat dst, int d, double sc, double ss){
268     BilateralFilter(src, dst, d, sc, ss);
269 }
270 
271 void blur(Mat src, Mat dst, Size ps){
272     Blur(src, dst, ps);
273 }
274 
275 void boxFilter(Mat src, Mat dst, int ddepth, Size ps){
276     BoxFilter(src, dst, ddepth, ps);
277 }
278 
279 void sqBoxFilter(Mat src, Mat dst, int ddepth, Size ps){
280     SqBoxFilter(src, dst, ddepth, ps);
281 }
282 
283 void dilate(Mat src, Mat dst, Mat kernel){
284     Dilate(src, dst, kernel);
285 }
286 
287 void dilate(Mat src, Mat dst, Mat kernel, Point anchor=Point(-1,-1), int iterations=1){
288     Dilate2(src, dst, kernel, anchor, iterations);
289 }
290 
291 void erode(Mat src, Mat dst, Mat kernel){
292     Erode(src, dst, kernel);
293 }
294 
295 void erode(Mat src, Mat dst, Mat kernel, Point anchor=Point(-1,-1), int iterations=1){
296     Erode2(src, dst, kernel, anchor, iterations);
297 }
298 
299 void matchTemplate(Mat image, Mat templ, Mat result, int method, Mat mask){
300     MatchTemplate(image, templ, result, method, mask);
301 }
302 
303 Moment moments(Mat src, bool isBinaryImage){
304     return Moments(src, isBinaryImage);
305 }
306 
307 void pyrDown(Mat src, Mat dst, Size dstsize, int borderType){
308     PyrDown(src, dst, dstsize, borderType);
309 }
310 
311 void pyrUp(Mat src, Mat dst, Size dstsize, int borderType){
312     PyrUp(src, dst, dstsize, borderType);
313 }
314 
315 Rect boundingRect(Point[] con){
316     return BoundingRect(Contour(con.ptr, con.length.to!int));
317 }
318 
319 void boxPoints(RotatedRect rect, Mat boxPts){
320     BoxPoints(rect, boxPts);
321 }
322 
323 double contourArea(Point[] con){
324     return ContourArea(Contour(con.ptr, con.length.to!int));
325 }
326 
327 RotatedRect minAreaRect(Point[] _points){
328     RotatedRect rr = MinAreaRect(Points(_points.ptr, _points.length.to!int));
329     Point[] ps = rr.pts.points[0..rr.pts.length].dup;
330     Points_Close(rr.pts);
331     RotatedRect ret = {Contour(ps.ptr, cast(int)ps.length), rr.boundingRect, rr.center, rr.size, rr.angle};
332     return ret;
333 }
334 void minEnclosingCircle(Point[] _points, Point2f* center, float* radius){
335     MinEnclosingCircle(Points(_points.ptr, _points.length.to!int), center, radius);
336 }
337 
338 // enum cv::RetrievalModes for findContours
339 enum: int {
340     RETR_EXTERNAL,
341     RETR_LIST,
342     RETR_CCOMP,
343     RETR_TREE,
344     RETR_FLOODFILL
345 }
346 // enum cv::ContourApproximationModes for findContours
347 enum: int {
348     CHAIN_APPROX_NONE,
349     CHAIN_APPROX_SIMPLE,
350     CHAIN_APPROX_TC89_L1,
351     CHAIN_APPROX_TC89_KCOS
352 }
353 
354 Point[][] findContours(Mat src, int mode, int method){
355     Contours cnts = FindContours(src, mode, method);
356     Point[][] dcnts; dcnts.length = cnts.length;
357     foreach(i; 0..cnts.length){
358         Points pts = cnts.contours[i];
359         Point[] dpts = pts.points[0..pts.length].dup;
360         dcnts[i] = dpts;
361     }
362     Contours_Close(cnts);
363     return dcnts;
364 }
365 
366 Tuple!(Point[][], Scalar[]) findContoursWithHier(Mat src, int mode, int method){
367     Hierarchy chier;
368     Contours cntrs = FindContoursWithHier(src, &chier, mode, method);
369     
370     Scalar[] hier = chier.scalars[0..chier.length].dup;
371     free(chier.scalars);
372     
373     Point[][] rc; rc.length = cntrs.length;
374     
375     foreach(i; 0..cntrs.length){
376         Contour cp = cntrs.contours[i];
377         Point[] dp = cp.points[0..cp.length].dup;
378         free(cp.points);
379         rc[i] = dp;
380     }
381     free(cntrs.contours);
382     return tuple(rc, hier);
383 }
384 
385 int connectedComponents(Mat src, Mat dst, int connectivity, int ltype, int ccltype){
386     return ConnectedComponents(src, dst, connectivity, ltype, ccltype);
387 }
388 
389 int connectedComponentsWithStats(Mat src, Mat labels, Mat stats, Mat centroids, int connectivity, int ltype, int ccltype){
390     return ConnectedComponentsWithStats(src, labels, stats, centroids, connectivity, ltype, ccltype);
391 }
392 
393 void gaussianBlur(Mat src, Mat dst, Size ps, double sX, double sY, int bt){
394     GaussianBlur(src, dst, ps, sX, sY, bt);
395 }
396 
397 void laplacian(Mat src, Mat dst, int dDepth, int kSize, double scale, double delta, int borderType){
398     Laplacian(src, dst, dDepth, kSize, scale, delta, borderType);
399 }
400 
401 void scharr(Mat src, Mat dst, int dDepth, int dx, int dy, double scale, double delta,
402             int borderType){
403     Scharr(src, dst, dDepth, dx, dy, scale, delta, borderType);
404 }
405 
406 enum: int { // cv::MorphShapes
407     MORPH_RECT,
408     MORPH_CROSS,
409     MORPH_ELLIPSE
410 }
411 
412 Mat getStructuringElement(int shape, Size ksize){
413     return GetStructuringElement(shape, ksize);
414 }
415 
416 Mat getStructuringElement(int shape, Size ksize, Point anchor){
417     return GetStructuringElementWithAnchor(shape, ksize, anchor);
418 }
419 
420 enum: int { // cv::MorphTypes
421     MORPH_ERODE,
422     MORPH_DILATE,
423     MORPH_OPEN,
424     MORPH_CLOSE,
425     MORPH_GRADIENT,
426     MORPH_TOPHAT,
427     MORPH_BLACKHAT,
428     MORPH_HITMISS
429 }
430 
431 void morphologyEx(Mat src, Mat dst, int op, Mat kernel){
432     MorphologyEx(src, dst, op, kernel);
433 }
434 
435 void medianBlur(Mat src, Mat dst, int ksize){
436     MedianBlur(src, dst, ksize);
437 }
438 
439 void canny(Mat src, Mat edges, double t1, double t2){
440     Canny(src, edges, t1, t2);
441 }
442 
443 void canny(Mat dx, Mat dy, Mat edges, double threshold1, double threshold2, bool L2gradient = false){
444     Canny2(dx, dy, edges, threshold1, threshold2, L2gradient);
445 }
446 
447 void canny(Mat image, Mat edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false){
448     Canny3(image, edges, threshold1, threshold2, apertureSize, L2gradient);
449 }
450 
451 void cornerSubPix(Mat img, Mat corners, Size winSize, Size zeroZone, TermCriteria criteria){
452     CornerSubPix(img, corners, winSize, zeroZone, criteria);
453 }
454 
455 void goodFeaturesToTrack(Mat img, Mat corners, int maxCorners, double quality, double minDist){
456     GoodFeaturesToTrack(img, corners, maxCorners, quality, minDist);
457 }
458 
459 enum: int { // cv::HoughModes
460   HOUGH_STANDARD = 0, 
461   HOUGH_PROBABILISTIC = 1, 
462   HOUGH_MULTI_SCALE = 2, 
463   HOUGH_GRADIENT = 3 
464 }
465 
466 void houghCircles(Mat src, Mat circles, int method, double dp, double minDist){
467     HoughCircles(src, circles, method, dp, minDist);
468 }
469 void houghCirclesWithParams(Mat src, Mat circles, int method, double dp, double minDist,
470                             double param1, double param2, int minRadius, int maxRadius){
471     HoughCirclesWithParams(src, circles, method, dp, minDist,
472                             param1, param2, minRadius, maxRadius);
473 }
474 
475 void houghCircles(Mat image, ref Vec3f[] circles, int method, double dp,
476                   double minDist, double param1 = 100,
477                   double param2 = 100, int minRadius = 0, int maxRadius = 0){
478     Vec3fs ccircles = HoughCircles3(image, method, dp, minDist, param1, param2, minRadius, maxRadius);
479     circles = ccircles.vec3fs[0..ccircles.length].dup;
480     free(ccircles.vec3fs);
481 }
482 
483 void houghLines(Mat src, Mat lines, double rho, double theta, int threshold){
484     HoughLines(src, lines, rho, theta, threshold);
485 }
486 
487 void houghLinesP(Mat src, Mat lines, double rho, double theta, int threshold){
488     HoughLinesP(src, lines, rho, theta, threshold);
489 }
490 
491 void houghLinesP(Mat image, ref Vec4i[] lines, double rho, double theta,
492     int threshold, double minLineLength = 0, double maxLineGap = 0){
493     Vec4is clines;
494     HoughLinesP2(image, &clines, rho, theta, threshold, minLineLength, maxLineGap);
495     lines = clines.vec4is[0..clines.length].dup;
496     free(clines.vec4is);
497 }
498 
499 void houghLinesPWithParams(Mat src, Mat lines, double rho, double theta, int threshold, double minLineLength, double maxLineGap){
500     HoughLinesPWithParams(src, lines, rho, theta, threshold, minLineLength, maxLineGap);
501 }
502 
503 void houghLines(Mat image, ref Vec2f[] lines, double rho, double theta,
504     int threshold, double srn = 0, double stn = 0, double min_theta = 0, double max_theta = PI){
505     Vec2fs clines;
506     HoughLines2(image, &clines, rho, theta, threshold, srn, stn, min_theta, max_theta);
507     lines = clines.vec2fs[0..clines.length].dup;
508     free(clines.vec2fs);
509 }
510 
511 void houghLinesPointSet(Mat points, Mat lines, int lines_max, int threshold,
512                         double min_rho, double  max_rho, double rho_step,
513                         double min_theta, double max_theta, double theta_step){
514     HoughLinesPointSet(points, lines, lines_max, threshold,
515                         min_rho, max_rho, rho_step,
516                         min_theta, max_theta, theta_step);
517 }
518 
519 enum: int {
520   THRESH_BINARY = 0,
521   THRESH_BINARY_INV = 1,
522   THRESH_TRUNC = 2,
523   THRESH_TOZERO = 3,
524   THRESH_TOZERO_INV = 4,
525   THRESH_MASK = 7,
526   THRESH_OTSU = 8,
527   THRESH_TRIANGLE = 16
528 }
529   
530 enum: int {
531   ADAPTIVE_THRESH_MEAN_C =0,
532   ADAPTIVE_THRESH_GAUSSIAN_C =1
533 }
534 
535 void threshold(Mat src, Mat dst, double thresh, double maxvalue, int typ){
536     Threshold(src, dst, thresh, maxvalue, typ);
537 }
538 
539 void adaptiveThreshold(Mat src, Mat dst, double maxValue, int adaptiveTyp, int typ, int blockSize,
540                        double c){
541     AdaptiveThreshold(src, dst, maxValue, adaptiveTyp, typ, blockSize, c);
542 }
543 
544 
545 void arrowedLine(Mat img, Point pt1, Point pt2, Scalar color, int thickness){
546     ArrowedLine(img, pt1, pt2, color, thickness);
547 }
548 
549 void circle(Mat img, Point center, int radius, Scalar color, int thickness){
550     Circle(img, center, radius, color, thickness);
551 }
552 
553 void circle(Mat img, Point center, int radius, Scalar color, int thickness, int shift){
554     Circle2(img, center, radius, color, thickness, shift);
555 }
556 
557 void ellipse(Mat img, Point center, Point axes, double angle, double
558              startAngle, double endAngle, Scalar color, int thickness){
559     Ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness);
560 }
561 
562 void line(Mat img, Point pt1, Point pt2, Scalar color, int thickness){
563     Line(img, pt1, pt2, color, thickness);
564 }
565 
566 void line(Mat img, Point pt1, Point pt2, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0){
567     Line2(img, pt1, pt2, color, thickness, lineType, shift);
568 }
569 
570 void rectangle(Mat img, Rect rect, Scalar color, int thickness){
571     Rectangle(img, rect, color, thickness);
572 }
573 
574 enum: int { // cv::LineTypes
575     FILLED = -1, 
576     LINE_4 = 4, 
577     LINE_8 = 8, 
578     LINE_AA = 16
579 }
580 
581 void rectangle(Mat img, Point _pt1, Point _pt2, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0){
582     Rectangle2(img, _pt1, _pt2, color, thickness, lineType, shift);
583 }
584 
585 void fillPoly(Mat img, Point[][] _points, Scalar color) @nogc nothrow {
586     Points* incpts = cast(Points*)malloc(_points.length*Points.sizeof);
587     scope(exit){
588         foreach(i; 0.._points.length)
589             free(incpts[i].points);
590         free(incpts);
591     }
592 
593     foreach(i; 0.._points.length){
594         Point* inception = cast(Point*)malloc(_points[i].length*Point.sizeof);
595         foreach(j; 0.._points[i].length){
596             inception[j] = _points[i][j];
597         }
598         
599         incpts[i] = Points(inception, cast(int)_points[i].length);
600     }
601     auto param = Contours(incpts, cast(int)_points.length);
602     FillPoly(img, param, color);
603 }
604 
605 enum: int { // cv::HersheyFonts
606     FONT_HERSHEY_SIMPLEX = 0, 
607     FONT_HERSHEY_PLAIN = 1, 
608     FONT_HERSHEY_DUPLEX = 2, 
609     FONT_HERSHEY_COMPLEX = 3, 
610     FONT_HERSHEY_TRIPLEX = 4, 
611     FONT_HERSHEY_COMPLEX_SMALL = 5, 
612     FONT_HERSHEY_SCRIPT_SIMPLEX = 6, 
613     FONT_HERSHEY_SCRIPT_COMPLEX = 7, 
614     FONT_ITALIC = 16 
615 }
616 
617 Size getTextSize(string text, int fontFace, double fontScale, int thickness){
618     return GetTextSize(toStringz(text), fontFace, fontScale, thickness);
619 }
620 
621 void putText(Mat img, string text, Point org, int fontFace, double fontScale,
622              Scalar color, int thickness = 1){
623     PutText(img, toStringz(text), org, fontFace, fontScale, color, thickness);
624 }
625 
626 
627 enum: int { // cv::InterpolationFlags
628     INTER_NEAREST = 0, 
629     INTER_LINEAR = 1, 
630     INTER_CUBIC = 2, 
631     INTER_AREA = 3, 
632     INTER_LANCZOS4 = 4, 
633     INTER_LINEAR_EXACT = 5, 
634     INTER_MAX = 7, 
635     WARP_FILL_OUTLIERS = 8, 
636     WARP_INVERSE_MAP = 16 
637 }
638 
639 void resize(Mat src, Mat dst, Size sz, double fx, double fy, int interp){
640     Resize(src, dst, sz, fx, fy, interp);
641 }
642 
643 Mat getRotationMatrix2D(Point center, double angle, double scale){
644     return GetRotationMatrix2D(center, angle, scale);
645 }
646 
647 void warpAffine(Mat src, Mat dst, Mat rot_mat, Size dsize){
648     WarpAffine(src, dst, rot_mat, dsize);
649 }
650 
651 void warpAffineWithParams(Mat src, Mat dst, Mat rot_mat, Size dsize, int flags, int borderMode,
652                           Scalar borderValue){
653     WarpAffineWithParams(src, dst, rot_mat, dsize, flags, borderMode, borderValue);
654 }
655 
656 void warpPerspective(Mat src, Mat dst, Mat m, Size dsize){
657     WarpPerspective(src, dst, m, dsize);
658 }
659 
660 void applyColorMap(Mat src, Mat dst, int colormap){
661     ApplyColorMap(src, dst, colormap);
662 }
663 
664 void applyCustomColorMap(Mat src, Mat dst, Mat colormap){
665     ApplyCustomColorMap(src, dst, colormap);
666 }
667 
668 Mat getPerspectiveTransform(Point[] src, Point[] dst){
669     return GetPerspectiveTransform(Contour(src.ptr, src.length.to!int), Contour(dst.ptr, dst.length.to!int));
670 }
671 
672 void drawContours(Mat src, Point[][] contours, int contourIdx, Scalar color, int thickness) @nogc nothrow {
673     Points* incpts = cast(Points*)malloc(contours.length*Points.sizeof);
674     scope(exit){
675         foreach(i; 0..contours.length)
676             free(incpts[i].points);
677         free(incpts);
678     }
679 
680     foreach(i; 0..contours.length){
681         Point* inception = cast(Point*)malloc(contours[i].length*Point.sizeof);
682         foreach(j; 0..contours[i].length){
683             inception[j] = contours[i][j];
684         }
685         
686         incpts[i] = Points(inception, cast(int)contours[i].length);
687     }
688     Contours param = {incpts, cast(int)contours.length};
689     DrawContours(src, param, contourIdx, color, thickness);
690 }
691 
692 void drawContours(
693             Mat image,
694             Point[][] contours,
695             int contourIdx,
696             Scalar color,
697             int thickness,
698             int lineType,
699             Scalar[] hierarchy,
700             int maxLevel,
701             Point offset = Point(0,0)
702         ) @nogc nothrow {
703     Points* incpts = cast(Points*)malloc(contours.length*Points.sizeof);
704     scope(exit){
705         foreach(i; 0..contours.length)
706             free(incpts[i].points);
707         free(incpts);
708     }
709     foreach(i; 0..contours.length){
710         Point* inception = cast(Point*)malloc(contours[i].length*Point.sizeof);
711         foreach(j; 0..contours[i].length){
712             inception[j] = contours[i][j];
713         }
714         
715         incpts[i] = Points(inception, cast(int)contours[i].length);
716     }
717     Contours param = {incpts, cast(int)contours.length};
718     
719     Hierarchy chie = {hierarchy.ptr, cast(int)hierarchy.length};
720     
721     DrawContours2(image, param, contourIdx, color, thickness, lineType, chie, maxLevel, offset);
722 }
723 
724 void sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType){
725     Sobel(src, dst, ddepth, dx, dy, ksize, scale, delta, borderType);
726 }
727 
728 void spatialGradient(Mat src, Mat dx, Mat dy, int ksize, int borderType){
729     SpatialGradient(src, dx, dy, ksize, borderType);
730 }
731 
732 void remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation, int borderMode, Scalar borderValue){
733     Remap(src, dst, map1, map2, interpolation, borderMode, borderValue);
734 }
735 
736 enum: int { // cv::BorderTypes
737     BORDER_CONSTANT = 0, 
738     BORDER_REPLICATE = 1, 
739     BORDER_REFLECT = 2, 
740     BORDER_WRAP = 3, 
741     BORDER_REFLECT_101 = 4, 
742     BORDER_TRANSPARENT = 5, 
743     BORDER_REFLECT101 = BORDER_REFLECT_101, 
744     BORDER_DEFAULT = BORDER_REFLECT_101, 
745     BORDER_ISOLATED = 16 
746 }
747 
748 void filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor = Point(-1,-1), double delta = 0, int borderType = BORDER_DEFAULT){
749     Filter2D(src, dst, ddepth, kernel, anchor, delta, borderType);
750 }
751 
752 void sepFilter2D(Mat src, Mat dst, int ddepth, Mat kernelX, Mat kernelY, Point anchor, double delta, int borderType){
753     SepFilter2D(src, dst, ddepth, kernelX, kernelY, anchor, delta, borderType);
754 }
755 
756 void logPolar(Mat src, Mat dst, Point center, double m, int flags){
757     LogPolar(src, dst, center, m, flags);
758 }
759 
760 void fitLine(Point[] points, Mat line, int distType, double param, double reps, double aeps){
761     FitLine(Contour(points.ptr, points.length.to!int), line, distType, param, reps, aeps);
762 }
763 
764 void watershed(Mat src, Mat markers){
765     Watershed(src, markers);
766 }
767 
768 int floodFill(Mat image, Mat mask, Point seedPoint, Scalar  newVal,
769                 Rect rect = Rect(), Scalar loDiff = Scalar(), Scalar upDiff = Scalar(), int flags = 4){
770     return FloodFill(image, mask, seedPoint, newVal, rect, loDiff, upDiff, flags);
771 }
772 
773 int floodFill(Mat image, Point seedPoint, Scalar newVal, Rect rect = Rect(), Scalar loDiff = Scalar(), Scalar upDiff = Scalar(), int flags = 4){
774     return FloodFill2(image, seedPoint, newVal, rect, loDiff, upDiff, flags);
775 }
776 
777 enum: int{ // cv::DistanceTransformMasks
778     DIST_MASK_3 = 3, 
779     DIST_MASK_5 = 5, 
780     DIST_MASK_PRECISE = 0 
781 }
782 
783 enum: int { // cv::DistanceTransformLabelTypes
784     DIST_LABEL_CCOMP = 0, 
785     DIST_LABEL_PIXEL = 1 
786 }
787 
788 enum: int { // cv::DistanceTypes
789     DIST_USER = -1, 
790     DIST_L1 = 1, 
791     DIST_L2 = 2, 
792     DIST_C = 3, 
793     DIST_L12 = 4, 
794     DIST_FAIR = 5, 
795     DIST_WELSCH = 6, 
796     DIST_HUBER = 7 
797 }
798 
799 
800 void distanceTransform(Mat src, Mat dst, Mat labels, int distanceType,
801     int maskSize, int labelType = DIST_LABEL_CCOMP){
802     
803     DistanceTransform(src, dst, labels, distanceType, maskSize, labelType);
804 }	
805 
806 
807 void distanceTransform(Mat src, Mat	dst, int distanceType, int maskSize, int dstType = CV32F){
808     DistanceTransform2(src, dst, distanceType, maskSize, dstType);
809 }	
810 
811 /** Subdiv2D point location cases */
812 enum: int {
813     PTLOC_ERROR        = -2, //!< Point location error
814     PTLOC_OUTSIDE_RECT = -1, //!< Point outside the subdivision bounding rect
815     PTLOC_INSIDE       = 0, //!< Point inside some facet
816     PTLOC_VERTEX       = 1, //!< Point coincides with one of the subdivision vertices
817     PTLOC_ON_EDGE      = 2  //!< Point on some edge
818 }
819 
820 struct Subdiv2D {
821     void* p;
822     
823     static Subdiv2D opCall(){
824         return Subdiv2d_New();
825     }
826     
827     static Subdiv2D opCall(Rect rect){
828         return Subdiv2d_NewFromRect(rect);
829     }
830     
831     void insert(Point2f p){
832         Subdiv2D_Insert(this, p);
833     }
834     
835     void insert(Point2f[] ptvec){
836         Subdiv2D_InsertMultiple(this, Point2fs(ptvec.ptr, ptvec.length.to!int));
837     }
838     
839     Vec6f[] getTriangleList(){
840         auto v6fs = Subdiv2D_GetTriangleList(this);
841         Vec6f[] ret = v6fs.vec6fs[0..v6fs.length].dup;
842         Close_Vec6fs(v6fs);
843         return ret;
844     }
845     
846     Tuple!(Point2f[][], Point2f[]) getVoronoiFacetList(int[] idx = null){
847        Point2fs _faceCenters;
848        Point2fss _facetList = Subdiv2D_GetVoronoiFacetList(this, IntVector(idx.ptr, cast(int)idx.length), &_faceCenters);
849        
850        Point2f[] faceCenters = _faceCenters.points[0.._faceCenters.length].dup;
851        free(_faceCenters.points);
852        Point2f[][] retFL; retFL.length = _facetList.length;
853        for(size_t i = 0; i < _facetList.length; i++){
854            Point2fs fl = _facetList.point2fss[i];
855            Point2f[] point2fs = fl.points[0..fl.length].dup;
856            free(fl.points);
857            retFL[i] = point2fs;
858        }
859        free(_facetList.point2fss);
860        return tuple(retFL, faceCenters);
861     }
862     
863     /** Subdiv2D edge type navigation (see: getEdge()) */
864     static int NEXT_AROUND_ORG   = 0x00;
865     static int NEXT_AROUND_DST   = 0x22;
866     static int PREV_AROUND_ORG   = 0x11;
867     static int PREV_AROUND_DST   = 0x33;
868     static int NEXT_AROUND_LEFT  = 0x13;
869     static int NEXT_AROUND_RIGHT = 0x31;
870     static int PREV_AROUND_LEFT  = 0x20;
871     static int PREV_AROUND_RIGHT = 0x02;
872     
873     int edgeOrg(int edge, ref Point2f orgpt){
874         int retVal = Subdiv2D_EdgeOrg(this, edge, &orgpt);
875         return retVal;
876     }
877     
878     int edgeDst(int edge, ref Point2f dstpt){
879         int retVal = Subdiv2D_EdgeDst(this, edge, &dstpt);
880         return retVal;
881     }
882     
883     int getEdge(int edge, int nextEdgeType){
884         return Subdiv2D_GetEdge(this, edge, nextEdgeType);
885     }
886     
887     Vec4f[] getEdgeList(){
888         Vec4fs vec4fs = Subdiv2D_GetEdgeList(this);
889         Vec4f[] ret = vec4fs.vec4fs[0..vec4fs.length].dup;
890         free(vec4fs.vec4fs);
891         return ret;
892     }
893     
894     int[] getLeadingEdgeList(){
895         IntVector intv = Subdiv2D_GetLeadingEdgeList(this);
896         int[] ret = intv.val[0..intv.length].dup;
897         Close_IntVector(intv);
898         return ret;
899     }
900     
901     int nextEdge(int edge){
902         return Subdiv2D_NextEdge(this, edge);
903     }
904     
905     int rotateEdge(int edge, int rotate){
906         return Subdiv2D_RotateEdge(this, edge, rotate);
907     }
908     
909     int symEdge(int edge){
910         return Subdiv2D_SymEdge(this, edge);
911     }
912     
913     int locate(Point2f pt, ref int edge, ref int vertex){
914         return Subdiv2D_Locate(this, pt, edge, vertex);
915     }
916     
917     Point2f getVertex(int vertex, int* firstEdge = null){
918         return Subdiv2D_GetVertex(this, vertex, firstEdge);
919     }
920     
921     void initDelaunay(Rect bRect){
922         Subdiv2D_InitDelaunay(this, bRect);
923     }
924 }
925 
926 void Destroy(Subdiv2D sd){
927     Subdiv2D_Close(sd);
928 }
929 
930 void fillConvexPoly(Mat img, Point[] points, Scalar color, int lineType = LINE_8, int shift = 0){
931     FillConvexPoly(img, Points(points.ptr, cast(int)points.length), color, lineType, shift);
932 }
933 
934 enum: int {
935     CV_FILLED = -1,
936     CV_AA = 16
937 }
938 
939 void polylines(Mat img, Point[] pts, bool isClosed, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) @nogc nothrow {
940     Polylines(img, Points(pts.ptr, cast(int)pts.length), isClosed, color, thickness, lineType, shift);
941 }
942 
943 void polylines(Mat img, Point[][] pts, bool isClosed, Scalar color,
944     int thickness = 1, int lineType = LINE_8, int shift = 0) @nogc nothrow {
945     
946     Points* incpts = cast(Points*)malloc(pts.length*Points.sizeof);
947     scope(exit){
948         foreach(i; 0..pts.length)
949             free(incpts[i].points);
950         free(incpts);
951     }
952 
953     foreach(i; 0..pts.length){
954         Point* inception = cast(Point*)malloc(pts[i].length*Point.sizeof);
955         foreach(j; 0..pts[i].length){
956             inception[j] = pts[i][j];
957         }
958         
959         incpts[i] = Points(inception, cast(int)pts[i].length);
960     }
961     Pointss param = {incpts, cast(int)pts.length}; 
962     Polylines2ss(img, param, isClosed, color, thickness, lineType, shift);
963 }
964 
965 // Contrast-limited adaptive histogram equalization
966 struct CLAHE{
967 	void* p;
968     
969     static CLAHE opCall(){
970         return newCLAHE();
971     }
972     
973     static CLAHE opCall(double clipLimit, Size tileGridSize){
974         return CLAHE_CreateWithParams(clipLimit, tileGridSize);
975     }
976     
977     double getClipLimit(){
978         return CLAHE_GetClipLimit(this);
979     }
980     
981     Size getTilesGridSize(){
982         return CLAHE_GetTilesGridSize(this);
983     }
984     
985     void setClipLimit(double clipLimit){
986         CLAHE_SetClipLimit(this, clipLimit);
987     }
988     
989     void setTilesGridSize (Size tileGridSize){
990         CLAHE_SetTilesGridSize (this, tileGridSize);
991     }
992     
993     void apply(Mat src, Mat dst){
994         CLAHE_Apply(this, src, dst);
995     }
996 }
997 
998 void Destroy(CLAHE c){
999     CLAHE_Close(c);
1000 }
1001 
1002 CLAHE newCLAHE(){ // implement in 'this'?
1003     return CLAHE_Create();
1004 }
1005 
1006 CLAHE newCLAHEWithParams(double clipLimit, Size tileGridSize){
1007     return CLAHE_CreateWithParams(clipLimit, tileGridSize);
1008 }
1009 
1010 RotatedRect fitEllipse(Point[] points){
1011     RotatedRect rect = FitEllipse(Points(points.ptr, points.length.to!int));
1012     Point[] pts = rect.pts.points[0..rect.pts.length].dup;
1013     
1014     RotatedRect retRect = {
1015         Contour(pts.ptr, pts.length.to!int),
1016         rect.boundingRect,
1017         rect.center,
1018         rect.size,
1019         rect.angle
1020     };
1021     Points_Close(rect.pts);
1022     return retRect;
1023 }
1024 
1025 RotatedRect fitEllipse(Mat points){
1026     return FitEllipse2(points);
1027 }
1028 
1029 RotatedRect fitEllipseAMS(Point[] points){
1030     RotatedRect rect = FitEllipseAMS(Points(points.ptr, points.length.to!int));
1031     Point[] pts = rect.pts.points[0..rect.pts.length].dup;
1032     
1033     RotatedRect retRect = {
1034         Contour(pts.ptr, pts.length.to!int),
1035         rect.boundingRect,
1036         rect.center,
1037         rect.size,
1038         rect.angle
1039     };
1040     Points_Close(rect.pts);
1041     return retRect;
1042 }
1043 
1044 RotatedRect fitEllipseAMS(Mat points){
1045     return FitEllipseAMS2(points);
1046 }
1047 
1048 RotatedRect fitEllipseDirect(Point[] points){
1049     RotatedRect rect = FitEllipseDirect(Points(points.ptr, points.length.to!int));
1050     Point[] pts = rect.pts.points[0..rect.pts.length].dup;
1051     
1052     RotatedRect retRect = {
1053         Contour(pts.ptr, pts.length.to!int),
1054         rect.boundingRect,
1055         rect.center,
1056         rect.size,
1057         rect.angle
1058     };
1059     Points_Close(rect.pts);
1060     return retRect;
1061 }
1062 
1063 RotatedRect fitEllipseDirect(Mat points){
1064     return FitEllipseDirect2(points);
1065 }
1066 
1067 void ellipse(Mat img, RotatedRect box, Scalar color, int thickness = 1, int lineType = LINE_8){
1068     Ellipse2(img, box, color, thickness, lineType);
1069 }
1070 
1071 void pyrMeanShiftFiltering(Mat src, Mat dst, double sp, double sr, int maxLevel = 1,
1072         TermCriteria termcrit = TermCriteria(TermCriteria.MAX_ITER+TermCriteria.EPS, 5, 1)){
1073     PyrMeanShiftFiltering(src, dst, sp, sr, maxLevel, termcrit);
1074 }
1075 
1076 double minEnclosingTriangle(Mat points, Mat triangle){
1077     return MinEnclosingTriangle(points, triangle);
1078 }
1079 
1080 double minEnclosingTriangle(Point[] points, ref Point2f[] triangle){
1081     import opencvd.cvcore: Destroy;
1082     
1083     const int cv32f2 = CV_MAKETYPE(CV_32F, 2);
1084     const int cv32s2 = CV_MAKETYPE(CV_32S, 2);
1085     
1086     Mat srcmat = zeros(points.length.to!int, 1, cv32s2);
1087     Mat dstmat = zeros(6, 1, cv32f2);
1088     
1089     scope(exit){
1090         Destroy(srcmat);
1091         Destroy(dstmat);
1092     }
1093     
1094     foreach(int i; 0..points.length.to!int){
1095         srcmat.set!int(i, 0, points[i].x);
1096         srcmat.set!int(i, 1, points[i].y);
1097     }
1098     
1099     
1100     double retval = MinEnclosingTriangle(srcmat, dstmat);
1101     
1102     triangle.length = dstmat.rows.to!size_t;
1103     foreach(int i; 0..dstmat.rows){
1104         float xx = dstmat.at!float(i, 0);
1105         float yy = dstmat.at!float(i, 1);
1106         triangle[i] = Point2f(xx, yy);
1107     }
1108     
1109     return retval;
1110 }
1111 
1112 double minEnclosingTriangle(Point2f[] points, ref Point2f[] triangle){
1113     import opencvd.cvcore: Destroy;
1114     
1115     const int cv32f2 = CV_MAKETYPE(CV_32F, 2);
1116     
1117     Mat srcmat = zeros(points.length.to!int, 1, cv32f2);
1118     Mat dstmat = zeros(6, 1, cv32f2);
1119     
1120     scope(exit){
1121         Destroy(srcmat);
1122         Destroy(dstmat);
1123     }
1124     
1125     foreach(int i; 0..points.length.to!int){
1126         srcmat.set!float(i, 0, points[i].x);
1127         srcmat.set!float(i, 1, points[i].y);
1128     }
1129     
1130     double retval = MinEnclosingTriangle(srcmat, dstmat);
1131     
1132     triangle.length = dstmat.rows.to!size_t;
1133     foreach(int i; 0..dstmat.rows){
1134         float xx = dstmat.at!float(i, 0);
1135         float yy = dstmat.at!float(i, 1);
1136         triangle[i] = Point2f(xx, yy);
1137     }
1138     
1139     return retval;
1140 }
1141 
1142 enum: int { // cv::HistCompMethods 
1143     HISTCMP_CORREL = 0, 
1144     HISTCMP_CHISQR = 1, 
1145     HISTCMP_INTERSECT = 2, 
1146     HISTCMP_BHATTACHARYYA = 3, 
1147     HISTCMP_HELLINGER = HISTCMP_BHATTACHARYYA, 
1148     HISTCMP_CHISQR_ALT = 4, 
1149     HISTCMP_KL_DIV = 5 
1150 }
1151 
1152 double compareHist(Mat H1, Mat H2, int method){
1153     return CompareHist(H1, H2, method);
1154 }
1155 
1156 enum: int {
1157     COLOR_BGR2BGRA = 0, 
1158 
1159     COLOR_RGB2RGBA = COLOR_BGR2BGRA, 
1160 
1161     COLOR_BGRA2BGR = 1, 
1162 
1163     COLOR_RGBA2RGB = COLOR_BGRA2BGR, 
1164 
1165     COLOR_BGR2RGBA = 2, 
1166 
1167     COLOR_RGB2BGRA = COLOR_BGR2RGBA, 
1168 
1169     COLOR_RGBA2BGR = 3, 
1170 
1171     COLOR_BGRA2RGB = COLOR_RGBA2BGR, 
1172 
1173     COLOR_BGR2RGB = 4, 
1174 
1175     COLOR_RGB2BGR = COLOR_BGR2RGB, 
1176 
1177     COLOR_BGRA2RGBA = 5, 
1178 
1179     COLOR_RGBA2BGRA = COLOR_BGRA2RGBA, 
1180 
1181     COLOR_BGR2GRAY = 6, 
1182 
1183     COLOR_RGB2GRAY = 7, 
1184 
1185     COLOR_GRAY2BGR = 8, 
1186 
1187     COLOR_GRAY2RGB = COLOR_GRAY2BGR, 
1188 
1189     COLOR_GRAY2BGRA = 9, 
1190 
1191     COLOR_GRAY2RGBA = COLOR_GRAY2BGRA, 
1192 
1193     COLOR_BGRA2GRAY = 10, 
1194 
1195     COLOR_RGBA2GRAY = 11, 
1196 
1197     COLOR_BGR2BGR565 = 12, 
1198 
1199     COLOR_RGB2BGR565 = 13, 
1200 
1201     COLOR_BGR5652BGR = 14, 
1202 
1203     COLOR_BGR5652RGB = 15, 
1204 
1205     COLOR_BGRA2BGR565 = 16, 
1206 
1207     COLOR_RGBA2BGR565 = 17, 
1208 
1209     COLOR_BGR5652BGRA = 18, 
1210 
1211     COLOR_BGR5652RGBA = 19, 
1212 
1213     COLOR_GRAY2BGR565 = 20, 
1214 
1215     COLOR_BGR5652GRAY = 21, 
1216 
1217     COLOR_BGR2BGR555 = 22, 
1218 
1219     COLOR_RGB2BGR555 = 23, 
1220 
1221     COLOR_BGR5552BGR = 24, 
1222 
1223     COLOR_BGR5552RGB = 25, 
1224 
1225     COLOR_BGRA2BGR555 = 26, 
1226 
1227     COLOR_RGBA2BGR555 = 27, 
1228 
1229     COLOR_BGR5552BGRA = 28, 
1230 
1231     COLOR_BGR5552RGBA = 29, 
1232 
1233     COLOR_GRAY2BGR555 = 30, 
1234 
1235     COLOR_BGR5552GRAY = 31, 
1236 
1237     COLOR_BGR2XYZ = 32, 
1238 
1239     COLOR_RGB2XYZ = 33, 
1240 
1241     COLOR_XYZ2BGR = 34, 
1242 
1243     COLOR_XYZ2RGB = 35, 
1244 
1245     COLOR_BGR2YCrCb = 36, 
1246 
1247     COLOR_RGB2YCrCb = 37, 
1248 
1249     COLOR_YCrCb2BGR = 38, 
1250 
1251     COLOR_YCrCb2RGB = 39, 
1252 
1253     COLOR_BGR2HSV = 40, 
1254 
1255     COLOR_RGB2HSV = 41, 
1256 
1257     COLOR_BGR2Lab = 44, 
1258 
1259     COLOR_RGB2Lab = 45, 
1260 
1261     COLOR_BGR2Luv = 50, 
1262 
1263     COLOR_RGB2Luv = 51, 
1264 
1265     COLOR_BGR2HLS = 52, 
1266 
1267     COLOR_RGB2HLS = 53, 
1268 
1269     COLOR_HSV2BGR = 54, 
1270 
1271     COLOR_HSV2RGB = 55, 
1272 
1273     COLOR_Lab2BGR = 56, 
1274 
1275     COLOR_Lab2RGB = 57, 
1276 
1277     COLOR_Luv2BGR = 58, 
1278 
1279     COLOR_Luv2RGB = 59, 
1280 
1281     COLOR_HLS2BGR = 60, 
1282 
1283     COLOR_HLS2RGB = 61, 
1284 
1285     COLOR_BGR2HSV_FULL = 66, 
1286 
1287     COLOR_RGB2HSV_FULL = 67, 
1288 
1289     COLOR_BGR2HLS_FULL = 68, 
1290 
1291     COLOR_RGB2HLS_FULL = 69, 
1292 
1293     COLOR_HSV2BGR_FULL = 70, 
1294 
1295     COLOR_HSV2RGB_FULL = 71, 
1296 
1297     COLOR_HLS2BGR_FULL = 72, 
1298 
1299     COLOR_HLS2RGB_FULL = 73, 
1300 
1301     COLOR_LBGR2Lab = 74, 
1302 
1303     COLOR_LRGB2Lab = 75, 
1304 
1305     COLOR_LBGR2Luv = 76, 
1306 
1307     COLOR_LRGB2Luv = 77, 
1308 
1309     COLOR_Lab2LBGR = 78, 
1310 
1311     COLOR_Lab2LRGB = 79, 
1312 
1313     COLOR_Luv2LBGR = 80, 
1314 
1315     COLOR_Luv2LRGB = 81, 
1316 
1317     COLOR_BGR2YUV = 82, 
1318 
1319     COLOR_RGB2YUV = 83, 
1320 
1321     COLOR_YUV2BGR = 84, 
1322 
1323     COLOR_YUV2RGB = 85, 
1324 
1325     COLOR_YUV2RGB_NV12 = 90, 
1326 
1327     COLOR_YUV2BGR_NV12 = 91, 
1328 
1329     COLOR_YUV2RGB_NV21 = 92, 
1330 
1331     COLOR_YUV2BGR_NV21 = 93, 
1332 
1333     COLOR_YUV420sp2RGB = COLOR_YUV2RGB_NV21, 
1334 
1335     COLOR_YUV420sp2BGR = COLOR_YUV2BGR_NV21, 
1336 
1337     COLOR_YUV2RGBA_NV12 = 94, 
1338 
1339     COLOR_YUV2BGRA_NV12 = 95, 
1340 
1341     COLOR_YUV2RGBA_NV21 = 96, 
1342 
1343     COLOR_YUV2BGRA_NV21 = 97, 
1344 
1345     COLOR_YUV420sp2RGBA = COLOR_YUV2RGBA_NV21, 
1346 
1347     COLOR_YUV420sp2BGRA = COLOR_YUV2BGRA_NV21, 
1348 
1349     COLOR_YUV2RGB_YV12 = 98, 
1350 
1351     COLOR_YUV2BGR_YV12 = 99, 
1352 
1353     COLOR_YUV2RGB_IYUV = 100, 
1354 
1355     COLOR_YUV2BGR_IYUV = 101, 
1356 
1357     COLOR_YUV2RGB_I420 = COLOR_YUV2RGB_IYUV, 
1358 
1359     COLOR_YUV2BGR_I420 = COLOR_YUV2BGR_IYUV, 
1360 
1361     COLOR_YUV420p2RGB = COLOR_YUV2RGB_YV12, 
1362 
1363     COLOR_YUV420p2BGR = COLOR_YUV2BGR_YV12, 
1364 
1365     COLOR_YUV2RGBA_YV12 = 102, 
1366 
1367     COLOR_YUV2BGRA_YV12 = 103, 
1368 
1369     COLOR_YUV2RGBA_IYUV = 104, 
1370 
1371     COLOR_YUV2BGRA_IYUV = 105, 
1372 
1373     COLOR_YUV2RGBA_I420 = COLOR_YUV2RGBA_IYUV, 
1374 
1375     COLOR_YUV2BGRA_I420 = COLOR_YUV2BGRA_IYUV, 
1376 
1377     COLOR_YUV420p2RGBA = COLOR_YUV2RGBA_YV12, 
1378 
1379     COLOR_YUV420p2BGRA = COLOR_YUV2BGRA_YV12, 
1380 
1381     COLOR_YUV2GRAY_420 = 106, 
1382 
1383     COLOR_YUV2GRAY_NV21 = COLOR_YUV2GRAY_420, 
1384 
1385     COLOR_YUV2GRAY_NV12 = COLOR_YUV2GRAY_420, 
1386 
1387     COLOR_YUV2GRAY_YV12 = COLOR_YUV2GRAY_420, 
1388 
1389     COLOR_YUV2GRAY_IYUV = COLOR_YUV2GRAY_420, 
1390 
1391     COLOR_YUV2GRAY_I420 = COLOR_YUV2GRAY_420, 
1392 
1393     COLOR_YUV420sp2GRAY = COLOR_YUV2GRAY_420, 
1394 
1395     COLOR_YUV420p2GRAY = COLOR_YUV2GRAY_420, 
1396 
1397     COLOR_YUV2RGB_UYVY = 107, 
1398 
1399     COLOR_YUV2BGR_UYVY = 108, 
1400 
1401     COLOR_YUV2RGB_Y422 = COLOR_YUV2RGB_UYVY, 
1402 
1403     COLOR_YUV2BGR_Y422 = COLOR_YUV2BGR_UYVY, 
1404 
1405     COLOR_YUV2RGB_UYNV = COLOR_YUV2RGB_UYVY, 
1406 
1407     COLOR_YUV2BGR_UYNV = COLOR_YUV2BGR_UYVY, 
1408 
1409     COLOR_YUV2RGBA_UYVY = 111, 
1410 
1411     COLOR_YUV2BGRA_UYVY = 112, 
1412 
1413     COLOR_YUV2RGBA_Y422 = COLOR_YUV2RGBA_UYVY, 
1414 
1415     COLOR_YUV2BGRA_Y422 = COLOR_YUV2BGRA_UYVY, 
1416 
1417     COLOR_YUV2RGBA_UYNV = COLOR_YUV2RGBA_UYVY, 
1418 
1419     COLOR_YUV2BGRA_UYNV = COLOR_YUV2BGRA_UYVY, 
1420 
1421     COLOR_YUV2RGB_YUY2 = 115, 
1422 
1423     COLOR_YUV2BGR_YUY2 = 116, 
1424 
1425     COLOR_YUV2RGB_YVYU = 117, 
1426 
1427     COLOR_YUV2BGR_YVYU = 118, 
1428 
1429     COLOR_YUV2RGB_YUYV = COLOR_YUV2RGB_YUY2, 
1430 
1431     COLOR_YUV2BGR_YUYV = COLOR_YUV2BGR_YUY2, 
1432 
1433     COLOR_YUV2RGB_YUNV = COLOR_YUV2RGB_YUY2, 
1434 
1435     COLOR_YUV2BGR_YUNV = COLOR_YUV2BGR_YUY2, 
1436 
1437     COLOR_YUV2RGBA_YUY2 = 119, 
1438 
1439     COLOR_YUV2BGRA_YUY2 = 120, 
1440 
1441     COLOR_YUV2RGBA_YVYU = 121, 
1442 
1443     COLOR_YUV2BGRA_YVYU = 122, 
1444 
1445     COLOR_YUV2RGBA_YUYV = COLOR_YUV2RGBA_YUY2, 
1446 
1447     COLOR_YUV2BGRA_YUYV = COLOR_YUV2BGRA_YUY2, 
1448 
1449     COLOR_YUV2RGBA_YUNV = COLOR_YUV2RGBA_YUY2, 
1450 
1451     COLOR_YUV2BGRA_YUNV = COLOR_YUV2BGRA_YUY2, 
1452 
1453     COLOR_YUV2GRAY_UYVY = 123, 
1454 
1455     COLOR_YUV2GRAY_YUY2 = 124, 
1456 
1457     COLOR_YUV2GRAY_Y422 = COLOR_YUV2GRAY_UYVY, 
1458 
1459     COLOR_YUV2GRAY_UYNV = COLOR_YUV2GRAY_UYVY, 
1460 
1461     COLOR_YUV2GRAY_YVYU = COLOR_YUV2GRAY_YUY2, 
1462 
1463     COLOR_YUV2GRAY_YUYV = COLOR_YUV2GRAY_YUY2, 
1464 
1465     COLOR_YUV2GRAY_YUNV = COLOR_YUV2GRAY_YUY2, 
1466 
1467     COLOR_RGBA2mRGBA = 125, 
1468 
1469     COLOR_mRGBA2RGBA = 126, 
1470 
1471     COLOR_RGB2YUV_I420 = 127, 
1472 
1473     COLOR_BGR2YUV_I420 = 128, 
1474 
1475     COLOR_RGB2YUV_IYUV = COLOR_RGB2YUV_I420, 
1476 
1477     COLOR_BGR2YUV_IYUV = COLOR_BGR2YUV_I420, 
1478 
1479     COLOR_RGBA2YUV_I420 = 129, 
1480 
1481     COLOR_BGRA2YUV_I420 = 130, 
1482 
1483     COLOR_RGBA2YUV_IYUV = COLOR_RGBA2YUV_I420, 
1484 
1485     COLOR_BGRA2YUV_IYUV = COLOR_BGRA2YUV_I420, 
1486 
1487     COLOR_RGB2YUV_YV12 = 131, 
1488 
1489     COLOR_BGR2YUV_YV12 = 132, 
1490 
1491     COLOR_RGBA2YUV_YV12 = 133, 
1492 
1493     COLOR_BGRA2YUV_YV12 = 134, 
1494 
1495     COLOR_BayerBG2BGR = 46, 
1496 
1497     COLOR_BayerGB2BGR = 47, 
1498 
1499     COLOR_BayerRG2BGR = 48, 
1500 
1501     COLOR_BayerGR2BGR = 49, 
1502 
1503     COLOR_BayerBG2RGB = COLOR_BayerRG2BGR, 
1504 
1505     COLOR_BayerGB2RGB = COLOR_BayerGR2BGR, 
1506 
1507     COLOR_BayerRG2RGB = COLOR_BayerBG2BGR, 
1508 
1509     COLOR_BayerGR2RGB = COLOR_BayerGB2BGR, 
1510 
1511     COLOR_BayerBG2GRAY = 86, 
1512 
1513     COLOR_BayerGB2GRAY = 87, 
1514 
1515     COLOR_BayerRG2GRAY = 88, 
1516 
1517     COLOR_BayerGR2GRAY = 89, 
1518 
1519     COLOR_BayerBG2BGR_VNG = 62, 
1520 
1521     COLOR_BayerGB2BGR_VNG = 63, 
1522 
1523     COLOR_BayerRG2BGR_VNG = 64, 
1524 
1525     COLOR_BayerGR2BGR_VNG = 65, 
1526 
1527     COLOR_BayerBG2RGB_VNG = COLOR_BayerRG2BGR_VNG, 
1528 
1529     COLOR_BayerGB2RGB_VNG = COLOR_BayerGR2BGR_VNG, 
1530 
1531     COLOR_BayerRG2RGB_VNG = COLOR_BayerBG2BGR_VNG, 
1532 
1533     COLOR_BayerGR2RGB_VNG = COLOR_BayerGB2BGR_VNG, 
1534 
1535     COLOR_BayerBG2BGR_EA = 135, 
1536 
1537     COLOR_BayerGB2BGR_EA = 136, 
1538 
1539     COLOR_BayerRG2BGR_EA = 137, 
1540 
1541     COLOR_BayerGR2BGR_EA = 138, 
1542 
1543     COLOR_BayerBG2RGB_EA = COLOR_BayerRG2BGR_EA, 
1544 
1545     COLOR_BayerGB2RGB_EA = COLOR_BayerGR2BGR_EA, 
1546 
1547     COLOR_BayerRG2RGB_EA = COLOR_BayerBG2BGR_EA, 
1548 
1549     COLOR_BayerGR2RGB_EA = COLOR_BayerGB2BGR_EA, 
1550 
1551     COLOR_BayerBG2BGRA = 139, 
1552 
1553     COLOR_BayerGB2BGRA = 140, 
1554 
1555     COLOR_BayerRG2BGRA = 141, 
1556 
1557     COLOR_BayerGR2BGRA = 142, 
1558 
1559     COLOR_BayerBG2RGBA = COLOR_BayerRG2BGRA, 
1560 
1561     COLOR_BayerGB2RGBA = COLOR_BayerGR2BGRA, 
1562 
1563     COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA, 
1564 
1565     COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA, 
1566 
1567     COLOR_COLORCVT_MAX = 143
1568 }