我正在尝试使用OpenCV检测数独谜题中的网格,但我在最后一步(我猜)遇到了麻烦。
我正在做的是:
所有这些都给了我以下图像:
从现在开始,我需要检测网格,我找到了一些如何做到这一点的方法,但没有一个方法让我有足够的信心。
第一个是使用Hough变换找到线,但我发现了很多虚假线。
另一个是使用连接组件,这给了我最好的结果。我试图将RANSAC作为一种获得正确质心的方法,但是我没有取得好成绩并且需要一段时间才能得到答案(“一段时间”不到2秒,但后来我想用它来实时视频)。
知道如何做到这一点?我的意思是,我怎么能丢弃错误的质心并开始解决数独?
答案 0 :(得分:8)
Hough变换绝对是最佳选择。实际上,网格检测是引入此tehcnique时最常见的示例之一(请参阅here和here)。
我建议采取以下步骤:
在最后一步,您有很多可能的方法,这在很大程度上取决于您之后想要对结果做些什么。例如,您可以使用找到的图像创建新的边缘图像并再次应用侵蚀和霍夫,您可以使用基于傅里叶的东西,或者您可以简单地按照某些任意阈值过滤线条(仅举几例)。我实现了最后一个(从概念上说这是最容易做到的),这就是我所做的(尽管我不确定这是否是最好的方法):
查看代码,玩得开心:
import cv2
import numpy as np
filter = False
file_path = ''
img = cv2.imread(file_path)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,90,150,apertureSize = 3)
kernel = np.ones((3,3),np.uint8)
edges = cv2.dilate(edges,kernel,iterations = 1)
kernel = np.ones((5,5),np.uint8)
edges = cv2.erode(edges,kernel,iterations = 1)
cv2.imwrite('canny.jpg',edges)
lines = cv2.HoughLines(edges,1,np.pi/180,150)
if not lines.any():
print('No lines were found')
exit()
if filter:
rho_threshold = 15
theta_threshold = 0.1
# how many lines are similar to a given one
similar_lines = {i : [] for i in range(len(lines))}
for i in range(len(lines)):
for j in range(len(lines)):
if i == j:
continue
rho_i,theta_i = lines[i][0]
rho_j,theta_j = lines[j][0]
if abs(rho_i - rho_j) < rho_threshold and abs(theta_i - theta_j) < theta_threshold:
similar_lines[i].append(j)
# ordering the INDECES of the lines by how many are similar to them
indices = [i for i in range(len(lines))]
indices.sort(key=lambda x : len(similar_lines[x]))
# line flags is the base for the filtering
line_flags = len(lines)*[True]
for i in range(len(lines) - 1):
if not line_flags[indices[i]]: # if we already disregarded the ith element in the ordered list then we don't care (we will not delete anything based on it and we will never reconsider using this line again)
continue
for j in range(i + 1, len(lines)): # we are only considering those elements that had less similar line
if not line_flags[indices[j]]: # and only if we have not disregarded them already
continue
rho_i,theta_i = lines[indices[i]][0]
rho_j,theta_j = lines[indices[j]][0]
if abs(rho_i - rho_j) < rho_threshold and abs(theta_i - theta_j) < theta_threshold:
line_flags[indices[j]] = False # if it is similar and have not been disregarded yet then drop it now
print('number of Hough lines:', len(lines))
filtered_lines = []
if filter:
for i in range(len(lines)): # filtering
if line_flags[i]:
filtered_lines.append(lines[i])
print('Number of filtered lines:', len(filtered_lines))
else:
filtered_lines = lines
for line in filtered_lines:
rho,theta = line[0]
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('hough.jpg',img)