图像
- 计算机中图像就是由像素点组成。
- RGB表示颜色通道,R红色G绿色B蓝色,[0-255]表示该像素点的亮度。
- 黑白图像只有一个通道表示亮度。
- 图像是500*500,则RGB三个通道均是500*500的矩阵,一个图像则为[500,500,3]。
数据读取-图像
cv2.IMREAD_COLOR:彩色图像
cv2.IMREAD_GRAYSCALE:灰色图像
import cv2 #OpenCv,有很多计算机视觉需要的的算法;opencv读取的格式是BGR import matplotlib.pyplot as plt #Pyplot包含一系列绘图函数的相关函数,用as给它设置一个别名plt import numpy as np #支持大量的维度数组与矩阵运算 用as给其设置别名np #%matplotlib inline #用它可以省略plt.show(),vscode用不了 def cv_show(name,img): #定义一个函数,更方便的显示图像 cv2.imshow(name,img) #图像的显示,也可以创建多个窗口 cv2.waitKey(0) #等待时间,毫秒级,0表示任意键终止 cv2.destroyAllWindows() img=cv2.imread('cat.jpg') #显示一个BGR图像 cv2.imshow('image',img) cv2.waitKey(0) cv2.destroyAllWindows img=cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE) #显示一个灰度图像 cv2.imshow('image',img) cv2.waitKey(0) cv2.destroyAllWindows cv2.imwrite('mycat.png',img) #保存图片 print(img.shape) #图像基本数值 print(img) #图片每一个像素点(矩阵形式) print(type(img)) #查看图片底层格式 print(img.size) #计算图片像素点个数 print(img.dtype) #图像数据类型
讯享网
截取部分图像数据
讯享网img=cv2.imread('cat.jpg') cat=img[0:200,0:200] #截取一段图像 cv_show('cat',cat) #显示截取图像的彩色图
颜色通道提取
B,G,R=cv2.split(img) print(B) print(B.shape) img=cv2.merge((B,G,R)) print(img.shape) cur_img=img.copy() #只保留R通道 cur_img[:,:,0]=0 cur_img[:,:,1]=0 cv_show('R',cur_img) cur_img=img.copy() #只保留G通道 cur_img[:,:,0]=0 cur_img[:,:,2]=0 cv_show('G',cur_img) cur_img=img.copy() #只保留B通道 cur_img[:,:,1]=0 cur_img[:,:,2]=0 cv_show('B',cur_img)
数据读取-视频
cv2.VideoCapture可以捕获摄像头,用数字来控制不同的设备,例如0,1。
如果是视频文件,直接指定好路径即可。
讯享网import cv2 import matplotlib.pyplot as plt import numpy as np #播放一个灰度视频 vc = cv2.VideoCapture('test.mp4') if vc.isOpened(): #检查是否打开正确 open,frame=vc.read() else: open = False while open: ret,frame=vc.read() if frame is None: break if ret == True: gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #此行代码为显示视频是灰度还是彩色的关键 cv2.imshow('result',gray) if cv2.waitKey(10) & 0xFF == 27: break vc.ralease() cv2.destroyAllWindows() #显示一个彩*** vc = cv2.VideoCapture('test.mp4') if vc.isOpened(): open,frame=vc.read() else: open = False while open: ret,frame=vc.read() if frame is None: break if ret == True: cv2.imshow('result',frame) if cv2.waitKey(10) & 0xFF == 27: break vc.ralease() cv2.destroyAllWindows()
边界填充
BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对图像中的像素在两边进行复制 fedcba | abcdefgh | hgfedcb
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称, gfedcb | abcdefgh | gfedcba
BORDER_WRAP:外包装法 cdefgh | abcdefgh | abcdefg
BORDER_CONSTANT:常量法,常数值填充。
import cv2 import numpy as np import matplotlib.pyplot as plt img=cv2.imread('cat.jpg') top_size,bottom_size,left_size,right_size=(50,50,50,50) replicate=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE) reflect=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT) reflect101=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT_101) wrap=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_WRAP) constant=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_CONSTANT,value=0) plt.subplot(231),plt.imshow(img,'gray'),plt.title('ORIGINAL') plt.subplot(232),plt.imshow(replicate,'gray'),plt.title('REPLICATE') plt.subplot(233),plt.imshow(reflect,'gray'),plt.title('REFLECT') plt.subplot(234),plt.imshow(reflect101,'gray'),plt.title('REFLECT_101') plt.subplot(235),plt.imshow(wrap,'gray'),plt.title('WRAP') plt.subplot(236),plt.imshow(constant,'gray'),plt.title('CONSTANT') plt.show()
运行结果:
数值计算
讯享网import cv2 import numpy as np import matplotlib.pyplot as plt img_cat=cv2.imread('cat.jpg') img_dog=cv2.imread('dog.jpg') img_cat2=img_cat+10 #直接相加,两数和超过255时 结果为 两数和 % 256 print(img_cat[:5,:,0]) print(img_cat2[:5,:,0]) print((img_cat+img_cat2)[:5,:,0]) print(cv2.add(img_cat,img_cat2)[:5,:,0]) #用cv2.add相加时,两数和超过255时 结果为255 # print(img_cat+img_dog) #shape不同时,不能相加 print(img_cat.shape) img_dog=cv2.resize(img_dog,(500,414)) #将'dog.jpg'的shape改成和'cat.jpg'一致 print(img_dog.shape) res=cv2.addWeighted(img_cat,0.4,img_dog,0.6,0) #将'cat.jpg'和'dog.jpg'融合。'cat.jpg'占比0.4;'dog.jpg'占比0.6;提亮值为0。 plt.imshow(res) plt.show()
运行结果:

res=cv2.resize(img_cat,(0,0),fx=3,fy=1) #将图片宽伸长三倍,高不变 plt.imshow(res) plt.show()
运行结果:

讯享网res=cv2.resize(img_cat,(0,0),fx=1,fy=3) #将图片宽不变,高伸长三倍 plt.imshow(res) plt.show()
运行结果 :

形态学
腐蚀操作
腐蚀操作所用函数为cv2.erode(),确定盒子大小的函数是np.ones()。
import cv2 import matplotlib.pyplot as plt import numpy as np def cv_show(name,img): cv2.imshow(name,img) cv2.waitKey(0) cv2.destroyAllWindows() #腐蚀操作 img = cv2.imread('dige.png') cv_show('img',img) kernel=np.ones((5,5),np.uint8) erosion=cv2.erode(img,kernel,iterations=1)#迭代 1 次 cv_show('erosion',erosion)
原图:

腐蚀操作,迭代1次后:

对圆进行腐蚀操作:
讯享网pie=cv2.imread('pie.png') cv_show('pie',pie) kernel=np.ones((30,30),np.uint8) erosion_1=cv2.erode(pie,kernel,iterations=1) erosion_2=cv2.erode(pie,kernel,iterations=2) erosion_3=cv2.erode(pie,kernel,iterations=3) res=np.hstack((erosion_1,erosion_2,erosion_3)) cv_show('res',res)
原图:

分别迭代 1 2 3

膨胀操作
腐蚀操作所用函数为cv2.dilate()
img = cv2.imread('dige.png') cv_show('img',img) kernel=np.ones((5,5),np.uint8) dige_erosion=cv2.erode(img,kernel,iterations=1) dige_dilate=cv2.dilate(dige_erosion,kernel,iterations=1) cv_show('dilate',dige_dilate)
原图:

膨胀操作,迭代一次后:

对圆进行膨胀操作:
讯享网pie=cv2.imread('pie.png') cv_show('pie',pie) kernel=np.ones((30,30),np.uint8) dilate_1=cv2.dilate(pie,kernel,iterations=1) dilate_2=cv2.dilate(pie,kernel,iterations=2) dilate_3=cv2.dilate(pie,kernel,iterations=3) res=np.hstack((dilate_1,dilate_2,dilate_3)) cv_show('res',res)
原图:

分别 迭代 1 2 3

开运算与闭运算
开运算:先腐蚀后膨胀
闭运算:先膨胀后腐蚀
import cv2 import numpy as np import matplotlib.pyplot as plt #开运算:先腐蚀后膨胀 def cv_show(name,img): cv2.imshow(name,img) cv2.waitKey(0) cv2.destroyAllWindows() img=cv2.imread('dige.png') cv_show('yuantu',img) #原图 kernel=np.ones((5,5),np.uint8) opening=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel) cv_show('opening',opening) #先腐蚀后膨胀结果图 #闭运算:先膨胀后腐蚀 img=cv2.imread('dige.png') cv_show('yuantu',img) #原图 kernel=np.ones((5,5),np.uint8) closing=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel) cv_show('closing',closing) #先膨胀后腐蚀结果图
原图:

开运算结果图:

闭运算结果图:

梯度运算
梯度=膨胀-腐蚀
讯享网#梯度运算 #梯度=膨胀—腐蚀 pie=cv2.imread('pie.png') kernel=np.ones((7,7),np.uint8) dilate=cv2.dilate(pie,kernel,iterations=5) #膨胀5次 ersion=cv2.erode(pie,kernel,iterations=5) #腐蚀5次 res=np.hstack((dilate,ersion)) cv_show('res',res) gradient=cv2.morphologyEx(pie,cv2.MORPH_GRADIENT,kernel) cv_show('gradient',gradient)
将原图分别膨胀5次和腐蚀5次后的结果图:

梯度运算结果图:

礼帽与黑帽
礼帽:原始输入-开运算结果

img=cv2.imread('dige.png') tophat=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel) cv_show('tophat',tophat)
结果图:

黑帽:闭运算结果-原始输入
讯享网img=cv2.imread('dige.png') blackhat=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel) cv_show('blackhat',blackhat)
结果图:

三种梯度计算的算子
Sobel算子

dst=cv2.Sobel(src,ddepth,dx,dy,ksize)
- ddepth:图像的深度
- dx和dy分别表示水平和竖直方向
- ksize是Sobel算子的大小
img=cv2.imread('D:\pythontupian\pie.png',cv2.IMREAD_GRAYSCALE) cv2.imshow('img',img) cv2.waitKey() cv2.destroyAllWindows() def cv_show(img,name): cv2.imshow(name,img) cv2.waitKey() cv2.destroyAllWindows() sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) cv_show(sobelx,'sobelx')
原图 只计算了右-左且未取绝对值


白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值。
讯享网sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) sobelx=cv2.convertScaleAbs(sobelx) #取绝对值 cv_show(sobelx,'sobelx')

sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) sobely=cv2.convertScaleAbs(sobely) cv_show(sobely,'sobely')
下-上的结果截图

分别计算x和y,再求和
讯享网sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0) cv_show(sobelxy,'sobelxy')

直接计算(不建议)
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3) sobelxy=cv2.convertScaleAbs(sobelxy) cv_show(sobelxy,'sobelxy')

"lena" 图片示例:
讯享网img=cv2.imread('D:\pythontupian\lena.jpg',cv2.IMREAD_GRAYSCALE) cv_show(img,'img') sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) sobelx=cv2.convertScaleAbs(sobelx) sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) sobely=cv2.convertScaleAbs(sobely) sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0) cv_show(sobelxy,'sobelxy')
原图 先计算右-左,再计算下-上,最后结果相加。

img=cv2.imread('D:\pythontupian\lena.jpg',cv2.IMREAD_GRAYSCALE) sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3) sobelxy=cv2.convertScaleAbs(sobelxy) cv_show(sobelxy,'sobelxy')
直接计算梯度

scharr算子

讯享网img=cv2.imread('D:\pythontupian\lena.jpg',cv2.IMREAD_GRAYSCALE) scharrx=cv2.Scharr(img,cv2.CV_64F,1,0) scharrx=cv2.convertScaleAbs(scharrx) scharry=cv2.Scharr(img,cv2.CV_64F,0,1) scharry=cv2.convertScaleAbs(scharry) scharrxy=cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
laplacian算子

img=cv2.imread('D:\pythontupian\lena.jpg',cv2.IMREAD_GRAYSCALE) laplacian=cv2.Laplacian(img,cv2.CV_64F) laplacian=cv2.convertScaleAbs(laplacian)
三种算子计算结果比较
讯享网res=np.hstack((sobelxy,scharrxy,laplacian)) cv_show(res,'res')
Sobel scharr laplacian

图像平滑处理
均值滤波
简单的平均卷积操作
import cv2 import matplotlib.pyplot as plot import numpy as np img=cv2.imread('D:\pythontupian\lenaNoise.png') def cv_show(name,img): cv2.imshow(name,img) cv2.waitKey(0) cv2.destroyAllWindows() #原图 cv_show('img',img) #均值滤波 #简单的平均卷积操作 blur=cv2.blur(img,(3,3)) cv_show('blur',blur)
原图:

结果图:

方框滤波
基本和均值一样,可以选择归一化
讯享网#基本和均值一样,可以选择归一化 box=cv2.boxFilter(img,-1,(3,3),normalize=True) cv_show('box',box)
结果图:

不选择归一化的话很容易越界
#未选择归一化,越界后的结果 box=cv2.boxFilter(img,-1,(3,3),normalize=False) cv_show('box',box)
越界结果图:

高斯滤波
高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
讯享网#高斯滤波 #高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的 aussian=cv2.GaussianBlur(img,(5,5),1) cv_show('aussian',aussian)
结果图:

中值滤波
相当于用中值代替
#中值滤波 #相当于用中值代替 median=cv2.medianBlur(img,5) cv_show('median',median)
结果图:

展示均值、高斯、中值滤波结果:
讯享网#展示所有结果 res=np.hstack((blur,aussian,median),) cv_show('res',res)


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/70248.html