[英]Enhance edges in OpenCV (Java) while removing noise
我正在尝试在 Java 中编写一个 OpenCV 程序,该程序用手机拍摄标记的照片并在标记上找到圆形轮廓。 我已经让它在 Android 模拟器中工作(照片具有完美的照明条件),但无法让它与手机本身一起工作。 这是我要捕获的标记:
在使用转换为灰度、高斯模糊和 Canny 边缘检测器的组合后,我得到了这个 output:
如果我然后尝试在图像上找到轮廓,则返回的轮廓数量非常高(超过 1000 个),但它们并没有关闭(因为边缘似乎太弱了。在原始图像上绘制的轮廓:
这是我用于分段的代码:
Mat processed = new Mat(original.height(), original.width(), original.type());
Imgproc.cvtColor(original, processed, Imgproc.COLOR_RGB2GRAY);
Imgproc.GaussianBlur(processed, processed, new Size(7, 7), 0.1);
Imgproc.Canny(processed, processed, 50, 50*3, 3, false);
我尝试过调整不同的参数(阈值等),但感觉这不是理想的解决方案。 我认为必须有一种方法来增强精明检测器返回的边缘,但我自己还没有找到任何东西。
任何帮助表示赞赏!
您可以查看 opencv 中的dilation
操作以增强边缘。
https://docs.opencv.org/4.x/db/df6/tutorial_erosion_dilatation.html
还可以使用Canny
边缘检测、 approxPolyDP
和minEnclosingCircle
查看下面的示例。 这与您的问题非常接近。
https://docs.opencv.org/4.x/da/d0c/tutorial_bounding_rects_circles.html
https://docs.opencv.org/4.x/d3/dc0/group__imgproc__shape.html#ga0012a5fdaea70b8a9970165d98722b4c
https://docs.opencv.org/4.x/d3/dc0/group__imgproc__shape.html#ga8ce13c24081bbc7151e9326f412190f1
你想要这样的东西吗?
噪声通常存在 - 可以减少 - 您可以使用 AdaptiveThreshold 区分圆圈,然后使用我在下面描述的方法找到圆圈。 关键是,您从相机获得的真实世界图像可能包含一大堆其他圆圈 - 所以最好找到所有圆圈。 比较它们的大小。 找出在颜色、大小和位置方面与您的标记最相似的 4 个圆圈。
一个快速的python代码来区分圆圈:
# Make a gray version
gry = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
# Thresh
ada = cv2.adaptiveThreshold(
gry, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2
)
# Remove noises
out = cv2.medianBlur(ada, 7)
# Invert colors (Not needed)
out = ~out
我测试了 Python 代码,它可以工作; 您可以找到 Java 或 C++ 的等效项。 我试图解释 Java 代码,但我是即时编写的,没有进行测试。 我写的 Java 代码可能有错误,但它确实明白了这一点。 稍作改动可能会奏效。 我还编写了应该将圆圈作为最后一个块的代码。 使用它很棘手,需要调整参数。
Java:
...
Imgproc.cvtColor(im, gry, Imgproc.COLOR_RGBA2GRAY);
Imgproc.adaptiveThreshold(gry, ada, 255,
Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 11, 2);
Imgproc.medianBlur(ada, out, 7);
...
和寻找圈子:
Java:
...
SimpleBlobDetector_Params params = new SimpleBlobDetector_Params();
params.set_filterByCircularity(true);
params.set_minCircularity(0.01f);
params.set_maxArea(50000);//important
SimpleBlobDetector detector = SimpleBlobDetector.create(params);
// List of detected points
MatOfKeyPoint keyPoints = new MatOfKeyPoint();
detector.detect(ada, keyPoints);
// Draw circles on final image
Scalar color = new Scalar(127, 0, 255);
for (KeyPoint key: keyPoints.toList()) {
Imgproc.circle(im, key.pt, (int) (key.size / 2.0f), color, 3/*Thickness*/);
}
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.