检测多模灰度图像上的模糊矩形

pzo*_*pzo 5 opencv image-processing feature-detection

我有以下图片 矩形图案板

我试图找到主矩形的像素坐标(白线之间的像素坐标).我尝试了一些东西,但我无法获得足够好的解决方案.如果没有检测到所有矩形(特别是那些非常小的矩形),解决方案就不一定非常完美.虽然角落位置必须尽可能精确,特别是那些更大的模糊(我正在尝试编写一些简单的AR引擎).

我可以澄清只有4级灰度:0,110,180和255(打印时,没有屏幕会因闪电和阴影而变化)

到目前为止,我尝试了几件事:

  1. 手动多级阈值处理(因为阴影和不同的闪电不起作用)
  2. 自适应阈值处理:2个问题:
    • 它将180和255种颜色组合成白色,0,110组合成黑色
    • 模糊(较大)矩形的边/角位置不精确(它会增加矩形区域的模糊)
  3. sobel边缘检测(模糊矩形的角更尖锐,但它也检测矩形的内边缘,这些边缘轮廓也不总是闭合的

看起来像将这两个想法结合起来会产生更好的结果.或者也许有人有不同的想法?

我也在考虑做洪水填充,但是很难找到确定好的种子点和阈值(背景中可能还有其他一些白色物体).此外,我希望稍后针对GPU进行优化,并且泛洪填充算法对此不太适合.

下面是我到目前为止尝试的一些示例代码:

image = cv2.imread('data/image.jpg');
gray  = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imshow('image', gray) 


adaptive = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 601, 0)
cv2.imshow('adaptive', adaptive)


gradx = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=3)
grady = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=3)
abs_gradx = cv2.convertScaleAbs(grady)
abs_grady = cv2.convertScaleAbs(grady)
grad = cv2.addWeighted(abs_gradx, 0.5, abs_grady, 0.5, 0)

kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
grad = cv2.morphologyEx(grad, cv2.MORPH_OPEN, kernel)
grad = cv2.morphologyEx(grad, cv2.MORPH_CLOSE, kernel)
cv2.imshow('sobel',grad)


#kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(7,7))
#grad = cv2.morphologyEx(grad, cv2.MORPH_OPEN, kernel)
retval, grad = cv2.threshold(grad, 10, 255, cv2.THRESH_BINARY)
cv2.imshow('sobel+morph+thrs',grad)

cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 3

我相信你的答案在于使用霍夫变换来检测线,将这些线延伸以跨越较暗的正方形之间的中断,然后寻找标记出角的相交。我在 Matlab 中进行了快速的操作,并得出了以下结论,它并不完美,但应该显示出潜力:

% Open image
i = imread('https://i.stack.imgur.com/kwcXm.jpg');

% Use a sharpening filter to enhance some of the edges
H = fspecial('unsharp');
i = imfilter(i, H, 'replicate');
% Detect edge segments using canny
BW = edge(i, 'canny');

% Apply hough transform to edges
[H, T, R] = hough(BW, 'RhoResolution', 0.5, 'Theta', -90:0.5:89.5);
% Find peaks in hough transform
P = houghpeaks(H, 5, 'threshold', ceil(0.1*max(H(:))));
% Extract lines from peaks, extending partial lines
lines = houghlines(BW, T, R, P, 'FillGap', 100, 'MinLength', 5);

% Plot detected lines on image
imshow(i); hold on;
for k = 1:length(lines)
   xy = [lines(k).point1; lines(k).point2];
   plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
end
Run Code Online (Sandbox Code Playgroud)

最终结果:

最后结果

显然还有改进的空间,仍有许多线需要检测,但如果调整各种参数不起作用,您可以采用初始结果并搜索更多具有相似角度的线以获得更完整的集合。然后可以从相交处找到角点,提取起来应该很简单。