本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的、不同方法的处理,以达到对图像进行去噪、锐化等一系列的操作。同时,希望观看本专栏的小伙伴可以理解到OpenCv进行图像处理的强大哦,如有转载,请注明出处(原文链接和作者署名),感谢各位小伙伴啦!
前文参考:
《OpenCv视觉之眼》Python图像处理一 :Opencv-python的简介及Python环境搭建
《OpenCv视觉之眼》Python图像处理二 :Opencv图像读取、显示、保存基本函数原型及使用
《OpenCv视觉之眼》Python图像处理三 :Opencv图像属性、ROI区域获取及通道处理
《OpenCv视觉之眼》Python图像处理四 :Opencv图像灰度处理的四种方法及原理
《OpenCv视觉之眼》Python图像处理五 :Opencv图像去噪处理之均值滤波、方框滤波、中值滤波和高斯滤波
《OpenCv视觉之眼》Python图像处理六 :Opencv图像傅里叶变换和傅里叶逆变换原理及实现
《OpenCv视觉之眼》Python图像处理七 :Opencv图像处理之高通滤波和低通滤波原理及构造
《OpenCv视觉之眼》Python图像处理八 :Opencv图像处理之图像阈值化处理原理及函数
《OpenCv视觉之眼》Python图像处理九 :Opencv图像形态学处理之图像腐蚀与膨胀原理及方法
《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法
《OpenCv视觉之眼》Python图像处理十一 :Opencv图像形态学处理之顶帽运算与黑帽运算
《OpenCv视觉之眼》Python图像处理十二 :Opencv图像轮廓提取之基于一阶导数的Roberts算法、Prewitt算法及Sobel算法
《OpenCv视觉之眼》Python图像处理十三 :Opencv图像轮廓提取之基于二阶导数的Laplacian算法和LOG算法
《OpenCv视觉之眼》Python图像处理十四 :Opencv图像轮廓提取之Scharr算法和Canny算法
《OpenCv视觉之眼》Python图像处理十五 :Opencv图像处理之图像缩放、旋转和平移原理及实现
上次博客我们结束了OpenCV图像处理的基本步骤,包括图像灰度处理、图像滤波去噪、图像阈值化、图像形态学处理、图像轮廓提取等,这是在现实OpenCV对一张图像进行处理的一般步骤,例如我们要识别图像中的人脸,图像中的硬币、图像中的车牌或者是提取图像中的某个物体,以上步骤都是我们必须通过调整参数而需要使用的;上次博客结束了以上步骤,接下来该系列的讲解主要针对图像目的操作,也就是项目实战,你也可以理解为通过《OpenCV视觉之眼》识别图像中的物体。
本次博客,林君学长主要介绍如何通过OpenCV图像处理库对图像中的硬币进行检测识别,大家主要理解硬币检测的过程中对图像处理的过程,每一步过程代表什么含义,怎么对步骤中所用到的函数通过参数调节达到我们预期的目标
图像处理实战1:对图像中的硬币进行检测,在终端打印出硬币个数,并在原图上画出识别到的硬币的轮廓
对图像中的硬币检测针对的不是一张图像,而是一类图像,通过OpenCV对图像进行识别有优势也有缺点,对于一类图像,OpenCV编写的识别算法可能只对一张图像有效,而针对这一类型的其他图像,可能得到的结果不是预期的效果,这是OpenCV对图像识别的缺点,不比神经网络训练一下针对一类图像都可以进行识别;但优点是对图像识别的速度快、开源代码,比神经网络进行模型训练容易理解;以上的优点和缺点在下面的操作中是可以体现的,一起学习吧!
图像硬币检测步骤一般情况分为以下8个步骤,如下所示:
注意:以下步骤所用的函数参数是随便进行设置的,因此,图像可能达不到预期要求,后面通过参数进行调节
1)、硬币图像数据准备
2)、导入OpenCV-Python库读取图像,并进行泛洪处理(背景填充)
#导入函数库
import cv2
import numpy as np
#读取一张硬币图像
img=cv2.imread("coins2.jpg")
#对图像进行泛洪处理
h, w = img.shape[:2] #获取图像的长和宽
mask = np.zeros((h+2, w+2), np.uint8)#进行图像填充
cv2.floodFill(img, mask, (w-1,h-1), (255,255,255), (2,2,2),(3,3,3),8)
#图像灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#通过高斯滤波对图像进行模糊处理,可以理解为对图像硬币去噪
blur=cv2.GaussianBlur(gray,(29,29),1,1)#这里可以用中值滤波,具体视对图像效果选择
5)、对滤波去噪后的图像进行阈值化处理,将轮廓与周围无用信息分开
#通过二进制阈值化对图像进行阈值化处理,将硬币轮廓与周围噪声区分开来
ret,thresh1=cv2.threshold(blur,127,255,cv2.THRESH_BINARY)
6)、图像形态学处理,通过闭运算,去除图像内部噪声
#进行闭运算,去除图像内部噪声
#设置卷积核
kernel = np.ones((7,7), np.uint8)
close=cv2.morphologyEx(thresh1, cv2.MORPH_CLOSE, kernel)
7)、利用Canny算法提取轮廓
#利用canny算法对图像进行轮廓提取
Canny = cv2.Canny(close, 50, 150)
#显示图像轮廓提取图像
cv2.imshow("Canny",Canny)
#等待键盘键值关闭
cv2.waitKey(0)
如果图像轮廓在进行阈值化后已经很清晰,该步骤可以省略
8)、提取轮廓线条,并在终端打印硬币个数,最后将轮廓线条画在原图上
#在提取出的轮廓图像中找出轮廓线条
(cnts1,_) =cv2.findContours(Canny,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
#在终端打印出硬币个数
print("图像中的硬币共有:",len(cnts1),"个")
#将硬币轮廓线条画在原图
coins1 = img.copy()
cv2.drawContours(coins1, cnts1, -1, (0,255,0), 2)
#显示在原图上面检测出来的硬币
cv2.imshow("coins",coins1)
#等待键盘键值关闭
cv2.waitKey(0)
findContours()函数原型:(cnts1,_) =cv2.findContours(img,a,b)
drawContours()函数原型:cv2.drawContours(img, cnts1, indnx, color, size)
再次声明:以上函数参数暂未进行调整,因此不少我们预期的图像,后面我们会进行参数调整的哦!
'''
项目实战一:OpenCV图像硬币检测
'''
#导入函数库
import cv2
import numpy as np
#读取一张硬币图像
img=cv2.imread("coins2.jpg")
#低通滤波处理
#对图像进行泛洪处理
h, w = img.shape[:2] #获取图像的长和宽
mask = np.zeros((h+2, w+2), np.uint8)#进行图像填充
cv2.floodFill(img, mask, (w-1,h-1), (255,255,255), (2,2,2),(3,3,3),8)
#图像灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#通过高斯滤波对图像进行模糊处理,可以理解为对图像硬币去噪
blur=cv2.cv2.GaussianBlur(gray,(29,29),0,0)#这里可以用中值滤波,具体视对图像效果选择
cv2.imshow("blur",blur)
cv2.waitKey(0)
#通过二进制阈值化对图像进行阈值化处理,将硬币轮廓与周围噪声区分开来
ret,thresh1=cv2.threshold(blur,127,255,cv2.THRESH_BINARY)
cv2.imshow("thresh1",thresh1)
cv2.waitKey(0)
#进行闭运算,去除图像内部噪声
kernel = np.ones((7,7), np.uint8)#设置卷积核
close=cv2.morphologyEx(thresh1, cv2.MORPH_CLOSE, kernel)#闭运算
cv2.imshow("close",close)
cv2.waitKey(0)
#利用canny算法对图像进行轮廓提取
Canny = cv2.Canny(close, 20, 150)
#显示图像轮廓提取图像
cv2.imshow("Canny",Canny)
#等待键盘键值关闭
cv2.waitKey(0)
#在提取出的轮廓图像中找出轮廓线条
(cnts1,_) =cv2.findContours(Canny,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
#在终端打印出硬币个数
print("图像中的硬币共有:",len(cnts1),"个")
#将硬币轮廓线条画在原图
coins1 = img.copy()
cv2.drawContours(coins1, cnts1, -1, (0,255,0), 2)
#显示在原图上面检测出来的硬币
cv2.imshow("coins",coins1)
#等待键盘键值关闭
cv2.waitKey(0)
接下来,我们通过调节以上代码中的相关参数,进行图像预期处理,如下步骤
在以上运用到的函数进行参数调节的过程中,我们主要通过滤波去噪参数和Canny算法参数,通过调节以上参数进行图像预期处理
1)、观察以上阈值化后的图像轮廓,可以发现,图像轮廓不完整,因此,高斯滤波核过大,导致图像轮廓丢失,因此,我们将高斯滤波核尺寸缩小,至于尺寸的调节,可以观察到至少包含所有硬币轮廓,调节后如下:
blur=cv2.GaussianBlur(gray,(17,17),1,1)#这里可以用中值滤波,具体视对图像效果选择
1)、在很多时候,图像不完整是由于二进制阈值化参数阈值设置过低,将低模糊后的低像素值设置为白色了,可以将阈值调大一点
ret,thresh1=cv2.threshold(blur,177,255,cv2.THRESH_BINARY)
2)、图像阈值化之后,会紧跟形态学处理,一般我们会运用形态学处理将图像内部的白色间隙去掉,使得全部为黑色形状,这样在进行Canny算法提取的时候才不会出现多余的轮廓,因此,需要调节闭运算的卷积核,自己适当调整
kernel = np.ones((7,7), np.uint8)#设置卷积核
Canny算法是边缘检测的优质算法,但前提是我们得设置好上下阈值,因为最后是通过双阈值方式得到最终轮廓,因此,选择上下阈值时非常重要的,不同的图像对应不同的上下阈值,这也是前面我们说到的缺点,对同类其他图像进行处理需要多次调解参数,具体调解到提取完美的轮廓为止,如下所示:
Canny = cv2.Canny(close, 20, 150)
'''
项目实战一:OpenCV图像硬币检测
'''
#导入函数库
import cv2
import numpy as np
#读取一张硬币图像
img=cv2.imread("coins2.jpg")
#低通滤波处理
#对图像进行泛洪处理
h, w = img.shape[:2] #获取图像的长和宽
mask = np.zeros((h+2, w+2), np.uint8)#进行图像填充
cv2.floodFill(img, mask, (w-1,h-1), (255,255,255), (2,2,2),(3,3,3),8)
#图像灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#通过高斯滤波对图像进行模糊处理,可以理解为对图像硬币去噪
blur=cv2.cv2.GaussianBlur(gray,(17,17),0,0)#这里可以用中值滤波,具体视对图像效果选择
#通过二进制阈值化对图像进行阈值化处理,将硬币轮廓与周围噪声区分开来
ret,thresh1=cv2.threshold(blur,177,255,cv2.THRESH_BINARY)
#进行闭运算,去除图像内部噪声
kernel = np.ones((7,7), np.uint8)#设置卷积核
close=cv2.morphologyEx(thresh1, cv2.MORPH_CLOSE, kernel)#闭运算
#利用canny算法对图像进行轮廓提取
Canny = cv2.Canny(close, 20, 150)
#显示图像轮廓提取图像
cv2.imshow("Canny",Canny)
#在提取出的轮廓图像中找出轮廓线条
(cnts1,_) =cv2.findContours(Canny,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
#在终端打印出硬币个数
print("图像中的硬币共有:",len(cnts1),"个")
#将硬币轮廓线条画在原图
coins1 = img.copy()
cv2.drawContours(coins1, cnts1, -1, (0,255,0), 2)
#显示在原图上面检测出来的硬币
cv2.imshow("coins",coins1)
#等待键盘键值关闭
cv2.waitKey(0)
3)、缺点展示
如果我们通过以上的参数再去检测其他硬币图像,我们可以发现效果非常不明显,如下所示:
因此,对于同类的不同图像,我们需要再次调解上面所讲得参数!
以上就是本次博客的全部内容,遇到问题的小伙伴记得留言评论,学长看到会为大家进行解答的,这个学长不太冷!
你生活在别人的眼神里,就迷失在自己的心路上。你永远无法满足所有人,不必为了取悦这个世界而扭曲自己。
陈一月的又一天编程岁月^ _ ^