static public CvPoint[] DistillContours( CvMat inputMat_grey, int maxContourPoints, CvPoint offset, ContourRetrieval retr = ContourRetrieval.External, ContourChain chain = ContourChain.ApproxSimple) { // maxContourPoints (original name "maxContours"); 5 or 100??!!! // TODO : The CV docs specifically state that the image should be in binary format. Check if it is. //std::vector<std::vector<cv::Point>> updateContours; //std::vector<cv::Vec4i> m_hierarchy; // TODO : Not used currently, but determine if it's gonna be needed for points-tracking // see usage here: http://stackoverflow.com/questions/35418714/opencvsharps-findcontour-returns-wrong-data ContourData contoursData = Filters.FindContours(inputMat_grey, retr, chain, offset); CvPoint[][] contoursFound = contoursData.contours; // original name: "updateContours" if (contoursFound.Length == 0) { return(null); // TODO : cannot process frame, no contours found. Maybe it's time to rethink about that strategy and not simply } // return empty handed!!! double[] contourAreas = contoursData.areas; Point[] newPtV; // find index of max-area contour int index = 0; double maxArea = 0; for (int i = contourAreas.Length - 1; i >= 0; --i) { double area = contourAreas[i]; if (area > maxArea) { index = i; maxArea = area; } } // approximate contour down to 4 points // TODO : This idea sounds weird. Why not check all contours and find one that is best approximated by 4 points??? CvPoint[] biggestContour = contoursFound[index]; newPtV = new Point[biggestContour.Length]; PointOps.CopyCvPointsToPoints(biggestContour, newPtV); //PointOps.CopyCvPointsToGenericPointsArray( biggestContour, newPtV ); double epsilon = 1; while (newPtV.Length > maxContourPoints) { newPtV = Cv2.ApproxPolyDP(newPtV, epsilon++, true); // TODO : Is incrementing epsilon by 1 a bit stupid? Maybe increment exponentially? } // finally CvPoint[] cvPoints = new CvPoint[newPtV.Length]; PointOps.CopyPointsToCvPoints(newPtV, cvPoints); return(cvPoints); }
// The OpenCVSharp is for some reason complicated and needs to be abstracted. So here is the abstraction layer... // TODO : The CV docs specifically state that the image should be in binary format. Check if it is. // see usage here: http://stackoverflow.com/questions/35418714/opencvsharps-findcontour-returns-wrong-data static public ContourData FindContours(CvMat input, ContourRetrieval retrievalMode, ContourChain chainMode, CvPoint offset, double minArea = 0) { List <CvPoint[]> pointsArrays = new List <CvPoint[]>(); List <double> areas = new List <double>(); CvSeq <CvPoint> contoursRaw; using (CvMemStorage storage = new CvMemStorage()) { Cv.FindContours(input, storage, out contoursRaw, CvContour.SizeOf, retrievalMode, chainMode, offset); using (CvContourScanner scanner = new CvContourScanner(input, storage, CvContour.SizeOf, retrievalMode, chainMode, offset)) { foreach (CvSeq <CvPoint> c in scanner) { List <CvPoint> points = new List <CvPoint>(); //Some contours have negative area! double area = c.ContourArea(); if (Math.Abs(area) >= minArea) { areas.Add(area); foreach (CvPoint p in c.ToArray()) { points.Add(p); } pointsArrays.Add(points.ToArray()); } } } } ContourData data = new ContourData(); data.contours = pointsArrays.ToArray(); data.areas = areas.ToArray(); return(data); }