读,写,显示图像
\qquad
OpenCV中的imread(),imwrite()和imshow()函数分别用于读,写和显示图像。其中imread()函数用于将文件中的图像读入内存,它支持各种静态图像文件格式,如BMP,PNG,JPEG,TIFF等。
\qquad
imread()函数返回一个 numpy.ndarray 对象(即 NumPy 数组),数组元素为图像的像素。OpenCV 使用 NumPy 数组来保存图像,数组的 shape(数组形状)、dtype(数据类型)、size(数组元素个数)等属性表示图像的相关属性。下面的代码使用的图像为彩色 JPG 图像,img.shape 的输出结果为(512, 512,3),说明表示彩色图像的数组是一个三维数组,3 个值依次表示图像的高度、宽度和通道数;图像的分辨率为 512×512。代码中 img.dtype的输出结果为 uint8,说明每个数组元素用一个字节(8 位)保存,每个数组元素为一个像素B,G和R通道的颜色。颜色取值范围为[0, 255]。
1.读取图像
import cv2
img = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_GRAYSCALE_4)
print(type(img))
print(img)
print(img.shape)
print(img.dtype)
print(img.size)
2.写入图像
import cv2
import numpy
img = numpy.zeros((300, 300), dtype=numpy.uint8)
cv2.imwrite('text_2.jpg', img)
3.显示图像
\qquad
inshow()函数的第一个参数为窗口名称,第二个参数为图像数组。其中,在使用时,这两个参数缺一不可,如果缺了一个会报错,如果窗口名称输入的是中文,会显示乱码,因为imshow函数的窗口标题是gbk编码,而Python3默认UTF-8编码。因而窗口标题包含中文时,会显示乱码。解决这个问题,最直接就是从标题的编码入手,在参数后面加这行代码.encode(“gbk”).decode(errors=“ignore”)强制转换编码方式,如:
cv2.imshow('lena'.encode("gbk").decode(errors="ignore"), img)
但转换有风险,不一定百分之百正确,也不一定可以显示出来,最好还是使用英文。
\qquad
在显示图像时,程序创建的图像窗口会在显示后立即关闭,所以为了图像显示更久一点,可使用waitKey()函数等待用户输入来控制窗口的关闭,其中该函数的基本格式如下:
rv = cv2.waitkey([delay])
其中,rv 保存函数返回值,如果没有键被按下,返回-1;如果有键被按下,返回键的 ASCII码。参数 delay 表示等待按键的时间(单位为毫秒),负数或 0 表示无限等待,默认值为 0;设置了delay参数时,等待时间结束时结束等待,函数返回-1。
import cv2
img = cv2.imread('lena.jpg')
cv2.imshow('lena', img)
cv2.waitKey(0)
读,写,播放视频
\qquad
OpenCV 的 VideoCapture 类和 VideoWriter 类提供了视频处理功能,支持各种格式的视频文件。 视频处理的基本操作步骤如下。 (1)将视频文件或者摄像头作为数据源来创建 VideoCapture 对象。 (2)调用 VideoCapture 对象的 read()方法获取视频中的帧,每一帧都是一幅图像。 (3)调用 VideoWriter 对象的 write()方法将帧写入视频文件,或者调用 cv2.imshow()函数在窗口中显示帧(即播放视频)。
播放视频
在播放视频时,一般会使用cv2.waitKey()函数来设置延迟时间,如果不设置延迟时间,视频的播放速度会非常快,一般设置延迟时间为25毫秒。
import cv2
vc = cv2.VideoCapture('test2-5.mp4')
fps = vc.get(cv2.CAP_PROP_FPS)
size = (vc.get(cv2.CAP_PROP_FRAME_WIDTH),
vc.get(cv2.CAP_PROP_FRAME_HEIGHT))
print('帧率:', fps)
print('大小:', size)
success, frame = vc.read()
while success:
cv2.imshow('myvideo', frame)
success, frame = vc.read()
key = cv2.waitKey(25)
if key == 27:
break
vc.release()
将视频写入文件
将视频写入文件与播放视频类似,需要逐帧将视频写入文件。在创建 VideoWhiter 对象时,可指定保存视频的文件名、视频解码器格式、帧速率和大小。cv2.VideoWhiter_ fourco()函数用 4 个字符来指定解码器格式,通过解码器格式生成相应格式的视 频文件。常用的解码器格式如下:
函数 | 解码器格式 |
---|
cv2.VideoWrter_ fourco(‘P’,‘I’,‘M’,‘1’) | XVID的 MPEG-1 编码格式,视频文件扩展名为.avi | cv2.VideoW/riter_fourco(‘M’,‘P’,‘4’,‘2’) | Microsoit的MPEG-4 编码格式,视频文件扩展名为,avi | c2.VideoWriter_fourco(‘X’,‘V’,‘I’,‘D’) | XVID 的 MPEG-4 编码格式,视频文件扩展名为,avi | c2.VideoWriter_fourco(‘F’,‘L’,‘V’,‘1’) | XVID 的 MPEG-4 编码格式,视频文件扩展名为,flv |
import cv2
vc = cv2.VideoCapture('test2-5.mp4')
fps = vc.get(cv2.CAP_PROP_FPS)
size = (int(vc.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(vc.get(cv2.CAP_PROP_FRAME_HEIGHT)))
vw = cv2.VideoWriter('test2-6out.avi',
cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'),
fps,size)
success, frame = vc.read()
while success:
vw.write(frame)
success, frame = vc.read()
vc.release()
捕获摄像头视频并将视频写入文件
要捕获摄像头视频,需要将摄像头的ID作为参数来创建VideoCapture对象。通常0表示默认摄像头。
import cv2
vc = cv2.VideoCapture(0)
fps = 30
size = (int(vc.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(vc.get(cv2.CAP_PROP_FRAME_HEIGHT)))
vw = cv2.VideoWriter('test2-7out.avi',
cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'),
fps, size)
success, frame = vc.read()
while success:
vw.write(frame)
cv2.imshow('MyCamera', frame)
key = cv2.waitKey(25)
if key == 27:
break
success, frame = vc.read()
vc.release()
操作灰度,色彩图像
操作灰度图像
通常,计算机将灰度处理为256级(0~255),0表示黑色,255表示白色,用一个字节来存储一个像素的值。OpenCV使用单通道的二维数组来表示灰度图像。 代码中的“img[:,:]=n”语句将图像的全部像素值修改为 n,n 的值在程序运行过程中不断增大。从运行结果可看到输出的像素值不会大于 255。当 n 大于 255 时,因为数组元素的数据类型为numpy.uint8,所以 OpenCV 会自动按 256 取模。
import cv2
import numpy
img = numpy.zeros((240, 320), dtype=numpy.uint8)
n = 0
while True:
cv2.imshow('GrayImg', img)
n += 20
img[:, :] = n
print(img[1, 1])
key = cv2.waitKey(1000)
if key == 27:
break
操作彩色图像
不同色彩空间中,颜色的表示方法有所不同,但不同色彩空间之间可根据公式进行转换。下面我们简单介绍 RGB 色彩空间中图像的表示方法。RGB 中的R 指红色(Red),G指绿色(Green),B 指蓝色(Blue)。在表示图像时,有 R、G 和 B 3 个通道,分别对应红色、绿色和蓝色。每个通道中像素的取值范围为[0,255]),用 3 个通道的像素组合表示彩色图像。RGB色彩空间颜色通道依次为 B、G、R,但 OpenCV 默认的图像格式为 BGR,即颜色通道依次为B,G,R。
import cv2
import numpy
img = numpy.zeros((240, 320, 3), dtype=numpy.uint8)
r0 = 0
r1 = 1
r2 = 2
while True:
img[:80, :, r0] = 255
img[80:160, :, r1] = 255
img[160:, :, r2] = 255
cv2.imshow('ColorImg', img)
key = cv2.waitKey(1000)
img[:, :, :] = 0
t = r0
r0 = r1
r1 = r2
r2 = t
if key == 27:
break
图像通道操作
通过数组索引拆分通道
OpenCV中BGR格式的图像是一个三维数组,可用数组的索引操作来拆分3个色彩通道。
import cv2
img = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2)
cv2.imshow('lena', img)
b = img[:, :, 0]
g = img[:, :, 1]
r = img[:, :, 2]
cv2.imshow('lena_B', b)
cv2.imshow('lena_G', g)
cv2.imshow('lena_R', r)
cv2.waitKey(0)
使用cv.split()函数来拆分通道
import cv2
img = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2)
cv2.imshow('lena', img)
b, g, r = cv2.split(img)
cv2.imshow('lena_B', b)
cv2.imshow('lena_G', g)
cv2.imshow('lena_R', r)
cv2.waitKey(0)
合并图像通道
import cv2
img = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2)
cv2.imshow('lena', img)
b, g, r = cv2.split(img)
rgb = cv2.merge([r, g, b])
gbr = cv2.merge([g, b, r])
cv2.imshow('lena_RGB', rgb)
cv2.imshow('lena_GBR', gbr)
cv2.waitKey(0)
图像运算
OpenCV使用的是NumPy数组来表示图像,所以我们可以很方便的执行基于数组的图像运算。
加法运算
加法运算符“+”和 cv2.add()函数可用于执行图像加法运算。 用“+”运算符执行两个图像数组加法时,如果两个像素相加大于 256,则会将其按 256 取模。CV2.add()函数执行两个图像数组加法时,如果两个像素相加大于 256,则取 255。
import cv2
img1 = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2)
img2 = cv2.imread('opencvlog.jpg', cv2.IMREAD_REDUCED_COLOR_2)
img3 = img1+img2
img4 = cv2.add(img1, img2)
cv2.imshow('lena', img1)
cv2.imshow('log', img2)
cv2.imshow('lena+log', img3)
cv2.imshow('lenaaddlog', img4)
cv2.waitKey(0)
加权加法运算
cv2.addWeighted()函数可执行图像的加权加法运算,其基本格式如下。
dst = cv2.addweighted(src1, alpha, srcz, beta, gamma)
其中,变量 dst 保存结果,src1 和 src2 为执行加权加法运算的两个图像数组,alpha和 beta 为权重,gamma为附加值。OpenCV 按下面的公式执行图像数组的加权加法运算。
dst = src1*alpha + src2*beta + gamma
import cv2
img1 = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2)
img2 = cv2.imread('opencvlog.jpg', cv2.IMREAD_REDUCED_COLOR_2)
img3 = cv2.addWeighted(img1, 0.5, img2, 0.5, 0)
cv2.imshow('lena', img1)
cv2.imshow('log', img2)
cv2.imshow('lena+log', img3)
cv2.waitKey(0)
位运算
在学习OpenCV中对图像的位运算前,我们先回顾下位运算 程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。比如,&运算本来是一个逻辑运算符,但整数与整数之间也可以进行&运算。举个例子,6的二进制是110,11的二进制是1011,那么6 & 11的结果就是2,它是二进制对应位进行逻辑运算的结果(0表示False,1表示True,空位都当0处理)。
下面是位运算的规则:
OpenCV 提供了如下图像位运算函数:
函数 | 解释 |
---|
cv2.bitwise_and(src1,src2[,mask]) | mask 对应的位不为 0时,图像src1 和 src2 执行按位与操作 | cv2.bitwise_orsrc1,src2[,mask]) | mask对应的位不为 0时,图像 sic1 和 sic2执行按位或操作 | cv2.btwise _not(src1[,mask]) | mask对应的位不为0时,图像 sic1执行按位取反操作 | cv2.btwise _xor(src1,src2[,mask]) | mask 对应的位不为 0时,图像 src1 和 sic2执行按位异或操作 |
import cv2
src1 = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2)
src2 = cv2.imread('opencvlog.jpg', cv2.IMREAD_REDUCED_COLOR_2)
img3 = cv2.bitwise_and(src1, src2)
img4 = cv2.bitwise_or(src1, src2)
img5 = cv2.bitwise_not(src1)
img6 = cv2.bitwise_xor(src1, src2)
cv2.imshow('lena', src1)
cv2.imshow('log', src2)
cv2.imshow('lenaandlog', img3)
cv2.imshow('lenaorlog', img4)
cv2.imshow('lenanotlog', img5)
cv2.imshow('lenaxorlog', img6)
cv2.waitKey(0)
代码素材
|