我试图在我必须处理的各种图片中检测网格的角点。图像可以是倾斜的,有些可能是相对定向的,但我们不能保证所有图像都是这样的。在
为了确定网格的角点,我尝试使用Hough线,但是没有用。有时Hough线不能识别网格的边缘,很难确定绘制的哪些线属于网格的边缘,哪些是网格线。在
然后我决定用轮廓来检测网格的边缘。然而,它会拾取大量的轮廓,并导致同样的问题,即在所有识别出的轮廓中,哪些位于拐角处。在
为了帮助实现这一点,我使用了双边滤波、Canny边缘检测、形态学膨胀和Harris边缘检测,就像我的问题一样。即使应用了所有这些措施,我仍然会得到大量的假角,有时真角没有被识别出来。在
我想知道是否有人能帮我改进角落检测的结果,或者是否有人有一个完全不同的建议可以帮助我解决问题。我们的目标是得到角点,这样我就可以使用10×10的网格来执行单应性,以解释图像中的倾斜。它还将有助于将网格正方形映射到像素空间,这非常有用。在
这是我的代码(命名有点草率,但我稍后会尝试修复它)。还有,是的,我全力以赴在双边过滤,它似乎有助于消除不必要的轮廓和角落。在
当我尝试将Hough线应用于轮廓图像时,我似乎也遇到了一个错误:
error: (-215) img.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) in function cv::HoughLinesStandard
from PIL import Image
import numpy as np
import cv2
import glob
#import images using opencv
images = [cv2.imread(file) for file in glob.glob("SpAMImages/*.jpg")]
for image in images:
#resizes image gotten from folder and performs bilateral filtering
img = cv2.bilateralFilter(cv2.resize(image, (715,715)), 15, 800, 800)
#applies a canny edge detection filter on the images loaded from the folder
gridEdges = cv2.Canny(img, 140, 170)
#apply image dilation
kernel = np.ones((5,5), np.uint8)
gridEdges = cv2.dilate(gridEdges, kernel, iterations=1)
gridEdges = np.float32(gridEdges)
gridEdges = cv2.blur(gridEdges,(10,10))
gridEdges = cv2.cornerHarris(gridEdges,2,3,0.04)
gridEdges = cv2.dilate(gridEdges,None)
img[gridEdges>0.01*gridEdges.max()]=[0,0,255]
#draw contours on current image
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
contourImage, contours, hierarchy =
cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
contour = cv2.drawContours(img, contours, -1, (0,255,0), 3)
'''
def largest_4_sided_contour(thresh, show_contours=True):
contourImage, contours, hierarchy =
cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
contour = cv2.drawContours(img, contours, -1, (0,255,0), 3)
contours = sorted(contours, key = cv2.contourArea, reverse = True)
for cnt in contours[:min(5, len(contours))]:
print(len(cnt))
if len(cnt) == 4:
return cnt
return None
print(largest_4_sided_contour(thresh))
#applies a hough transformation to extract gridlines from the image
-----------THIS LINE BELOW GIVES ME THE ERROR-----------------
lines = cv2.HoughLines(img, 1, np.pi/180, 245)
#iterates through an array of lines gottne from the hough transform
#and draws them unto the image
for i in range(len(lines)):
for rho,theta in lines[i]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img, (x1,y1),(x2,y2),(0,0,255),2)
cv2.imwrite('houghlines.jpg', img)
'''
#resize window because for some reason they are too large.
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.resizeWindow('image', 800, 800)
#display all the images produced from above processes
cv2.imshow('image', img)
cv2.imshow('dilated edges', gridEdges)
#cv2.imshow('contour', contour)
cv2.waitKey(0)
'''
retrieve image size from imported image.
testImageWidth, testImageHeight = img.shape[:2]
print(testImageHeight, testImageWidth)'''
这些是我尝试使用轮廓检测和Harris角点检测来获取角点的一些图像。在
使用轮廓和harris角点检测识别角点:
还有一些我要处理的图像的例子。在
主要示例网格:
有点倾斜的网格:
提前感谢您的帮助!!!在
您正在使用OpenCV在Python中工作,但是我将使用MATLAB和DIPimage来给您一个答案。我希望这个答案是关于概念的,而不是关于代码的。我确信在Python中使用OpenCV可以实现所有这些功能。在
我的目标是找到棋盘的四个角。网格本身是可以猜到的,因为它只是一个等距的划分板,没有必要尝试检测所有的线。四个角给出了透视变换的所有信息。在
检测电路板的最简单方法是识别出它是浅色的,背景是深色的。从灰度值图像开始,我应用一个小的闭合值(我使用了一个直径为7像素的圆,这适用于我用作示例的下采样图像,但是您可能需要适当地增加全尺寸图像的大小)。结果如下:
接下来,我使用Otsu阈值选择进行二进制化,并删除孔(该部分不重要,如果有孔,其余部分也可以工作)。我们现在看到的连接元件对应于电路板和相邻的电路板(或电路板周围的其他白色物体)。在
选择最大的连接组件是一个相当常见的过程。在下面的代码中,我标记图像(标识连接的组件),计算每个连接组件的像素数,然后选择像素最多的一个。在
最后,从这个结果中减去它的腐蚀,我们只剩下板边缘的像素(这里是蓝色覆盖在输入图像上):
我用来寻找角点的技巧非常简单,但是在这里失败了,因为其中一个角不在图像中。在这四条边上使用Hough可能是一种更有效的方法。使用this other answer获得一些关于如何实现这一点的想法和代码。在
在任何情况下,我都会在棋盘的左上角找到离图像左上角最近的边缘像素。其他3个角也一样。这些结果是上图中的红点。在
这里的第三个选项是将轮廓转换为多边形,使用Douglas–Peucker算法简化它,丢弃沿着图像边缘的边(这是图像中不存在角点的地方),并延伸该边任一侧的两条边,以找到图像外部的顶点。在
下面是MATLAB(带DIPimage)代码。在
我有一个答案给你,虽然还不完整,但可能对你有帮助。 我使用Ramer–Douglas–Peucker algorithm来确定轮廓,然后从轮廓中提取矩形框。然后我使用“长方体”区域占图像区域的百分比来删除较小的框。这会删除大部分的垃圾箱。在
下面是我在python代码中所做的一个示例:
寻找轮廓:
使用等高线查找方框:
^{pr2}$要组合这两种方法:
显示图像:
最后一步是合并任何相交的长方体,因为您只对边/角感兴趣,然后只得到面积最大的长方体。查看here以检查如何组合框。在
{我的源代码:^ a3}
图像结果:
正常:
倾斜:
希望这有帮助!在
相关问题 更多 >
编程相关推荐