前言

在此之前,OpenCV玩九宫格数独(一)和(二)分别介绍了如何从九宫格图片中提取出已知数字和如何用knn训练数字识别模型。在这些前期工作都已经完成的基础上,接下来我们需要做什么呢?

我们要做的有三部分:

1.生成九宫格,也就是生成一个9x9的矩阵,把已知的数字按照图片中的位置填到矩阵中的相应位置,其他位置全部置0。

2.编写数独求解算法,对九宫格矩阵进行求解。

3.把填完的九宫格重新填充到图片中去。

我们仍然是一步一步来说。

生成九宫格

这里就需要用到我们之前两篇的内容了,生成九宫格的步骤如下:

1.从九宫格图片中提取数字(第一篇内容)

2.用训练的数字识别模型对上一步的数字进行识别。

这里需要注意的是,提取之后的数字,要按照训练模型之前的数据处理方式进行处理,然后输入knn模型识别。识别效果如下图所示。就像上一篇结尾说的一样,本文用不到一百个样本训练出来的模型仅仅能保证在本文的示例图片上取得完美效果。其他情况下不作保证。如果想要得到更完美的数字识别模型,请优化数据预处理方式和加大数据量。


3.按照位置顺序把数字填入相应的矩阵位置中。

矩阵初始化为零阵

soduko = np.zeros((9, 9),np.int32)

然后按照位置求解数字在矩阵中所处的位置


## 求在矩阵中的位置    soduko[int(y/box_h)][int(x/box_w)] = number

得到的矩阵如下所示:

跟上面的图片比较一下,是不是位置一样呢?

编写算法求解九宫格矩阵

数独的求解算法有很多种,热爱数独的且热爱数学的人对此进行了深入研究,提出了各种各样的算法。这里用的是传说中的回溯法。回溯法具体内容感兴趣的可以自行搜索,我这里只是用,没有深究。

至于为什么用这个算法?。。。因为我在stackoverflow上找到了可用的代码(捂脸逃…)

代码里标注了出处:

## 数独求解算法,回溯法。来源见下面链接,有细微改动。
## http://stackoverflow.com/questions/1697334/algorithm-for-solving-sudoku
def findNextCellToFill(grid, i, j):for x in range(i,9):for y in range(j,9):if grid[x][y] == 0:return x,yfor x in range(0,9):for y in range(0,9):if grid[x][y] == 0:return x,yreturn -1,-1def isValid(grid, i, j, e):rowOk = all([e != grid[i][x] for x in range(9)])if rowOk:columnOk = all([e != grid[x][j] for x in range(9)])if columnOk:# finding the top left x,y co-ordinates of the section containing the i,j cellsecTopX, secTopY = 3 *int(i/3), 3 *int(j/3)for x in range(secTopX, secTopX+3):for y in range(secTopY, secTopY+3):if grid[x][y] == e:return Falsereturn Truereturn Falsedef solveSudoku(grid, i=0, j=0):i,j = findNextCellToFill(grid, i, j)if i == -1:return Truefor e in range(1,10):if isValid(grid,i,j,e):grid[i][j] = eif solveSudoku(grid, i, j):return True# Undo the current cell for backtrackinggrid[i][j] = 0return False

然后我们根据算法对前面生成的数独求解。只需要这么一句就行:

solveSudoku(soduko)

这里为了便于观察,分别原始数独求解后的数独,为了验算,输出结果数独的每行每列的和,如果求解正确,每行每列和都应该等于1+2+...+9=45

print("\n生成的数独\n")
print(soduko)
print("\n求解后的数独\n")## 数独求解
solveSudoku(soduko)print(soduko)
print("\n验算:求每行每列的和\n")
row_sum = map(sum,soduko)
col_sum = map(sum,zip(*soduko))
print(list(row_sum))
print(list(col_sum))

输出的结果如下:

最后两行可以看到各行各列的和确实都是45。数独求解成功。

在黑窗口里看最后的数独可能不那么友好,接下来我们就把生成的九宫格填充到图片里来看。

填充图片九宫格

我们只需要在图片中九宫格中相应的位置写相应的数字就可以了,这一部分乏善可陈。还是直接看代码和效果图吧。

## 把结果按照位置填入图片中
for i in range(9):for j in range(9):x = int((i+0.25)*box_w)y = int((j+0.5)*box_h)cv2.putText(img,str(soduko[j][i]),(x,y), 3, 2.5, (0, 0, 255), 2, cv2.LINE_AA)
#print(number_boxes)
cv2.namedWindow("img", cv2.WINDOW_NORMAL);
cv2.imshow("img", img)
cv2.waitKey(0)

最后的效果你应该在预告篇就看到过了。为了便于对比,保留了上一步数字识别的结果。

尾声

到此,整个opencv玩数独项目告一段落。容我感慨几句。

玩数独项目最早可以追溯到一年前,那时候就开始尝试用C++来对数独图片进行处理,但是最终受限于当时的水平和心态,只完成了一小半。为什么说心态呢?因为那时候很多东西不会的也不敢去尝试,如果当时敢于尝试,畏难心理没有那么重的话,也许这个项目会提前很久完成。

其实我本来最擅长的是C++的,然而最近用python越来越顺手了。这个项目坐下来受益最大的显然是我自己。分享出来,感兴趣的人也许会有很多,但是真正会去做一遍的应该没有几个。会完整做下来的应该更是寥寥无几。

这个小项目都对高手来说也许不算什么,但是对于初学Python和opencv的人来说应该是一个不错的锻炼。希望有人能做一遍,能做下来的相信会做的更好。欢迎感兴趣的人来一起交流学习。

代码

github:https://github.com/LiuXiaolong19920720/opencv-soduko


公众号CVPy,分享OpenCV和Python的实战内容。每一篇都会放出完整的代码。欢迎关注。

OpenCV玩九宫格数独(三):九宫格生成与数独求解相关推荐

  1. 数独终局生成及残局求解

    文章目录 一.项目地址 二.各模块开发时间预估 三.学习过程.解题思路 3.1 开发语言及运行环境 3.2 项目要求分析 3.2.1 需求建模 3.2.2 数据流设计方法 3.3 解题思路 3.3.1 ...

  2. python数独伪代码回溯法_数独的暴力回溯解法和Python GUI

    数独起源于18世纪初瑞士数学家欧拉等人研究的拉丁方阵,20世纪70年代,经过美国及日本学者的推广和改良,定名为数独(Sudoku),大致的意思是"独个的数字"或"只出现一 ...

  3. OpenCV 玩九宫格数独(二):knn 数字识别

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:刘潇龙 前言 首先需要说明,这里所说的数字识别不是手写数字识别! 但凡对机器学习有所了解的人,相信看到数 ...

  4. (附代码)数独大作业【读取数独,解数独,生成唯一解数独(随机,特定形状,不同难度生成),玩数独】

    注:未经同意不要转载. 上学期简单的做了一个数独程序,实现了一些功能,想简单的为大家提供的思路. 为了避免某些情况出现,具体代码暂时先不发了,有不太懂的地方可以评论提问啊. 下面是我的具体报告: 一, ...

  5. 【算法分析】回溯法解数独(九宫格)算法

    这篇文章,是来详细介绍怎样写出一个算法,来解出所有的数独问题.算法的程序运行时间,缩减在了毫秒级别.等到这篇文章结束,我会抽时间写一篇文章,介绍如何生成一个随机的唯一解的数独问题.另外,为了做图形方便 ...

  6. 人效九宫格|三个提升路径,三种管理模式,让人效实时可量化

    文|盖雅学苑‍‍ 本文共5202字 在经济高速发展的过去,企业更关注机遇,当经济发展速度进入新常态时,企业更关注效率.在盖雅工场发布的<企业人效管理白皮书>中的数据显示,69.9%的企业依 ...

  7. 问题 B: 数独(九宫格经典问题+dfs)

    问题 B: 数独(九宫格经典问题+dfs) 题目描述 这个游戏只有一个规则: 将格子填满使得每一行,每一列,和每一个小的九宫格,恰好包含1-9这9个数字 正是由于规则简单而又变化多端,数独一时间风靡全 ...

  8. 【OpenCV 学习之路】(8)数独提取之一

    写在前面: 关于本次的数独识别项目,我先说明下情况: 这是本人18年6月份做的,现在把当时的笔记整理出来(口吻的描述是以当时的时间来描述). 这个数独的项目分别做了两次, 第一次做的还没做完,第二次可 ...

  9. C语言简单数独游戏终盘生成

    前言 这一篇文章介绍的是移动变换法,有详细的移动变化法的图文解析,在文末有完整的可用于查看移动变换法生成数独终盘过程的代码 实现思路 移动变换法这一方法是很简单的一种方法,实现起来也比较容易,但同时它 ...

最新文章

  1. 清华团队将Transformer用到3D点云分割
  2. 网站jcms流程分析
  3. C++尽量以const,enum,inline替换#define
  4. Elasticsearch概述、ES概念、什么是搜索、全文检索、Elasticsearch功能,什么是distributed document store(来自网络+学习资料)
  5. config.class.php,Config.class.php
  6. 异常的总结 java 1615387415
  7. android 半边圆角背景,Android UI(一)Layout 背景局部Shape圆角设计
  8. Android 学习笔记【基础扫盲篇】
  9. 区块链开发公司:区块链技术如何改变个人数据安全
  10. python微信头像_转:20行Python代码给微信头像戴帽子
  11. Microsoft Silverlight 4 Tools for Visual Studio 2010
  12. 锯齿波FMCW雷达目标检测原理
  13. 人类历史的进程vs互联网的进程
  14. Linux LVM全面实践
  15. PTA题目:7-9 抢红包 (25分)
  16. storm源码分析研究(十三)
  17. [导入]心若一动 泪就一行(转)
  18. others:南怀瑾先生讲:呵呼嘘吹嘻呬六字诀养生诀的要领---《南怀瑾与彼得圣吉》
  19. 【98期】面试官:给我说说你对Java GC机制的理解?
  20. 模型无关的时间序列度量方法及特征

热门文章

  1. 替换word中英文““为中文双引号“”,且保持西文为Time NewRome
  2. python人工智能方向如何入门_Python人工智能入门课程大纲;.pdf
  3. 答辩PPT的美化以及配色
  4. 用MATLAB求解数据拟合问题
  5. 使用realsensed455修改分辨率问题
  6. 社交里互评、点赞的实现
  7. python恶搞代码-Python里最搞怪的招式是啥 |初探生成器
  8. 人脸数据集汇总 MS1M-IBUG MS1M-ArcFace MS1M-RetinaFace 等
  9. k8s学习(二十) helm的基本使用
  10. vmware intel-vt