opencv-python实际演练(二)军棋自动裁判(4)棋子图像提取算法的改进
引子
在文章《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)棋子图像提取算法的改进相关推荐
- opencv-python实际演练(二)军棋自动裁判(2)棋子图像采集效果分析
引子 在前一篇文章<opencv-python实际演练(二)军棋自动裁判(1)棋子图像采集设备DIY>介绍了棋子图像采集设备的制作过程,在取得棋子图像后发现提取目标区域的效果还不够好,有时 ...
- opencv-python实际演练(二)军棋自动裁判(3)棋子图像采集设备的改进
引子 在文章<opencv-python实际演练(二)军棋自动裁判(1)棋子图像采集设备DIY>介绍了棋子图像采集设备的制作过程. 在文章<opencv-python实际演练(二)军 ...
- 关于军棋自动裁判机制的设想
一般来说,下军棋需要三个人,其中一个人当裁判. 如果只有两个人,又想玩军棋,就需要有一个自动裁判机制. 想到了几种自动裁判的方案 1 图像识别,用手机自动识别棋子上的文字,缺点是拍照,识别耗时较长 补 ...
- [Python]Tkinter+Numpy+Matplotlib 进行的简单交互+曲线拟合+图像绘制【已改进】
用Python的Tkinter.Numpy.Matplotlib库对曲线拟合的一点探索[已改进] 需要用到的库:如标题 三大方面 功能 需要的库 一. 简单交互,获取函数或者样本点 tkinter[p ...
- 数字图象处理之二维码图像提取算法(九)
经过对二维条码的预处理过程,去除了条码中包含的大部分背景信息,初步定定位了QR条码,实现了对二维条码的滤波和二值化处理.但是要提取QR码中的码字信息,还需要经过下面三个步骤: (1) 利用QR码符号特 ...
- python+OpenCV图像处理(十二)车牌定位中对图像的形态学组合操作处理
车牌定位中对图像的形态学组合操作处理 所谓的车牌定位,其中最关键的部分就是对图片的处理,参数的设置,并使之拥有泛化能力. 首先传入图片,在进行大规模的图片处理时,因为无法确定图片的尺寸,所以需要将原始 ...
- opencv mat初始化_【OpenCV入门之十二】看起来一样的图像竟然存在这么大的差别!...
小白导读 学习计算机视觉最重要的能力应该就是编程了,为了帮助小伙伴尽快入门计算机视觉,小白准备了[OpenCV入门]系列.新的一年文章的内容进行了很大的完善,主要是借鉴了更多大神的文章,希望让小伙伴更 ...
- 【OpenCV + Python】之bitwise_and、bitwise_not,bitwise_xor等图像基本运算(opencv位操作)
1.灰度图由0~255表示,0为黑,255为白,从位操作的角度出发,纯黑色为0,不是纯黑色为1,所以在一些纯白色,或者纯黑色背景里,可以转为灰度图,利用阈值将非背景色的内容抠出来作为模板,再与原图做位 ...
- Python开发的四国军棋AI智能裁判
目录 1,背景和软件的用途 2,环境介绍 2.1 硬件环境 2.2 软件环境 2.3 素材准备 3,软件功能介绍 4,代码 5,源程序打包下载 1,背景和软件的用途 在玩四国军棋时,除了要四个玩家之外 ...
- OpenCV学习笔记(二十六)——小试SVM算法ml OpenCV学习笔记(二十七)——基于级联分类器的目标检测objdect OpenCV学习笔记(二十八)——光流法对运动目标跟踪Video Ope
OpenCV学习笔记(二十六)--小试SVM算法ml 总感觉自己停留在码农的初级阶段,要想更上一层,就得静下心来,好好研究一下算法的东西.OpenCV作为一个计算机视觉的开源库,肯定不会只停留在数字图 ...
最新文章
- K-均值聚类(K-Means) C++代码实现
- 在工作中有被动转主动的体会_积极主动应对眼前的一切,就是对自己最好的犒赏...
- 使用stream类型的Result实现Ajax
- 计网 - 流和缓冲区:缓冲区的 flip 是怎么回事?
- windows 搭建python 虚拟环境 写程序_Windows下搭建Python虚拟环境
- 使用spring boot+shiro+jwt+mybatis-plus搭建项目框架
- uva 10608 FRIENDS
- JavaScript中带有示例的Math.PI属性
- 【重难点】【Java集合 01】HashMap 和 ConcurrentHashMap
- 挑战iOS!小米全新OS发布:22款机型首发
- python list去重函数_python 列表函数
- Introduction to SQL Server 2005 XML
- saas系统是什么_什么是灵活用工智能财税SaaS系统?有什么好处?
- tuxedo 强制重启
- buildroot external-toolchain的一次踩坑经历
- 如何免费在线将pdf转换成jpg图片
- Codeforces Round #614 (Div. 2)A. ConneR and the A.R.C. Markland-N
- 树链剖分 - 月下“毛景树”(BZOJ 4151)
- Ubuntu20.04+Window10双系统开机引导界面美化
- Bitmap的getpixel(x,y)和保存到系统图库的方法
热门文章
- Android dp方式的屏幕适配工具使用(Android Studio插件方式)
- 大饼“U”形底?ETR开始
- java 3gp 转mp3_Java利用Jave转换视频格式为3gp
- 四大开源3d游戏引擎探究(前言上)
- Google, with new Pixel and camera, is serious about devices
- 绘制神经元的结构模式图,神经元结构示意图简易
- Local Linear Model, Semi Local Linear Model and Local Level Model of TFP.STS
- echart实现地球外环绕卫星效果
- ECMAScript语法+关键字和保留字
- ArcGis基础—shapefile矢量文件与lyr图层文件之间有何区别?