python - 在噪声图像中检测几乎恒定颜色的垂直矩形
问题描述
我有一个带有几个矩形的嘈杂图像。从视觉上讲,矩形非常明显。它们都是垂直或水平的,它们不会以不同的角度出现。它们的颜色/强度也相当恒定。我想检测那些矩形,如果可能的话,检测其他矩形内或顶部/交叉上的矩形。
原图:
具有预期矩形/正方形的图像(可能有细垂直线,它们是否被检测为矩形并不重要):
从我收集到的信息来看,这是一项相当手动的工作,需要
- 将图像转换为 8 位灰度(我的图像已经是灰度)
- 添加高斯噪声以平滑图像
- 将结果转换为黑白,例如
adaptiveThreshold
- 扩大结果以尝试加入不再接触的部分
- 侵蚀结果以消除小的不需要的噪声
- 运行一些算法来检测形状
我目前正在计算以下图像:
结果说明:
- 没有噪音(尽管在其他一些图像上我仍然会在这里和那里得到小块噪音)
- 矩形并非全部闭合
- 左边的一个小矩形/正方形现在可能很难在垂直线旁边发现
我的问题是
- 有一个更好的方法吗?
- 如何继续检测当前尚未全部关闭的矩形?知道它们总是水平或垂直并且颜色几乎不变应该会有所帮助。
请注意,我也尝试过 Canny,但效果不佳。
我将 OpenCV 4.1.2 与 Python 3.7.2 一起使用。这是我当前的代码:
import cv2
import numpy
import platform
import sys
print("Python version: {}\nOpenCV version: {}".format(platform.python_version(), cv2.__version__))
# Used variables:
# For gaussian blur
gaussianBlur = 11
# For threshold
meanType = cv2.ADAPTIVE_THRESH_MEAN_C
meanTypeName = "Mean"
blockSize = 17
c = 3
# For close/open
growSize = 6
shrinkSize = 3
# Import image.
imageName = sys.argv[1]
image = cv2.imread(imageName)
# Convert to gray scale 8 bit, blur then take threshold.
grayscaled = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(grayscaled, (gaussianBlur, gaussianBlur), 0)
thresholded = cv2.adaptiveThreshold(blurred, 255, meanType, cv2.THRESH_BINARY_INV, blockSize, c)
# Close then Open to try to "close" the rectangles and remove noise.
rectClose = cv2.getStructuringElement(cv2.MORPH_RECT, (growSize,growSize))
rectOpen = cv2.getStructuringElement(cv2.MORPH_RECT, (shrinkSize,shrinkSize))
mask = cv2.morphologyEx(thresholded, cv2.MORPH_CLOSE, rectClose)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, rectOpen)
result = mask
# Compute contours and display them on the gray scale image
contours, hierarchy = cv2.findContours(result, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
resultWithContours = grayscaled
cv2.drawContours(resultWithContours, contours, -1, (0,0,255), cv2.FILLED)
# Display threshold image and original with detected contours.
both = numpy.concatenate([result, resultWithContours], axis=0)
cv2.imshow("{} Block Size={} C={}".format(meanTypeName, blockSize, c), both)
# Save both threshold and original with detected contours.
cv2.imwrite("{}_result_{}_blockSize{}_c{}.jpg".format(imageName, meanTypeName, blockSize, c), result)
cv2.imwrite("{}_contours_{}_blockSize{}_c{}.jpg".format(imageName, meanTypeName, blockSize, c), resultWithContours)
cv2.waitKey(0)
cv2.destroyAllWindows()
解决方案
我这样做了:
1- 带有双边滤波器的滤波图像
2- 应用 Otsu 阈值(并反转二进制图像)
3-打开图像(形态)
4-用打开的图像掩盖过滤后的图像
5-应用精明边缘检测器
现在,findContour
您drawContour
可以对矩形做任何您喜欢的事情。这是我的代码(C++):
Mat img__1, img__2,img__ = imread("E:/s.jpg", 0);
Mat filtered;
bilateralFilter(img__, filtered, 9, 5, 5);
imshow("filtered", filtered);
threshold(filtered, img__1, 0, 255, THRESH_OTSU);
img__1 = 255 - img__1;
imshow("Binarized by Otsu", img__1);
int k = 3;
erode(img__1, img__1, Mat::ones(k, k, CV_8U), Point(-1, -1), 1);
dilate(img__1, img__1, Mat::ones(k, k, CV_8U), Point(-1, -1), 1);
imshow("Dots removed", img__1);
img__1.convertTo(img__1, CV_32F);
filtered.convertTo(filtered, CV_32F);
img__1 = img__1 / 255.0;
multiply(filtered, img__1, img__1,1, CV_32F);
img__1.convertTo(img__1, CV_8U);
imshow("masked denoised image", img__1);
Mat canny_1;
Canny(img__1, canny_1, 30, 100);
imshow("final image", canny_1);
waitKey(0);
推荐阅读
- html - 单击表单输入元素时转到其他页面
- graphql - 我应该如何在 Gatsby 中存储数据(100 x 2 数组)?
- swift - 使用 CLGeocoder() 将地址转换为坐标的函数未正确返回坐标
- xamarin - Xamarin:无法将存档上传到 AppStore
- node.js - mongodb $addfields 条件不起作用
- service - 实施 'com.google.android.gms:play-services-ads:19.2.0'
- asp.net-core - 如何绕过 .NET Core 2.2 和 3.1 错误处理并显示标准 IIS 状态代码页?
- yarnpkg - 无法“纱线”升级到@react-native-firebase/firestore@7.3.0
- android - 如何允许谷歌播放服务(FCM 推送通知)在受限网络中运行
- python-3.x - 刚开始使用 Python 并使用 Python 完成自动化无聊的工作。关于清理我的代码有什么建议吗?