【发布时间】:2018-07-01 01:48:04
【问题描述】:
我正在尝试检测我必须处理的各种图片中的网格角。图像可能会倾斜,有些可能相对较好的方向,但我们不能保证所有图像都会这样。
为了确定网格的角,我尝试使用霍夫线但无济于事。有时霍夫线不能识别网格的边缘,很难确定绘制的线中哪些属于网格边缘,哪些是网格线。
然后我决定使用轮廓来检测网格的边缘。然而,它会检测到许多轮廓,并导致识别所有已识别轮廓中哪些位于拐角处的问题。
为了帮助解决这个问题,我使用了双边过滤、Canny 边缘检测、形态膨胀和 Harris 边缘检测,正如在与我的问题类似的问题中看到的那样。即使在应用了所有这些措施之后,我仍然会得到大量的假角,并且有时无法识别出真角。
我想知道是否有人有办法让我改进角点检测的结果,或者是否有人有完全不同的建议可能有助于解决我的问题。目标是获得角落,以便我可以使用 10 X 10 网格执行单应性,以解决图像中的倾斜问题。它还有助于将网格正方形映射到像素空间,这非常有用。
这是我的代码(命名有点草率,但我稍后会尝试修复它)。另外,是的,我全力以赴进行双边过滤,它似乎有助于消除不必要的轮廓和角落。
当我尝试将霍夫线应用于轮廓图像时,我似乎也遇到了一个错误:
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 角点检测获得角点的一些图像。
使用轮廓和哈里斯角检测识别角:
还有一些我必须使用的图像示例。
主要示例网格:
有点倾斜的网格:
提前感谢您的帮助!!!
【问题讨论】:
-
结合你的轮廓和霍夫线的方法应该能够提供帮助。只需将轮廓本身(未填充,只是轮廓)绘制到空白图像上。在 this 图像上使用 Hough 变换应该会给你四行。然后你可以简单地找到这四条线相交的角。请参阅我的回答 here 了解更多信息。
-
哇,谢谢,您的回答解决了我在确定角落时遇到的很多问题。我会尝试你的建议并更新结果。
-
酷,祝你好运! Lmk 如果你有问题。此外,您可以查看我构建的一系列霍夫线相关函数here on GitHub,这可能会有所帮助。我没有时间在这里写一个实际的解决方案,但如果你真的让它工作,回答你自己的问题也不错,这样其他人可能会偶然发现它! :) 此外,在轮廓上使用霍夫线的好处是,即使拐角在图像之外,您仍然可以计算实际的拐角。
-
看到您的编辑错误,霍夫线仅适用于 the docs 中所述的 8 位图像,因此您可能正在向其中发送浮动图像或其他内容?
-
@AlexanderReynolds 嘿 :))我使用了您链接的答案中的霍夫线解决方案,它运行良好,但我遇到了一些问题。对于我尝试处理的某些图像,我不断收到运行时警告,因此必须关闭程序。即使集群位于角落,从集群中获得的一些中心也会出现在边缘的中间。我猜它可能是从两个不同的集群中绘制中心?如果有帮助,我可以编辑我的问题以更好地解释我在说什么。
标签: python opencv image-processing opencv-contour corner-detection