当前位置: 首页 > 后端技术 > Python

Opencv学习指南入门(二):求俄罗斯方块的个数

时间:2023-03-25 23:33:19 Python

(注:本文节选自AdrianRosebrock的教程文章翻译后)本文将介绍以下几点:如何使用OpenCV将彩色图像转换为灰度图像-scale图像边缘检测灰度图像阈值检测、计数和绘制轮廓腐蚀膨胀mask图像首先需要导入必要的库和解析参数#导入必要的包,包括Python自带的命令行参数解析包argparseimportargparseimportimutilsimportcv2#构造参数解析器并解析参数ap=argparse.ArgumentParser()ap.add_argument("-i","--image",required=True,help="pathtoinputimage")args=vars(ap.parse_args())1.将彩色图像转换为灰度图像#加载图像(路径包含在命令行参数中)并显示image=cv2.imread(args["image"])cv2.imshow("Image",image)cv2.waitKey(0)#将图像转换为灰度图像,需要图像和cv2.COLOR_BGR2GRAY标志gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)cv2.imshow("Gray",gray)cv2.waitKey(0)2.边缘检测边缘检测对于寻找图像中对象的边界很有用,主要用于图像分割。#应用边缘检测在图像中找到目标对象的轮廓edged=cv2.Canny(gray,30,150)cv2.imshow("Edged",edged)cv2.waitKey(0)使用流行的Canny算法(开发由JohnF.Canny于1986年开发),我们可以找到图像中的边缘。cv2.Canny函数需要三个参数:img:灰度图像minimum:本例中的最低阈值30maximum:本例中的最大阈值是150aperture_size:Sobel核大小,默认这个值为3,所以不是代码中显示,不同的最小和最大阈值将返回不同的边缘图3.灰度图像阈值处理在灰度图像中,每个像素的灰度值从0到255,其中0表示“黑色”,255表示“白色”。0到255之间的值是不同深浅的灰色,值越接近0越暗,值越接近255越亮。图像阈值化是图像处理中一个重要的中间步骤。阈值化可以帮助我们去除更亮或更暗的图像区域和轮廓。以下代码经过反复试验(和经验)适用于此示例:#所有灰度值<225的像素都设置为255(白色)-俄罗斯方块#灰度值>=225和<=255像素设置为0(黑色)-背景thresh=cv2.threshold(gray,225,255,cv2.THRESH_BINARY_INV)[1]cv2.imshow("Thresh",thresh)cv2.waitKey(0)关于cv2的更多信息关于.threshold函数,请参考opencv官方文档。使用二值化图像从背景中分割前景对于寻找轮廓至关重要。4.检测、计数和绘制轮廓#在图像中找到前景物体的轮廓cnts=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts=imutils.grab_contours(cnts)output=image.copy()#Drawcontoursinaloopforcincnts:#Drawcontourswithpurplelines#一次显示一个物体的轮廓cv2.drawContours(output,[c],-1,(240,0,159),3)cv2.imshow("Contours",output)cv2.waitKey(0)使用cv2.findContours检测图像中的轮廓。图像使用二值图像。注意函数的参数,但问题的简化是找到前景(白色)像素。利用上一篇文章中的知识,在图像上叠加一些文字:#Indicatethenumberofpurpleoutlinestext="Ifound{}objects!".format(len(cnts))cv2.putText(output,text,(10,25),cv2.FONT_HERSHEY_SIMPLEX,0.7,(240,0,159),2)cv2.imshow("Contours",output)cv2.waitKey(0)变量文本是包含形状轮廓数的字符串,计算这个image中的对象总数是检查轮廓列表的长度len(cnts)5.ErosionandDilationErosionandDilationErosionanddilation通常用于减少二值图像中的噪声(阈值处理的副作用)。(1)为了减小前景物体的尺寸,我们可以通过多次迭代腐蚀像素:#通过腐蚀减小前景物体的尺寸,使用cv2.erode将轮廓尺寸缩小5mask=thresh.copy()mask=cv2.erode(mask,None,iterations=5)cv2.imshow("Eroded",mask)cv2.waitKey(0)使用OpenCV侵蚀轮廓,在足够的迭代后有效地缩小它们或使它们完全消失,这对于去除二值化图像中的噪声点通常很有用。(2)扩大前景物体的尺寸,只需使用cv2.dilate:#Dilationcanexpandthesizeoftheforegroundobjectmask=thresh.copy()mask=cv2.dilate(mask,None,iterations=5)cv2.imshow("Dilated",mask)cv2.waitKey(0)在图像处理中,如果需要连接附近的轮廓,可以放大图像。显示的是通过五次迭代扩大轮廓而不将两个轮廓合二为一的结果。6.蒙版图片之所以叫蒙版,是因为它们会隐藏图片中我们不关心的区域,比如用二值化的图片覆盖原图,你会得到如下结果:背景现在是黑色的,而前景由彩色像素组成——一些像素被二值化以突出显示俄罗斯方块区域=cv2.bitwise_and(image,image,mask=mask)cv2.imshow("Output",output)cv2.waitKey(0)7.运行脚本终端输入:pythonopencv_tutorial_02.py--imagetetris_blocks.png参数flag为--image,image参数为tetris_blocks.png-目录中关联文件的路径。最后贴上源码:#USAGE#pythonopencv_tutorial_02.py--imagetetris_blocks.png#importthenecessarypackagesimportargparseimportimutilsimportcv2#constructtheargumentparserandparsetheargumentsap=argparse.ArgumentParser()ap.add_argument("-i","--image",required=True,help="pathtoinputimage")args=vars(ap.parse_args())#加载输入图像(其路径通过命令行#参数提供)并显示图像toourscreenimage=cv2.imread(args["image"])cv2.imshow("Image",image)cv2.waitKey(0)#converttheimagetograyscalegray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)cv2.imshow("Gray",gray)cv2.waitKey(0)#应用边缘检测我们可以在#imagesedged=cv2.Canny(gray,30,150)cv2.imshow("Edged",edged)cv2中找到对象的轮廓.waitKey(0)#通过将所有小于225#的像素值设置为255(白色;前景)和所有>=225到255#(黑色;背景)的像素值来对图像进行阈值处理,从而对图像进行分割thresh=cv2.threshold(gray,225,255,cv2.THRESH_BINARY_INV)[1]cv2.imshow("Thresh",thresh)cv2.waitKey(0)#在#中找到前景对象的轮廓(即轮廓)阈值图像cnts=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts=imutils.grab_contours(cnts)output=image.copy()#loopoverthecontoursforcincnts:#draweachcontouron输出图像带有3px厚的紫色#轮廓,然后一次显示一个输出轮廓cv2.drawContours(output,[c],-1,(240,0,159),3)cv2.imshow("Contours",output)cv2.waitKey(0)#drawthetotalcontoursfoundinpurpletext="Ifound{}objects!".format(len(cnts))cv2.putText(output,text,(10,25),cv2.FONT_HERSHEY_SIMPLEX,0.7,(240,0,159),2)cv2.imshow("Contours",output)cv2.waitKey(0)#我们应用侵蚀来减小前景对象的大小mask=thresh.copy()mask=cv2.erode(mask,None,iterations=5)cv2.imshow("Eroded",mask)cv2.waitKey(0)#类似地,膨胀可以增加地面物体的大小mask=thresh.copy()mask=cv2.dilate(mask,None,iterations=5)cv2.imshow("Dilated",mask)cv2.waitKey(0)#我们可能想要应用的典型操作是获取我们的掩码并#将按位与应用于我们的输入图像,仅保留掩码#regionsmask=thresh.copy()output=cv2.bitwise_and(image,image,mask=mask)cv2.imshow("输出",输出)cv2.waitKey(0)