5

我有以下图片矩形图案板

我正在尝试查找主矩形(白线之间的那些)的像素坐标。我尝试了几件事,但我无法获得足够好的解决方案。解决方案不一定是完美的,如果不是所有矩形都被检测到(尤其是那些非常小的矩形),那也没关系。虽然角落的位置必须尽可能准确,尤其是那些更大的模糊(我正在尝试编写一些简单的 AR 引擎)。

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

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

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

看起来将这两者结合起来会以某种方式产生更好的结果。或者也许有人有不同的想法?

我也在考虑做floodfill,但是很难自动找到确定好的种子点和阈值(背景中可能还有一些其他的白色物体)。此外,我稍后将要针对 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()
4

2 回答 2

3

我相信您的答案在于使用霍夫变换来检测线条,将这些线条延伸到较暗方块之间的中断处,然后寻找相交标记出角落。我在 Matlab 中进行了快速操作,并提出了以下建议,它并不完美,但应该显示出潜力:

% Open image
i = imread('http://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

最终结果:

最后结果

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

于 2012-11-01T09:16:21.380 回答
0

我会尝试以下方法:

  • 霍夫变换检测所有直线
  • 寻找一组平行线,它们是:
    • 有足够的距离
    • 由浅色隔开

有几件事会使您的问题变得比实际需要的更棘手:

  • 透视失真
  • 光照变化,轻微阴影

如果您可以将上述内容最小化,它可能有助于解决问题。

于 2012-10-31T02:13:32.393 回答