OpenCV Java版Hough Guil检测器参数调优与精准检测求助
Java版OpenCV GeneralizedHoughGuil检测器参数调优与精准检测问题
我正在使用Java版OpenCV调优GeneralizedHoughGuil检测器,但官方教程对多数参数缺乏详细说明,导致难以实现精准检测。以下是我的检测器实现代码:
public class TemplateHoughGuilDetector { public static PositionVector runHoughGuilDetection(Mat template, Mat blurred) { var houghDetector = Imgproc.createGeneralizedHoughGuil(); houghDetector.setLevels(1500); houghDetector.setScaleThresh(200); houghDetector.setPosThresh(200); houghDetector.setAngleThresh(1000); houghDetector.setDp(15); houghDetector.setMinDist(.1); houghDetector.setAngleStep(.1); houghDetector.setAngleEpsilon(1); houghDetector.setMinAngle(0); houghDetector.setMaxAngle(360); houghDetector.setMinScale(.99); houghDetector.setMaxScale(1.01); houghDetector.setScaleStep(.01); houghDetector.setXi(90.0); PositionVector bestVoted = mostLikelyHoughDetectionWithScaleTolerance(template, blurred, houghDetector); return bestVoted; } private static PositionVector mostLikelyHoughDetectionWithScaleTolerance(Mat template, Mat blurred, GeneralizedHough houghDetector) { houghDetector.setTemplate(template); var positions = new Mat(); var votes = new Mat(); houghDetector.detect(blurred, positions, votes); var positionVectors = new ArrayList<PositionVector>(); for(int i = 0; i < positions.width(); i++) { var posData = positions.get(0, i); var voteData = votes.get(0, i); positionVectors.add(new PositionVector(posData[0], posData[1], posData[2], posData[3], voteData[0], voteData[1], voteData[2])); } final double maxPosVote = positionVectors.stream().map(PositionVector::posVotes).max(Double::compareTo).orElse(1.0); final double maxRotVote = positionVectors.stream().map(PositionVector::rotVotes).max(Double::compareTo).orElse(1.0); final double maxScaleVote = positionVectors.stream().map(PositionVector::scaleVotes).max(Double::compareTo).orElse(1.0); var bestScore = positionVectors.stream().map(v -> v.voteMagSqr(maxPosVote, maxRotVote, maxScaleVote)).max(Double::compareTo); MatOfPoint bestVoted = null; var output = new Mat(); Imgproc.cvtColor(blurred, output, Imgproc.COLOR_GRAY2BGR); var contours = new ArrayList<MatOfPoint>(); for (PositionVector v:positionVectors) { var rect = new RotatedRect(new Point(v.x(), v.y()), new Size(499, 499), v.rotation()); var points = new Point[4]; rect.points(points); final var contour = new MatOfPoint(points); if(v.voteMagSqr(maxPosVote, maxRotVote, maxScaleVote) == bestScore.get()) { bestVoted = contour; } contours.add(contour); } var drawMe = ContourOntoImage.createImageWithContours(output, contours, new Scalar(0, 0, 255), 1); if(bestVoted != null) { drawMe = ContourOntoImage.createImageWithContours(drawMe, List.of(bestVoted), new Scalar(255.0, 0.0, 255.0), 2); } Imgcodecs.imwrite("test_contours.png", drawMe); return positionVectors.stream().filter(pv -> pv.voteMagSqr(maxPosVote, maxRotVote, maxScaleVote) == bestScore.get()).findFirst().orElse(null); } }
测试代码
@Test public void perfectSquareRotNotScaledGuil() { loadLocally(); Mat template = makeRectangularGrayBigTemplate(); Mat blurred = makeRotatedBlurredRectangularGrayImage(); PositionVector bestVoted = TemplateHoughGuilDetector.runHoughGuilDetection(template, blurred); var loc = new Point(bestVoted.x(), bestVoted.y()); var rot = bestVoted.rotation(); var scale = bestVoted.scale(); assertThat(loc, is(closeToPoint(new Point(500, 500)).toWithin(1e-7))); assertThat(rot, is(closeTo(5.0, 1.0))); assertThat(scale, is(equalTo(1.0))); } private static Mat makeRotatedBlurredRectangularGrayImage() { Mat image = makeRotatedRectangularGrayImage(); var blurred = new Mat(); Imgproc.blur(image, blurred, new Size(3,3)); return blurred; } private static Mat makeRectangularGrayBigTemplate() { var template = new Mat(501, 501, CvType.CV_8UC1, new Scalar(255)); Imgproc.rectangle(template, new Point(1, 1), new Point(499, 499), new Scalar(0), Imgproc.FILLED); return template; } private static Mat makeRotatedRectangularGrayImage() { var image = new Mat(1000, 1000, CvType.CV_8UC1, new Scalar(255)); var rectangle = new RotatedRect(new Point(500, 500), new Size(499.0, 499.0), 5); var vertices = new Point[4]; rectangle.points(vertices); var matOfPoints = new MatOfPoint(vertices); Imgproc.fillConvexPoly(image, matOfPoints, new Scalar(0)); return image; }
测试结果
测试后得到检测结果图:![包含异常归一化分数轮廓的检测结果图]
模板图:![模板图]
参数测试总结
- Levels参数未产生明显影响
- 调整阈值会增加无效检测,但仍无法得到精准结果
- DP参数能影响无效检测数量,但未找到官方说明
- MinDist参数会提升位置检测密度,符合预期
- AngleStep、AngleEpsilon参数无法得到正确角度
- MinAngle、MaxAngle、MinScale、MaxScale、ScaleStep参数含义明确
- 修改Xi参数至10.0或45.0时无法检测到目标,对该参数的具体含义存在疑问
求助内容
- 如何调整参数使测试用例得到准确的位置与角度?
- 获取GeneralizedHoughGuil检测器各参数的详细说明。
实际需求补充
我的实际需求是基于DXF模板检测带镂空面板类物体(如图:![工作台上的零件]),DXF模板如图:![DXF模板图]。目前已能通过轮廓检测实现,但需不依赖轮廓,基于镂空部分完成精准检测。
内容的提问来源于stack exchange,提问作者vextorspace
相关产品推荐
相关产品推荐

