引子

在文章《opencv-python实际演练(二)军棋自动裁判(1)棋子图像采集设备DIY》介绍了棋子图像采集设备的制作过程。

在文章《opencv-python实际演练(二)军棋自动裁判(3)棋子图像采集设备的改进》对图像采集设备进行了改进。

在实验中发现了一种情形,就是有些棋子上的文字比较靠近边缘,按照以前的算法不能有效地提取目标区域

问题描述

当棋子上的文字比较靠近边缘,采集到的原始图像如下:

边缘检测的结果如下:

从上图可以看出棋子“连长”的轮廓的下边已经向内凹陷,这会导致轮廓的面积变小,在以前的算法中就不能正常的提取这个棋子的图像。改进思路

1 从硬件入手,保证棋子上的文字不要靠近边缘,但如果某些棋子在生产过程中有了偏差,要在采集设备上着手,比较难办

2 从软件着手,整个轮廓还是比较清楚的,只是边上向内凹陷或断裂。这时可以采用求出这个轮廓的外接矩形,并结合面积大小进行判断。

改进部分如下:

 else:#尝试计算外接矩形,当棋子上的笔画确到了外边缘,会造成外轮廓不再是矩形,面积缩小,这时尝试用外接矩形来包住这种外轮廓print("try boundingRect")             x, y, w, h = cv2.boundingRect(c)if w*h > Config.min_area:                approxBox = [[x,y],[x+w,y],[x+w,y+h],[x,y+h]]                approxBox = np.int0(approxBox)                return approxBox else:print("It is too small ,need not to find boundingBox,idx = %d area=%f"%(idx, theArea))return None

改进后的提取效果如下:

完整的python代码

#coding:utf-8
#将两个棋子的内容从棋子图像采集器中提取出来,供下一步的文本识别使用import cv2
import numpy as np
import math#配置数据
class Config:def __init__(self):pass#src = "photo1.jpg"src = "camera/piece1.png"resizeRate = 0.5min_area = 30000min_contours = 8threshold_thresh = 180epsilon_start = 10epsilon_step = 5'''
对坐标点进行排序
@return     [top-left, top-right, bottom-right, bottom-left]
'''
def order_points(pts):# initialzie a list of coordinates that will be ordered# such that the first entry in the list is the top-left,# the second entry is the top-right, the third is the# bottom-right, and the fourth is the bottom-leftrect = np.zeros((4, 2), dtype="float32")# the top-left point will have the smallest sum, whereas# the bottom-right point will have the largest sums = pts.sum(axis=1)rect[0] = pts[np.argmin(s)]rect[2] = pts[np.argmax(s)]# now, compute the difference between the points, the# top-right point will have the smallest difference,# whereas the bottom-left will have the largest differencediff = np.diff(pts, axis=1)rect[1] = pts[np.argmin(diff)]rect[3] = pts[np.argmax(diff)]# return the ordered coordinatesreturn rect# 求两点间的距离
def point_distance(a,b):return int(np.sqrt(np.sum(np.square(a - b))))# 找出外接四边形, c是轮廓的坐标数组
def boundingBox(idx,c,image):if len(c) < Config.min_contours:print("the contours length is  less than %d ,need not to find boundingBox,idx = %d "%(Config.min_contours,idx)) return Noneepsilon = Config.epsilon_startwhile True:approxBox = cv2.approxPolyDP(c,epsilon,True)#显示拟合的多边形#cv2.polylines(image, [approxBox], True, (0, 255, 0), 2)#cv2.imshow("image", image)        if (len(approxBox) < 4):print("the approxBox edge count %d is  less than 4 ,need not to find boundingBox,idx = %d "%(len(approxBox),idx)) return None#求出拟合得到的多边形的面积theArea = math.fabs(cv2.contourArea(approxBox))#输出拟合信息print("contour idx: %d ,contour_len: %d ,epsilon: %d ,approx_len: %d ,approx_area: %s"%(idx,len(c),epsilon,len(approxBox),theArea))if theArea > Config.min_area:if (len(approxBox) > 4):# epsilon 增长一个步长值epsilon += Config.epsilon_step               continueelse: #approx的长度为4,表明已经拟合成矩形了                #转换成4*2的数组approxBox = approxBox.reshape((4, 2))                            return approxBox                else:#尝试计算外接矩形,当棋子上的笔画确到了外边缘,会造成外轮廓不再是矩形,面积缩小,这时尝试用外接矩形来包住这种外轮廓print("try boundingRect")             x, y, w, h = cv2.boundingRect(c)if w*h > Config.min_area:                approxBox = [[x,y],[x+w,y],[x+w,y+h],[x,y+h]]                approxBox = np.int0(approxBox)                return approxBox else:print("It is too small ,need not to find boundingBox,idx = %d area=%f"%(idx, theArea))return None#提取目标区域
def pickOut():# 开始图像处理,读取图片文件image = cv2.imread(Config.src)#print(image.shape)#获取原始图像的大小srcHeight,srcWidth ,channels = image.shape#对原始图像进行缩放#image= cv2.resize(image,(int(srcWidth*Config.resizeRate),int(srcHeight*Config.resizeRate))) #cv2.imshow("image", image)#转成灰度图gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #cv2.imshow("gray", gray)# 中值滤波平滑,消除噪声# 当图片缩小后,中值滤波的孔径也要相应的缩小,否则会将有效的轮廓擦除binary = cv2.medianBlur(gray,7)#binary = cv2.medianBlur(gray,3)  #转换为二值图像ret, binary = cv2.threshold(binary, Config.threshold_thresh, 255, cv2.THRESH_BINARY)#显示转换后的二值图像#cv2.imshow("binary", binary)# 进行2次腐蚀操作(erosion)# 腐蚀操作将会腐蚀图像中白色像素,可以将断开的线段连接起来binary = cv2.erode (binary, None, iterations = 2)#显示腐蚀后的图像#cv2.imshow("erode", binary)# canny 边缘检测binary = cv2.Canny(binary, 0, 60, apertureSize = 3)#显示边缘检测的结果cv2.imshow("Canny", binary)# 提取轮廓contours,_ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 输出轮廓数目print("the count of contours is  %d \n"%(len(contours)))#显示轮廓#cv2.drawContours(image,contours,-1,(0,0,255),1)#cv2.imshow("image", image)#针对每个轮廓,拟合外接四边形,如果成功,则将该区域切割出来,作透视变换,并保存为图片文件for idx,c in enumerate(contours):approxBox = boundingBox(idx,c,image)if approxBox is None: print("\n")continue#显示拟合结果#cv2.polylines(image, [approxBox], True, (0, 0, 255), 2)#cv2.imshow("image", image)# 待切割区域的原始位置,# approxPolygon 点重排序, [top-left, top-right, bottom-right, bottom-left]src_rect = order_points(approxBox)  print("src_rect:\n",src_rect)        # 获取最小矩形包络rect = cv2.minAreaRect(approxBox)box = cv2.boxPoints(rect)box = np.int0(box)box = box.reshape(4,2)box = order_points(box)print("boundingBox:\n",box)         w,h = point_distance(box[0],box[1]), point_distance(box[1],box[2])print("w = %d ,h= %d "%(w,h))# 生成透视变换的目标区域dst_rect = np.array([[0, 0],[w - 1, 0],[w - 1, h - 1],[0, h - 1]],dtype="float32")# 得到透视变换矩阵M = cv2.getPerspectiveTransform(src_rect, dst_rect)#得到透视变换后的图像#warped = cv2.warpPerspective(image, M, (w, h))warped = cv2.warpPerspective(gray, M, (w, h))#将变换后的结果图像写入png文件cv2.imwrite("output/piece%d.png"%idx, warped, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])print("\n")print('over')
#-----------------------------------------------------------------------------------------------#准备捕捉摄像头内容
camera = cv2.VideoCapture(0)print('press s to pickout,q to quit')picIdx = 0
while True:success, frame = camera.read()cv2.imshow('MyCamera',frame)userInput = cv2.waitKey(10) & 0xffif userInput == ord('q'):breakif userInput == ord('s'):print('save pic')Config.src = "camera/pic%d.png"%picIdxcv2.imwrite(Config.src, frame, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])pickOut()

opencv-python实际演练(二)军棋自动裁判(4)棋子图像提取算法的改进相关推荐

  1. opencv-python实际演练(二)军棋自动裁判(2)棋子图像采集效果分析

    引子 在前一篇文章<opencv-python实际演练(二)军棋自动裁判(1)棋子图像采集设备DIY>介绍了棋子图像采集设备的制作过程,在取得棋子图像后发现提取目标区域的效果还不够好,有时 ...

  2. opencv-python实际演练(二)军棋自动裁判(3)棋子图像采集设备的改进

    引子 在文章<opencv-python实际演练(二)军棋自动裁判(1)棋子图像采集设备DIY>介绍了棋子图像采集设备的制作过程. 在文章<opencv-python实际演练(二)军 ...

  3. 关于军棋自动裁判机制的设想

    一般来说,下军棋需要三个人,其中一个人当裁判. 如果只有两个人,又想玩军棋,就需要有一个自动裁判机制. 想到了几种自动裁判的方案 1 图像识别,用手机自动识别棋子上的文字,缺点是拍照,识别耗时较长 补 ...

  4. [Python]Tkinter+Numpy+Matplotlib 进行的简单交互+曲线拟合+图像绘制【已改进】

    用Python的Tkinter.Numpy.Matplotlib库对曲线拟合的一点探索[已改进] 需要用到的库:如标题 三大方面 功能 需要的库 一. 简单交互,获取函数或者样本点 tkinter[p ...

  5. 数字图象处理之二维码图像提取算法(九)

    经过对二维条码的预处理过程,去除了条码中包含的大部分背景信息,初步定定位了QR条码,实现了对二维条码的滤波和二值化处理.但是要提取QR码中的码字信息,还需要经过下面三个步骤: (1) 利用QR码符号特 ...

  6. python+OpenCV图像处理(十二)车牌定位中对图像的形态学组合操作处理

    车牌定位中对图像的形态学组合操作处理 所谓的车牌定位,其中最关键的部分就是对图片的处理,参数的设置,并使之拥有泛化能力. 首先传入图片,在进行大规模的图片处理时,因为无法确定图片的尺寸,所以需要将原始 ...

  7. opencv mat初始化_【OpenCV入门之十二】看起来一样的图像竟然存在这么大的差别!...

    小白导读 学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了[OpenCV入门]系列.新的一年文章的内容进行了很大的完善,主要是借鉴了更多大神的文章,希望让小伙伴更 ...

  8. 【OpenCV + Python】之bitwise_and、bitwise_not,bitwise_xor等图像基本运算(opencv位操作)

    1.灰度图由0~255表示,0为黑,255为白,从位操作的角度出发,纯黑色为0,不是纯黑色为1,所以在一些纯白色,或者纯黑色背景里,可以转为灰度图,利用阈值将非背景色的内容抠出来作为模板,再与原图做位 ...

  9. Python开发的四国军棋AI智能裁判

    目录 1,背景和软件的用途 2,环境介绍 2.1 硬件环境 2.2 软件环境 2.3 素材准备 3,软件功能介绍 4,代码 5,源程序打包下载 1,背景和软件的用途 在玩四国军棋时,除了要四个玩家之外 ...

  10. OpenCV学习笔记(二十六)——小试SVM算法ml OpenCV学习笔记(二十七)——基于级联分类器的目标检测objdect OpenCV学习笔记(二十八)——光流法对运动目标跟踪Video Ope

    OpenCV学习笔记(二十六)--小试SVM算法ml 总感觉自己停留在码农的初级阶段,要想更上一层,就得静下心来,好好研究一下算法的东西.OpenCV作为一个计算机视觉的开源库,肯定不会只停留在数字图 ...

最新文章

  1. K-均值聚类(K-Means) C++代码实现
  2. 在工作中有被动转主动的体会_积极主动应对眼前的一切,就是对自己最好的犒赏...
  3. 使用stream类型的Result实现Ajax
  4. 计网 - 流和缓冲区:缓冲区的 flip 是怎么回事?
  5. windows 搭建python 虚拟环境 写程序_Windows下搭建Python虚拟环境
  6. 使用spring boot+shiro+jwt+mybatis-plus搭建项目框架
  7. uva 10608 FRIENDS
  8. JavaScript中带有示例的Math.PI属性
  9. 【重难点】【Java集合 01】HashMap 和 ConcurrentHashMap
  10. 挑战iOS!小米全新OS发布:22款机型首发
  11. python list去重函数_python 列表函数
  12. Introduction to SQL Server 2005 XML
  13. saas系统是什么_什么是灵活用工智能财税SaaS系统?有什么好处?
  14. tuxedo 强制重启
  15. buildroot external-toolchain的一次踩坑经历
  16. 如何免费在线将pdf转换成jpg图片
  17. Codeforces Round #614 (Div. 2)A. ConneR and the A.R.C. Markland-N
  18. 树链剖分 - 月下“毛景树”(BZOJ 4151)
  19. Ubuntu20.04+Window10双系统开机引导界面美化
  20. Bitmap的getpixel(x,y)和保存到系统图库的方法

热门文章

  1. Android dp方式的屏幕适配工具使用(Android Studio插件方式)
  2. 大饼“U”形底?ETR开始
  3. java 3gp 转mp3_Java利用Jave转换视频格式为3gp
  4. 四大开源3d游戏引擎探究(前言上)
  5. Google, with new Pixel and camera, is serious about devices
  6. 绘制神经元的结构模式图,神经元结构示意图简易
  7. Local Linear Model, Semi Local Linear Model and Local Level Model of TFP.STS
  8. echart实现地球外环绕卫星效果
  9. ECMAScript语法+关键字和保留字
  10. ArcGis基础—shapefile矢量文件与lyr图层文件之间有何区别?