1.opencv—图像处理基础
Posted cpLoners
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.opencv—图像处理基础相关的知识,希望对你有一定的参考价值。
opencv——图像处理基础
读,写,显示图像
\\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) # 创建300*300的黑色正方形图像
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') # 读取图像,缩小为原来的1/2
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') # 创建VideoCapture对象
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() # 读第1帧
while success: # 循环读视频帧,直到视频结束
cv2.imshow('myvideo', frame) # 在窗口中显示帧图像
success, frame = vc.read() # 读下一帧
key = cv2.waitKey(25)
if key == 27: # 按Esc键退出
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') # 创建VideoCapture对象
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() # 读第1帧
while success: # 循环读视频帧,直到视频结束
vw.write(frame) # 将帧写入文件
success, frame = vc.read() # 读下一帧
vc.release() # 关闭视频
捕获摄像头视频并将视频写入文件
要捕获摄像头视频,需要将摄像头的ID作为参数来创建VideoCapture对象。通常0表示默认摄像头。
import cv2
vc = cv2.VideoCapture(0) # 创建VideoCapture对象,视频源为默认摄像头
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() # 读第1帧
while success: # 循环读视频帧,直到视频结束
vw.write(frame) # 将帧写入文件
cv2.imshow('MyCamera', frame) # 显示帧
key = cv2.waitKey(25)
if key == 27: # 按Esc键结束
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) # 延迟1秒
if key == 27:
break # 按【Esc】键结束
操作彩色图像
不同色彩空间中,颜色的表示方法有所不同,但不同色彩空间之间可根据公式进行转换。下面我们简单介绍 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 # 通道r0上三分之一颜色值设为255
img[80:160, :, r1] = 255 # 通道r1中部三分之一颜色值设为255
img[160:, :, r2] = 255 # 通道r2下三分之一颜色值设为255
cv2.imshow('ColorImg', img)
key = cv2.waitKey(1000) # 延迟1秒
img[:, :, :] = 0 # 像素全部置0
t = r0 # 轮换通道序号
r0 = r1
r1 = r2
r2 = t
if key == 27:
break # 按【Esc】键结束
图像通道操作
通过数组索引拆分通道
OpenCV中BGR格式的图像是一个三维数组,可用数组的索引操作来拆分3个色彩通道。
import cv2
img = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2) # 读取图像,缩小为原来的1/2
cv2.imshow('lena', img) # 显示原图像
b = img[:, :, 0] # 获得B通道图像
g = img[:, :, 1] # 获得G通道图像
r = img[:, :, 2] # 获得R通道图像
cv2.imshow('lena_B', b) # 显示B通道图像
cv2.imshow('lena_G', g) # 显示G通道图像
cv2.imshow('lena_R', r) # 显示R通道图像
cv2.waitKey(0)
使用cv.split()函数来拆分通道
import cv2
img = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2) # 读取图像,缩小为原来的1/2
cv2.imshow('lena', img) # 显示原图像
b, g, r = cv2.split(img) # 按通道拆分图像
cv2.imshow('lena_B', b) # 显示B通道图像
cv2.imshow('lena_G', g) # 显示G通道图像
cv2.imshow('lena_R', r) # 显示R通道图像
cv2.waitKey(0)
合并图像通道
import cv2
img = cv2.imread('lena.jpg', cv2.IMREAD_REDUCED_COLOR_2) # 读图像,缩小为原来的1/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) # 显示add()图像
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) # 显示addWeighted()图像
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)
代码素材
以上是关于1.opencv—图像处理基础的主要内容,如果未能解决你的问题,请参考以下文章
计算机视觉OpenCV 4高级编程与项目实战(Python版):图像处理基础
计算机视觉OpenCV 4高级编程与项目实战(Python版):图像处理基础