注意:opencv_python版本选择3.4.1.15,过高可能会有专利问题无法使用。目前通用的教程中版本基本都是opencv2、3.
图片入门
一张图片由海量的像素点构成,而一个像素点由BGR三个颜色通道组成的,也就是三原色光。BGR的数值表示亮度,使用整数表示,从 0 ~ 255 ,一共256级,0 为黑色,255 为白色,因此数值越大图片越亮。一张彩色照片通常就是BGR图片。
对于一张图片来说,它的数值就是一个矩阵,行列就是像素点的数量。程序读取图片时,就是在读取这个图片像素点所映射的矩阵。
图片读取
1 2 3 4 5 6 7 8
| jz=cv2.imread("D:\\z-bank\\bank\\PY\\book.png") print(jz)
out: [[[230 226 232] [227 223 229] [227 222 231] ...
|
这里的中括号有三层,表示三个维度,用[h,w,c]表示。补充:hwc维度表示一个图像,H表示图像高度,w表示宽度,c表示通道数。
如果使用jz=cv2.imread("book.png",cv2.IMREAD_GRAYSCALE)
读取灰度图片,那么将没有c
,只有h、w。
imread()
函数的第二个参数是读取图片的方式,有以下几种:
- cv2.IMREAD_COLOR:读取彩色图片,透明度忽略,这是默认方式,用1表示
- cv2.IMREAD_GRAYSCALE:读取灰度图片。 用0表示
- cv2.IMREAD_UNCHANGED:读取图片的alpha通道。用-1表示
图片显示
1 2 3 4
| jz=cv2.imread("D:\\z-bank\\bank\\PY\\book.png") cv2.imshow("jz",jz) cv2.waitKey(0) cv2.destroyAllWindows()
|
使用imshow()
函数来显示图像,窗口自适应图像尺寸。
waitKey()
用于设置窗口开启时间,单位毫秒。设为 0 代表按下任意键即可关闭图片窗口。一般来说就是填 0
destroyAllWindows()
用于关闭所有窗口,如果想关闭指定窗口,可以使用destroyWindow()
函数。
图片裁剪
jz
是一个数组,左边参数为y轴裁剪范围,右边为x轴。单位是像素。具体数值可以在ps->信息窗口中查看。
图像裁剪截取图像的特定区域,在识别图像中的特定目标时,可以使用图像裁剪来提高识别的准确率。
1 2 3
| jz=cv2.imread("D:\\z-bank\\bank\\PY\\book.png") jz=jz[80:183,134:236] cv_show('jz',jz)
|
图片保存
cv2.imwrite('book.png',jz)
即可保存图片
图片通道分离与合并
图片shape值的最后一位表示通道数,分别是BGR,用0、1、2表示
1 2 3
| b,g,r=cv2.split(jz) cv_show('b',b)
|
图像允许将任意通道置为0,并合并其他通道,从而达到去除某个通道的效果。
1 2 3 4
| cpimg=cv2.merge([b,g,r]) cpimg[:,:,0]=0 cpimg[:,:,2]=0 cv_show('cpimg',cpimg)
|
matplotlib显示图片
1 2 3 4 5 6
| jz=cv2.imread("D:\\z-bank\\bank\\PY\\book.png")
plt.imshow(jz,cmap='gray',interpolation='bicubic') plt.xticks([]),plt.yticks([]) plt.show()
|
其他图像信息
1 2 3
| print(type(jz)) print(jz.size) print(jz.dtype)
|
图像基本操作
图片填充
图像填充可以在周边创建边框,例如相框。都使用copyMakeBorder()
函数,用法及参数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| img=cv2.imread("D:\\z-bank\\bank\\PY\\book.png") replicate=cv2.copyMakeBorder(img,10,10,10,10,cv2.BORDER_CONSTANT) reflect =cv2.copyMakeBorder(img,10,10,10,10,cv2.BORDER_REFLECT) reflect101 = cv2.copyMakeBorder(img,10,10,10,10,cv2.BORDER_REFLECT_101) wrap = cv2.copyMakeBorder(img,10,10,10,10,cv2.BORDER_WRAP) constant= cv2.copyMakeBorder(img,10,10,10,10,cv2.BORDER_CONSTANT,value=[255,0,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()
|
图像加法
对一张图片做加法时,会对每个像素点的RGB值进行加法运算。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| tx=cv2.imread("D:\\z-bank\\bank\\PY\\tx.jpg") print(tx[:3,:,0]) tx2=tx+10 print(tx2[:3,:,0])
[[137 137 137 ... 144 144 144] [137 137 137 ... 144 144 144] [137 137 137 ... 144 144 144]]
[[147 147 147 ... 154 154 154] [147 147 147 ... 154 154 154] [147 147 147 ... 154 154 154]]
|
如上代码,对 tx 图片每个像素点的BGR值+10,此时图片就会变亮。而如果将+10后的图片与原图相加,将得到一个(137+147)%256=28的结果,即图片变暗。因此,图像加法并不是简单的加法运算,而是对每个像素点的RGB值进行加法运算。
1 2 3 4 5 6 7
| tx3=tx+tx2 print(tx3[:3,:,0])
[[28 28 28 ... 42 42 42] [28 28 28 ... 42 42 42] [28 28 28 ... 42 42 42]]
|
上面的加法运算使用的是Numpy的模运算,也可以使用OpenCV的饱和运算,即超过255的值就截断为255,低于0的值就截断为0。
1 2 3 4 5 6 7
| tx3=cv2.add(tx,tx2) print(tx3[:3,:,0])
[[255 255 255 ... 255 255 255] [255 255 255 ... 255 255 255] [255 255 255 ... 255 255 255]]
|
图像融合
图像融合的前提是两张图片的shape必须相同,所以需要先使用cv2.resize()
函数调整图片大小。
1 2 3 4 5 6 7 8 9 10 11
| tx=cv2.imread("D:\\z-bank\\bank\\PY\\tx.jpg") xx=cv2.imread("D:\\z-bank\\bank\\PY\\xx.jpg") print("tx:",tx.shape) print("xx:",xx.shape)
newxx=cv2.resize(xx,(tx.shape[1],tx.shape[0]))
tx: (960, 960, 3) xx: (700, 700, 3) newxx: (960, 960, 3)
|
cv2.resize()
函数还可以将第二个参数设置为(0,0),第三个参数设置为缩放比例,即可按比例缩放图片。如下,x,y轴缩放为原来的一半,图像大小变为原来的四分之一。
1 2
| tx=cv2.imread("D:\\z-bank\\bank\\PY\\tx.jpg") cv2.resize(tx,(0,0),fx=0.5,fy=0.5)
|
然后使用cv2.addWeighted()
函数进行融合,用法如下。对图像进行加权融合,公式为:dst=α⋅img1+β⋅img2+γ。其中α、β、γ是缩放系数,α+β=1。
最后的效果类似于Photoshop中的图层融合,正片叠底。
1 2
| res=cv2.addWeighted(tx,0.5,xx,0.5,5) cv_show("res",res)
|
视频入门
视频读取
读取视频时,首先创建一个VideoCapture
对象。参数是设备索引或视频文件的名称。设备索引是指定摄像头,一般用0、1、2等数字表示。也可以填写视频文件的路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| videos=cv2.VideoCapture("D:\\z-bank\\bank\\PY\\wg.flv") if videos.isOpened(): open,frame=videos.read() else: open=False
while open: ret,frame=videos.read() if frame is None: break
if ret==True: gray=cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow('result',gray) if cv2.waitKey(25) & 0xFF ==27: break
videos.release() cv2.destroyAllWindows()
|
视频保存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| vd=cv2.VideoCapture("D:\\z-bank\\bank\\PY\\wg.flv")
out=cv2.VideoWriter('D:\\z-bank\\bank\\PY\\out.avi',cv2.VideoWriter_fourcc(*'XVID'),25.0,(640,480))
if vd.isOpened(): open,frame=vd.read() else: open=False while open: ret,frame=vd.read() if frame is None: break
if ret==True: frame=cv2.flip(frame,0) out.write(frame) cv2.imshow('frame',frame) if cv2.waitKey(1) & 0xFF==ord('q'): break
vd.release() cv2.destroyAllWindows()
|