加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_阳江站长网 (https://www.0662zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > 模式 > 正文

干货 | 手把手教你用115行代码做个数独解析器!

发布时间:2020-09-12 15:47:38 所属栏目:模式 来源:51cto
导读:你也是数独爱好者吗? Aakash Jhawar和许多人一样,乐于挑战新的难题。上学的时候,他每天早上都要玩数独。长大后,随着科技的进步,我们可以让计算机来帮我们解数独了!只需要点击数独的图片,它就会为你填满全部九宫格。 叮~ 这里有一份数独解析教程,等

 干货 | 手把手教你用115行代码做个数独解析器!

你也是数独爱好者吗?

Aakash Jhawar和许多人一样,乐于挑战新的难题。上学的时候,他每天早上都要玩数独。长大后,随着科技的进步,我们可以让计算机来帮我们解数独了!只需要点击数独的图片,它就会为你填满全部九宫格。

叮~ 这里有一份数独解析教程,等待你查收~ 喜欢收藏硬核干货的小伙伴看过来~

我们都知道,数独由9×9的格子组成,每行、列、宫各自都要填上1-9的数字,要做到每行、列、宫里的数字都不重复。

可以将解析数独的整个过程分成3步:

第一步:从图像中提取数独

第二步:提取图像中出现的每个数字

第三步:用算法计算数独的解

第一步:从图像中提取数独

首先需要进行图像处理。

1、对图像进行预处理

首先,我们应用高斯模糊的内核大小(高度,宽度)为9的图像。注意,内核大小必须是正的和奇数的,并且内核必须是平方的。然后使用11个最近邻像素自适应阈值。

proc = cv2.GaussianBlur(img.copy(),(9,9),0)  proc = cv2.adaptiveThreshold(proc,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2) 

为了使网格线具有非零像素值,我们颠倒颜色。此外,把图像放大,以增加网格线的大小。

proc = cv2.bitwise_not(proc,proc)     kernel = np.array([[0。,1.,0.],[1.,1.,1.],[0.,1.,0.]] ,np.uint8)  proc = cv2.dilate(proc,kernel) 

干货 | 手把手教你用115行代码做个数独解析器!     

阈值化后的数独图像

2、找出最大多边形的角

下一步是寻找图像中最大轮廓的4个角。所以需要找到所有的轮廓线,按面积降序排序,然后选择面积最大的那个。

_, contours, h = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  contours = sorted(contours, key=cv2.contourArea, reverse=True)  polygon = contours[0] 

使用的操作符。带有max和min的itemgetter允许我们获得该点的索引。每个点都是有1个坐标的数组,然后[0]和[1]分别用于获取x和y。

右下角点具有最大的(x + y)值;左上角有点最小(x + y)值;左下角则具有最小的(x - y)值;右上角则具有最大的(x - y)值。

bottom_right, _ = max(enumerate([pt[0][0] + pt[0][1] for pt in                        polygon]), key=operator.itemgetter(1))  top_left, _ = min(enumerate([pt[0][0] + pt[0][1] for pt in                    polygon]), key=operator.itemgetter(1))  bottom_left, _ = min(enumerate([pt[0][0] - pt[0][1] for pt in                       polygon]), key=operator.itemgetter(1))  top_right, _ = max(enumerate([pt[0][0] - pt[0][1] for pt in                     polygon]), key=operator.itemgetter(1)) 

现在我们有了4个点的坐标,然后需要使用索引返回4个点的数组。每个点都在自己的一个坐标数组中。

[polygon[top_left][0], polygon[top_right][0], polygon[bottom_right][0], polygon[bottom_left][0]] 

干货 | 手把手教你用115行代码做个数独解析器!

最大多边形的四个角

3、裁剪和变形图像

有了数独的4个坐标后,我们需要剪裁和弯曲一个矩形部分,从一个图像变成一个类似大小的正方形。由左上、右上、右下和左下点描述的矩形。

注意:将数据类型显式设置为float32或‘getPerspectiveTransform’会引发错误。

top_left, top_right, bottom_right, bottom_left = crop_rect[0], crop_rect[1], crop_rect[2], crop_rect[3]  src = np.array([top_left, top_right, bottom_right, bottom_left], dtype= float32 )   side = max([  distance_between(bottom_right, top_right),               distance_between(top_left, bottom_left),              distance_between(bottom_right, bottom_left),                 distance_between(top_left, top_right) ]) 

用计算长度的边来描述一个正方形,这是要转向的新视角。然后要做的是通过比较之前和之后的4个点来得到用于倾斜图像的变换矩阵。最后,再对原始图像进行变换。

dst = np.array([[0, 0], [side - 1, 0], [side - 1, side - 1], [0, side - 1]], dtype= float32 )  m = cv2.getPerspectiveTransform(src, dst)  cv2.warpPerspective(img, m, (int(side), int(side))) 

干货 | 手把手教你用115行代码做个数独解析器!

裁剪和变形后的数独图像

4、从正方形图像中推断网格

从正方形图像推断出81个单元格。我们在这里交换 j 和 i ,这样矩形就被存储在从左到右读取的列表中,而不是自上而下。

(编辑:应用网_阳江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读