OpenCV玩九宫格数独(一) 您所在的位置:网站首页 数独九宫格怎样玩 OpenCV玩九宫格数独(一)

OpenCV玩九宫格数独(一)

2024-06-30 22:51| 来源: 网络整理| 查看: 265

参考:http://blog.csdn.net/xingchenbingbuyu/article/details/70169665

数据:

这里写图片描述

方法

在仔细研究了opencv轮廓提取函数findContours()之后,发现利用轮廓的层级结构会更加简单。

cv2.findContours(image, mode, method[, contours[, hierarchy[, offset] ] ]) → contours, hierarchy

在Python中,findContours()接受如下参数并返回contours和hierarchy。

image 源图像,一般为8为单通道图像,更具体来说,二值图像。其他情况暂且不论。

mode 轮廓检索模式,简要介绍几种:

cv2.RETR_EXTERNAL 只检测外轮廓。对所有轮廓设置hierarchy[i][2]=hierarchy[i][3]=-1cv2.RETR_LIST 提取所有轮廓,并放置在list中,检测到的轮廓不建立等级关系。cv2.RETR_TREE 提取所有轮廓,建立网状的轮廓结构。

method 轮廓的近似办法,是提取轮廓上所有像素点,还是只提取关键的一些点。比如一条线段是提取所有点还是只提取两个端点。

contours 检测到的轮廓,为组成轮廓的点集。hierarchy 下面详述。 hierarchy

什么是层级结构呢?我们检测轮廓的时候,有时候可能会出现其中一个轮廓包含了另外一个轮廓,比如同心圆。这里我们认为外侧轮廓为父轮廓,内侧被包含的为子轮廓。同一级别的又有前一个轮廓和后一个轮廓。总的来说,hierarchy表达的是不同轮廓之间的 关系和联系。

这样,每一个轮廓都会有[Next, Previous, First_Child, Parent]

上面说到,cv2.RETR_EXTERNAL 只检测外轮廓。对所有轮廓设置hierarchy[i][2]=hierarchy[i][3]=-1。由于只检测最外围轮廓,所有检测到的轮廓肯定没有父轮廓和子轮廓,所有层级结构的第三个和第四个元素都设置为-1。

看下图:

这里写图片描述

如果只检测最外围轮廓,那么只会检测到轮廓0、1和2。

如果建立层级关系,以轮廓3为例,那么它的父轮廓是2a,子轮廓是3a,没有前一轮廓和后一轮廓,设为-1。所以它的hierarchy应该是[-1,-1,3a,2a]

如果是轮廓2,那么它的前一轮廓就是1,子轮廓是2a,没有后一轮廓和父轮廓。所以它的hierarchy应该是[-1,1,2a,-1]

上面说了啥

一般来说经过前面的阈值分割得到二值图像,然后从二值图像中提取的轮廓是这样的。这是处理的比较好的情况下:

这里写图片描述

显然最最外面的那个包围所有的就是0号轮廓,里面的九九八十一个小方格就是0号轮廓的子轮廓。而每一个已知数字的轮廓都是对应方格的子轮廓。

提取数字

我们的办法就是先提取方格,然后提取数字。

八十一个小方格有什么特点?父轮廓都是0号轮廓!所以:

boxes = [] for i in range(len(hierarchy[0])): if hierarchy[0][i][3] == 0: boxes.append(hierarchy[0][i])

不记得的可以上翻看一下hierarchy是不是第四个元素表示父轮廓。

然后从小方格中提取数字轮廓。数字轮廓的有什么特点?其父轮廓有子轮廓,也即是说包含子轮廓的小方格里面就有数字。所以:

for j in range(len(boxes)): if boxes[j][2] != -1: x,y,w,h = cv2.boundingRect(contours[boxes[j][2]]) number_boxes.append([x,y,w,h])

不记得的可以上翻看一下hierarchy是不是第三个元素表示子轮廓。不等于-1表示存在。

最后把检测到的数字画出来就可以得到下面的这幅图了。

这里写图片描述

代码 # -*- coding: UTF-8 -*- import cv2 img = cv2.imread('./image/001.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ## 阈值分割 ret,thresh = cv2.threshold(gray,200,255,1) # 转成二值图像,数字变成白色,背景为黑色 ## 对二值图像执行膨胀操作 kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(5, 5)) dilated = cv2.dilate(thresh,kernel) # 扩大白色像素 ## 轮廓提取,cv2.RETR_TREE表示建立层级结构 image, contours, hierarchy = cv2.findContours(dilated,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) ## 提取小方格,其父轮廓都为0号轮廓 boxes = [] for i in range(len(hierarchy[0])): if hierarchy[0][i][3] == 0: boxes.append(hierarchy[0][i]) ## 提取数字,其父轮廓都存在子轮廓 number_boxes = [] for j in range(len(boxes)): if boxes[j][2] != -1: # 存在子轮廓 即里面有数字 #number_boxes.append(boxes[j]) x,y,w,h = cv2.boundingRect(contours[boxes[j][2]]) number_boxes.append([x,y,w,h]) img = cv2.rectangle(img,(x-1,y-1),(x+w+1,y+h+1),(0,0,255),2) cv2.namedWindow("img", cv2.WINDOW_NORMAL); cv2.imshow("img", img) cv2.waitKey(0)


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有