gpt4 book ai didi

python - 使用 OpenCV 和 Python 查找数独网格

转载 作者:太空狗 更新时间:2023-10-29 22:17:44 25 4
gpt4 key购买 nike

我正在尝试使用 OpenCV 检测数独游戏中的网格,但我在最后几步中遇到了问题(我猜)。

我正在做的是:

  • 缩小图像
  • 模糊它
  • 应用高通滤波器(双边)
  • 使用自适应阈值对图像进行阈值处理
  • 一些膨胀和腐 eclipse

所有这一切给了我以下图像:

Original image downsampled and blurred.

enter image description here

从现在开始,我需要检测网格,我找到了一些方法来做到这一点,但没有一种方法让我有足够的信心。

第一个是使用 Hough 变换查找直线,但我发现了很多伪直线。

Hough transform.

另一种是使用连接组件,这给了我最好的结果。我试图实现 RANSAC 作为获得正确质心的一种方式,但我没有得到好的结果,也需要一段时间才能得到答案(“一会儿”不到 2 秒,但后来我想在实时视频)。

enter image description here

enter image description here

知道如何做到这一点吗?我的意思是,我怎样才能丢弃错误的质心并开始解决数独问题?

最佳答案

霍夫变换绝对是必经之路。事实上,网格检测是介绍此技术时最流行的示例之一(请参阅 herehere)。

我建议采取以下步骤:

  • 下采样
  • 模糊
  • 应用 Canny(您应该从使用的角度很好地猜测网格线的最小/最大可能长度)
  • 扩张边缘图像(canny发现网格中分隔符的两个边界为不同的边缘,扩张将使它们再次合并)
  • 腐 eclipse (现在我们的边界太粗了,虽然会发现太多线)
  • 应用 HoughLines
  • 合并相似行

在最后一步,您有许多可能的方法,这在很大程度上取决于您之后想要对结果做什么。例如,您可以使用找到的图像创建一个新的边缘图像并再次应用腐 eclipse 和霍夫,您可以使用基于傅里叶的东西,或者您可以简单地通过一些任意阈值(仅举几例)过滤线条。我实现了最后一个(因为从概念上讲这是最容易做到的),这是我所做的(尽管我完全不确定这是否是最好的方法):

  • 为 rho 和 theta 值定义了一个任意阈值
  • 检查边缘在另一个边缘的这些阈值中的次数
  • 从最相似的那一行开始,我开始删除与其相似的行(这样我们将在某种意义上保留相似组中“中间”的行)
  • 剩下的几行是最终的候选人

看代码,玩得开心:

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)

Result

关于python - 使用 OpenCV 和 Python 查找数独网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48954246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com