首页 > 解决方案 > 在噪声图像中检测几乎恒定颜色的垂直矩形

问题描述

我有一个带有几个矩形的嘈杂图像。从视觉上讲,矩形非常明显。它们都是垂直或水平的,它们不会以不同的角度出现。它们的颜色/强度也相当恒定。我想检测那些矩形,如果可能的话,检测其他矩形内或顶部/交叉上的矩形。

原图:

原始图像

具有预期矩形/正方形的图像(可能有细垂直线,它们是否被检测为矩形并不重要):

带有预期矩形的图像

从我收集到的信息来看,这是一项相当手动的工作,需要

  1. 将图像转换为 8 位灰度(我的图像已经是灰度)
  2. 添加高斯噪声以平滑图像
  3. 将结果转换为黑白,例如adaptiveThreshold
  4. 扩大结果以尝试加入不再接触的部分
  5. 侵蚀结果以消除小的不需要的噪声
  6. 运行一些算法来检测形状

我目前正在计算以下图像:

黑白阈值图像

结果说明:

我的问题是

请注意,我也尝试过 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()

标签: pythonopencvcontour

解决方案


我这样做了:

1- 带有双边滤波器的滤波图像

2- 应用 Otsu 阈值(并反转二进制图像)

3-打开图像(形态)

4-用打开的图像掩盖过滤后的图像

5-应用精明边缘检测器

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

现在,findContourdrawContour可以对矩形做任何您喜欢的事情。这是我的代码(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);

推荐阅读