本人小白,最近在学习python-opencv,找了一些博主的学习笔记或者代码练习了一下,以下是做了一些整理,本篇文章很多都是在其他博主的博客上翻译转载来的,我会尽量在文章中注明出处,如果有那些未注明,请告知我进行删除或添加。
本文主要参考文献:
1.LonelDemo,[opencv3.3+python3.6]学习笔记总结
2.浅墨_毛星云,[opencv入门教学之十] 形态学图像处理(一):腐蚀与膨胀
3.opencv-Python中文教程
我在代码中添加了中文注释,所以在运行代码前请在最前面添加:
#-*- coding:UTF-8 -*-
代码如下:
import cv2
capture = cv2.VideoCapture(0)#参数0调用电脑自带摄像头
while(True):
ret,frame = capture.read()#获取图像
cv2.imshow("video",frame)#显示图像
if cv2.waitKey(1) & 0xFF== ord('q'):#按下q键退出
break
cv2.release()
cv2.destroyAllWindows()
opencv中常用的几种色彩转化的方法:灰度图像、BGR、HSV、YUV、YCrCb。
(1)灰度图像:灰度色彩空间是通过取出色彩信息来将其转化为灰阶,灰度色彩空间对中间处理特别有效,比如人脸检测。
(2)BGR:三通道图像,每个像素点都由一个三元数组来表示。
(3)HSV:H是色调,S是饱和度,V是黑暗的程度。
(4)YUV:YUV编码采用明亮度和色度表示每个像素的颜色。其中Y表示明亮度,也就是灰阶值。U、V表示色度,描述的是色调和饱和度。
(5)YCrCb:百度百科上说这个就是YUV
代码如下:
mport cv2
def color_space_demo(image):
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#转化为灰度图
cv2.imshow("gray",gray)
cv2.imwrite("gray.png",gray)#以下的imwrite()都是我为了保存效果图加上的,如果没有需要可以注释掉。
hsv = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)#转化为HSV
cv2.imshow("hsv",hsv)
cv2.imwrite("hsv.png",hsv)
yuv = cv2.cvtColor(image,cv2.COLOR_BGR2YUV)#转化为YUV
cv2.imshow("yuv",yuv)
cv2.imwrite("yuv.png",yuv)
ycrcb=cv2.cvtColor(image,cv2.COLOR_BGR2YCrCb)#转化为YCrCb
cv2.imshow("ycrcb",ycrcb)
cv2.imwrite("ycrcb.png",ycrcb)
print("--------Hello Python---------")
src=cv2.imread("1.jpg")
cv2.imshow("src",src)
color_space_demo(src)
k=cv2.waitKey(0)
if k==27:
cv2.destroyAllWindows()
效果图如下:
(1)原图
(2)灰度图
(3)HSV
(4)YUV
(5)YCrCB
代码如下:
import cv2
def bgr_split_merge(image):
b,g,r = cv2.split(image) #分离图片三通道的值
cv2.imshow("blue",b) #显示单通道blue的图片
cv2.imwrite("blue.png",b)
cv2.imshow("green",g) #显示单通道green的图片
cv2.imwrite("green.png",g)
cv2.imshow("red",r) #显示单通道red的图片
cv2.imwrite("red.png",r)
image[:,:,2]=0 #设置第三个值为0
image=cv2.merge([b,g,r]) #合并三通道的值
cv2.imshow("bgr_dealed",image)
cv2.imwrite("bgr_dealed.png",image)
print("---------Hello Python----------")
src=cv2.imread("1.png")
cv2.imshow("source image",src)
bgr_split_merge(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图如下:
(1)原图
(2)单blue通道(姚明大哥我对不起你QAQ)
(3)单green通道
(4)单red通道
(5)三通道合并
主要包括算数运算和逻辑运算,其中算数运算包括:加减乘除以及均值和方差;;逻辑运算包括:与或非。
代码如下:
import cv2
import numpy as np
def add_demo(img1,img2): #加运算
dst=cv2.add(img1,img2)
cv2.imshow("add_demo",dst)
cv2.imwrite("add.png",dst)
def subtract_demo(img1,img2): #减运算
dst=cv2.subtract(img1,img2)
cv2.imshow("subtract_demo",dst)
cv2.imwrite("subtract.png",dst)
def divide_demo(img1,img2): #除运算
dst=cv2.divide(img1,img2)
cv2.imshow("divide_demo",dst)
cv2.imwrite("divide.png",dst)
def multiply_demo(img1,img2): #乘运算
dst=cv2.multiply(img1,img2)
cv2.imshow("multiply_demo",dst)
cv2.imwrite("multiply.png",dst)
def others(img1,img2): #求均值和方差运算
m1=cv2.meanStdDev(img1)
m2=cv2.meanStdDev(img2)
h,w=img1.shape[:2]
print(m1)
print(m2)
img=np.zeros([h,w],np.uint8)
m=cv2.meanStdDev(img)
print(m)
def bit_and(img1,img2): #与运算
dst=cv2.bitwise_and(img1,img2)
cv2.imshow("bit_and",dst)
cv2.imwrite("bit_and.png",dst)
def bit_or(img1,img2): #或运算
dst=cv2.bitwise_or(img1,img2)
cv2.imshow("bit_or",dst)
cv2.imwrite("bit_or.png",dst)
def bit_not(img1,img2): #非运算
dst=cv2.bitwise_not(img1)
cv2.imshow("bit_not",dst)
cv2.imwrite("bit_not.png",dst)
print("----------------Hello World-------------------")
src1=cv2.imread("zero_reverse.png")
src2=cv2.imread("color.png")
src2=cv2.resize(src2,(275,183)) #两个图的尺寸不相同,转化成相同尺寸
print(src1.shape) #此处注意shape输出的是[height,width]
print(src2.shape) #resize中输入的是[width,height]
cv2.imshow("image1",src1)
cv2.imshow("image2",src2)
print("--------------PIXEL MATH DEAL-------------------")
add_demo(src2,src1)
subtract_demo(src2,src1)
divide_demo(src2,src1)
multiply_demo(src2,src1)
others(src1,src2)
print("------------------PIXEL LOGAL DEAL----------------------")
bit_and(src1,src2)
bit_or(src1,src2)
bit_not(src1,src2)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图如下:
(1)原图
(2)加运算
(3)减运算
(4)乘运算
(5)除运算
(6)与运算
(7)或运算
(8)非运算
注:
图像尺寸变换方法:
img2=cv2.resize(img1,(width,height),interpolation=cv2.INTER_CUBIC)
img1:待输入的图片
括号里面为要更改的图像尺寸
第三个参数为尺寸变换使用的插值方法,几种插值方法的不同见下表
使用canny边缘检测算法可以将图像中的轮廓提取出来,canny边缘检测算法的主要过程如下:
(1)高斯模糊-GaussianBlur
(2)灰度转换-cvtColor
(3)计算梯度-Sobel/Scharr
(4)非最大信号抑制
(5)高低阈值输出二值图像
代码如下:
import cv2
def edge_demo(img):
blurred=cv2.GaussianBlur(img,(3,3),0) #高斯模糊,减小噪声
gray=cv2.cvtColor(blurred,cv2.COLOR_BGR2GRAY)#转化为灰度图
grad_x=cv2.Sobel(gray,cv2.CV_16SC1,1,0) #x梯度方向
grad_y=cv2.Sobel(gray,cv2.CV_16SC1,0,1) #Y梯度方向
edge_output=cv2.Canny(grad_x,grad_y,50,150)
cv2.imshow("canny edge",edge_output)
dst=cv2.bitwise_and(img,img,mask=edge_output)#逻辑与运算
cv2.imshow("color edge",dst)
print("----------HELLO PYTHON-----------")
src=cv2.imread("1.png")
cv2.imshow("source image",src)
edge_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图如下:
(1)原图
(2)canny边缘检测后
(3)逻辑与后
注:
第三个图进行逻辑与运算,其中bitwise_and()函数中的mask参数,根据这篇文章
感觉类似于喷漆画画时,我们剪出一块想要形状的纸板放在上面,喷漆只喷在剪出的形状上,所以第三个图应该就是将canny中的白色区域换成了原图的中的颜色
图像的边缘信息,不是指的图像的四个边的那一部分的信息,而是图像在像素层面上,像素值跃迁,差异值较大的地方。而边缘保留滤波算法则可以解决这个问题,滤波之后的输出可以完整的保存图像整体边缘的信息。常见的边缘保留滤波算法有:
(1)高斯双边滤波
(2)均值迁移滤波
注:
自己使用后感觉这个滤波就像磨皮似的,尤其第一个高斯双边滤波,可以将脸上的雀斑之类的去掉效果很好,并且可以很好的保留原图的风格;但是第二个均值迁移滤波整体效果和原图差异比较大
代码如下:
import cv2
def bi_demo(img):
dst=cv2.bilateralFilter(img,0,100,15) #高斯双边滤波
#cv2.namedWindow("bi_demo",0) #flags=0,也可以用cv2.WINDOW_NORMAL,这个模式下可以调整窗口大小,flages=1,表示窗口不能调整大小
#cv2.resizeWindow("bi_demo",540,960) #也可以采用这样的方法来设定窗口的大小,不过我当时用了一个手机拍的图片,可能像素有点高,这两种方法都没有起作用,图片展示不开也没办法调整大小
cv2.imshow("bi_demo",dst)
cv2.imwrite("bi_demo.png",dst)
def shift_demo(img):
dst=cv2.pyrMeanShiftFiltering(img,10,50) #均值迁移,有时候过度模糊
#cv2.namedWindow("shift_demo",cv2.WINDOW_NORMAL)
cv2.imshow("shift_demo",dst)
cv2.imwrite("shift_demo.png",dst)
print("-------------Hello Python------------")
src=cv2.imread("2.png")
#cv2.namedWindow("source image",cv2.WINDOW_NORMAL)
cv2.imshow("source image",src)
bi_demo(src)
shift_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果图如下:
(1)原图
(2)高斯双边滤波
(3)均值双边滤波
腐蚀和膨胀能实现多种多样的功能,主要如下:
(1)消除噪声
(2)分割出独立的图像元素,在图像中连接相邻的元素
(3)寻找图像中明显的极大值区域或极小值区域
(4)求出图像的梯度
注:
腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分,膨胀就是对图片中高亮部分进行膨胀,即邻域扩张,效果图拥有比原图更大的高亮区域,针对上图而言的话就是白色部分扩张;腐蚀就是原图中的高亮部分被腐蚀,即邻域被蚕食,效果图拥有比原图更小的高亮区域,针对上图而言,白色部分缩减。
一、腐蚀操作
把前景物体的边界腐蚀掉,但是前景仍然是白色的。卷积核沿着图像进行滑动,如果与卷积核对应的原图像的所有像素值都是1,那么中心元素就保持原来的像素值,否则就变为0,。根据卷积核的大小靠近前景的所有像素都会被腐蚀掉(变为0),所以前景物体会变小,整幅图像的白色区域会减少。这对于去除白噪音很有用,也可以用来断开两个连在一起的物体。
第一个白色区域减少应该很容易理解,第二个说可以断开两个连在一起的物体,我找了张图片试了下,是一个香蕉的图片,可以看下下图的效果,感觉也不是很明显,不过也能看出在香蕉连接部分黑色部分加重了。
代码如下:
import cv2
import numpy as np
img=cv2.imread("zero_reverse.png")
kernel = np.ones((5,5),np.uint8)#设置5X5卷积核
erosion = cv2.erode(img,kernel,iterations=1)#第三个参数我没查是什么。。
while(1):
cv2.imshow("img",img)
cv2.imshow('erosion',erosion)
k = cv2.waitKey(1)
if k == ord('q'):
break
cv2.imwrite('erosion.png',erosion)
cv2.destroyWindows()
效果图如下:
(1)原图
(2)腐蚀后
(3)原图2
(4)腐蚀后
二、膨胀操作
与腐蚀相反,与卷积对应的原图像的像素值只要有一个是1,中心元素的像素值就是1。所以这个操作会增加图像中的白色区域(前景)。一般在去噪音的时候先腐蚀在膨胀,因为腐蚀再去掉白噪音的同时,也会使前景对象变小,所以我们再膨胀。这时白噪音已经被去除了,不会再回来了,但是前景还在并会增加,膨胀也可以用来连接两个分开的物体。
代码如下:
dilation = cv2.dilate(img,kernel,iteration=1)#和之前代码中的erosion那行替换
效果图如下:
(1)原图
(2)膨胀后
三、开运算
先进行腐蚀再进行膨胀的运算叫做开运算。用来被去除噪声。
代码如下:
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
效果图如下:
注:开运算我试了下,找了一个图,也不知道是不是噪点图,感觉用了之后感觉特别糊
(1)原图
(2)开运算后
四、闭运算
先膨胀后腐蚀。被用来填充前景物体上的小洞,或者前景上的小黑点。
代码如下:
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
效果图如下:
注:它上面说可以填充图像上的小洞或小黑点,我就找了一副有小黑点的图片,从图片效果上来看的话,确实可以对小黑点有填充的作用。
(1)原图
(2)闭运算后
五、形态学梯度
其实就是一幅图像膨胀与腐蚀的差别,结果看上去就像前景图像的轮廓。
代码如下:
gradient = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
效果图我没试。。
未完待续…