//********************************************************************************************************************************************************************************************** //********************************************************************************************************************************************************************************************** //********************************************************************************************************************************************************************************************** /// <summary> /// Extract the contour. /// TODO: probably should have this passed in from the puzzle, since it already does this. It was done this way because the contours don't correspond to the correct pixel locations in this cropped version of the image. /// </summary> private void extract_edges() { Bitmap bwImg = PieceImgBw.Bmp; _logHandle.Report(new LogEventInfo(PieceID + " Extracting edges")); if (corners.Size != 4) { return; } VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); CvInvoke.FindContours(new Image<Gray, byte>(bwImg), contours, null, RetrType.List, ChainApproxMethod.ChainApproxNone); bwImg.Dispose(); if (contours.Size == 0) { _logHandle.Report(new LogEventError(PieceID + " No contours found.")); return; } int indexLargestContour = 0; // Find the largest contour double largestContourArea = 0; for(int i = 0; i < contours.Size; i++) { double contourAreaTmp = CvInvoke.ContourArea(contours[i]); if(contourAreaTmp > largestContourArea) { largestContourArea = contourAreaTmp; indexLargestContour = i; } } VectorOfPoint contour = contours[indexLargestContour]; VectorOfPoint new_corners = new VectorOfPoint(); for (int i = 0; i < corners.Size; i++) //out of all of the found corners, find the closest points in the contour, these will become the endpoints of the edges { double best = 10000000000; Point closest_point = contour[0]; for (int j = 0; j < contour.Size; j++) { double d = Utils.Distance(corners[i], contour[j]); if (d < best) { best = d; closest_point = contour[j]; } } new_corners.Push(closest_point); } corners = new_corners; if (PluginFactory.GetGeneralSettingsPlugin().SolverShowDebugResults) { Bitmap colorImg = PieceImgColor.Bmp; Image<Rgb, byte> edge_img = new Image<Rgb, byte>(colorImg); for (int i = 0; i < corners.Size; i++) { CvInvoke.Circle(edge_img, Point.Round(corners[i]), 2, new MCvScalar(255, 0, 0), 1); } _logHandle.Report(new LogEventImage(PieceID + " New corners", edge_img.Bitmap)); colorImg.Dispose(); edge_img.Dispose(); } List<int> sections = find_all_in(contour, corners); //Make corners go in the correct order Point[] new_corners2 = new Point[4]; int cornerIndexUpperLeft = -1; double cornerDistUpperLeft = double.MaxValue; for (int i = 0; i < 4; i++) { new_corners2[i] = contour[sections[i]]; double cornerDist = Utils.DistanceToOrigin(contour[sections[i]]); if(cornerDist < cornerDistUpperLeft) { cornerDistUpperLeft = cornerDist; cornerIndexUpperLeft = i; } } new_corners2.Rotate(-cornerIndexUpperLeft); corners.Push(new_corners2); sections.Rotate(-cornerIndexUpperLeft); Edges[0] = new Edge(PieceID, 0, PieceImgColor, contour.GetSubsetOfVector(sections[0], sections[1]), _logHandle, _cancelToken); Edges[1] = new Edge(PieceID, 1, PieceImgColor, contour.GetSubsetOfVector(sections[1], sections[2]), _logHandle, _cancelToken); Edges[2] = new Edge(PieceID, 2, PieceImgColor, contour.GetSubsetOfVector(sections[2], sections[3]), _logHandle, _cancelToken); Edges[3] = new Edge(PieceID, 3, PieceImgColor, contour.GetSubsetOfVector(sections[3], sections[0]), _logHandle, _cancelToken); }