OpenCV
- OpenCV(开放源代码计算机视觉库)介绍
- 是一个开源计算机视觉和机器学习软件库。由一系列C++类和函数构成,用于图像处理、计算机视觉领域的算法实现
- OpenCV优势
- 开源免费
- 多语言支持
- 跨平台
- 丰富API
- OpenCV-Python
- 为原始OpenCV C++实现的python包装器,结合了OpenCV C++ API的高性能和python语言的易用性和简洁性
- 如何解决Python与C/C++等语言相比,速度较慢的问题?
- python可以使用C/C++扩展
- 在C/C++中编写计算密集型代码
- 创建可用作python模块的python包装器
如此可在python中调用后台的C/C++代码,速度将和C/C++一样快,同时在python中编写代码也更加容易。
- OpenCV-Python使用Numpy,所有OpenCV数组结构都转换为Numpy数组。
- Numpy是一个高度优化的数据操作库,OpenCV使用Numpy也使得OpenCV使用Numpy的其他库集成变得更加容易。
环境安装
win+R调出窗口后输入cmd打开命令行界面
输“ activate 环境名”激活虚拟环境
输入命令:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
完成安装(在pycharm中使用需要进行虚拟环境配置,具体步骤在这不详细赘述)
图像表示
这里所需的理论知识有:
- OpenCV常用8位图像,大多数彩色和灰度图像使用8位表示每个通道的像素值,范围从0-255,0代表最黑,1表示最白
- 日常生活常见图像由RGB三原色(R:红色,G:绿色,B:蓝色)三个颜色按比例混合而成
- 计算机中称RGB三原色为RGB三通道,每个通道取值为0-255,根据三个通道存储的像素值来对应不同颜色
图像存储
在OpenCV中,无论是读取还是创建图像,结果都是一个NumPy数组。
- 彩色图像:三维数组
- 灰度图像:二维
图像本质上是像素值的二维或三维矩阵(对于彩色图像)。
- 形状(Shape):图像的尺寸由其高(height)、宽(width)和通道数(channels)决定。可以通过
img.shape属性获取这些信息。- 对于彩色图像(如RGB),返回的是一个包含三个值的元组 (height, width, channels)。
- 对于灰度图像,返回的是一个包含两个值的元组 (height, width),因为灰度图像只有一个通道。
- 数据类型(dtype):图像中的每个像素值的数据类型决定了可以存储的最大值。例如,8位无符号整数(uint8)允许的范围是从0到255。
- 像素表示
- 单通道图像(灰度图像):每个像素由一个数值表示,代表该点的亮度。值越低(接近0),颜色越暗;值越高(接近255),颜色越亮。
- 多通道图像(彩色图像):在OpenCV中,默认情况下,彩色图像是以BGR(蓝-绿-红)顺序存储
-
彩色图像
- 每个像素通常是由红(R)、绿(G)、蓝(B)三个分量来表示的,分量介于(0,255)。
- RGB图像每一个像素的颜色值(由RGB三原色表示)直接存放在图像矩阵中,由于每一像素的颜色需由R、G、B三个分量来表示,M、N分别表示图像的行列数,三个M x N的二维矩阵分别表示各个像素的R、G、B三个颜色分量。
- RGB图像的数据类型一般为8位无符号整型,通常用于表示和存放彩色图像。
基本图像操作
- 创建窗体:cv.nameWindow()
import cv2 as cv
#创建窗体
cv.namedWindow("mywindow", cv.WINDOW_AUTOSIZE)
cv.namedWindow("mywindow2", cv.WINDOW_NORMAL)
#autosize:无法手动调整窗口大小;normal:正常,可以手动调整
- 读取图像:cv.imshow(winname,img)
img = cv.imread("../images/1.jpg")
gray = cv.imread("../images/1.jpg",cv.IMREAD_GRAYSCALE)#读取灰度图片
# print(img)
# print(img.shape)#(h,w,c)
# print(img.dtype)
#print(gray,gray.shape,gray.dtype)
注意这里的路径,不要写错了,放在同一个根目录下的文件可以../读取的方式,当然直接找到文件复制文件路径也可。
- 保存图片(cv.imwrite)
cv.imwrite("./gray.jpg",gray)
- 显示图像(cv.imshow)
cv.imshow("mywindow", img)
cv.imshow("mywindow2", gray)
#留下绘制时间,等待n毫秒,0代表一直等代
cv.waitKey(0)
#销毁窗口释放资源
cv.destroyAllWindows()
运行结果分别弹出两个弹窗:


注意:在调用显示图像的API后,要调用cv.waitKey(0)给图像绘制留下时间,否则窗口会出现无响应的情况,并且图像无法显示出来
cv.waitKey(0):表示无限期等待任何键盘按键。这种用法常见于图像显示窗口中,确保图像在窗口中显示直到用户关闭它
cv.waitKey(n):n>0,意味着程序将等待n毫秒。这种方式常用于视频播放或实时摄像头捕获场景,以便控制每一帧停留的时间,同时允许用户通过按键来中断循环或发出命令。
- 创建黑白、随机像素的图片文件
这里使用np.zeros()创建全黑图像,再修改像素值成为全白图像。
import cv2 as cv
import numpy as np
#创建黑色图像
black=np.zeros((640,480,3),dtype=np.uint8)
cv.imshow("black",black)
#创建白色图像
white=np.ones((640,480,3),255,dtype=np.uint8)
cv.imshow("white",white)
#修改黑图里面的像素值为255
black[:,:,:]=255
cv.imshow("white2",black)
#创建随机像素的图像
random=np.random.randint(0,256,(640,480,3),dtype=np.uint8)
cv.imshow("random",random)
cv.waitKey(0)
cv.destroyAllWindows()
运行结果有两个弹窗图片:


- 图像切片
- OpenCV中图像切片用于从图像中提取一个子区域(矩形区域)
- 一个图像img,类型为numpy.ndarray
img[y:y+h,x:x+w]的含义如下- x:子区域左上角的x坐标
- y:子区域左上角的y坐标
- w:子区域的宽度
- h:子区域的高度
- 切片操作
-
img[y:y+h,x:x+w]提取的是从(x,y)开始,高度为h,宽度为w的矩形区域
-
注意:
边界检查:确保(y,x)和(y+h,x+w)都在图像的边界内,否则会出现索引越界错误。
数据类型:img通常是numpy.ndarray类型,切片操作返回的也是numpy.ndarray类型。
import cv2 as cv
#读图
cat = cv.imread("../images/cat1.png")
#剪裁(380,240)(477,374)
roi=cat[240:374,380:477]
roi2=cat[370:454,426:516]
cv.imshow("eye",roi)
cv.imshow("nose",roi2)
cv.waitKey(0)
cv.destroyAllWindows()
剪裁结果如下:例子中进行了两次截取,分别实时眼睛和鼻子


注意:如在截取的对象上做修改,原图也会跟着被修改,是因为提取的对象内存地址与原图被截取部分的内存地址相同
- 图像大小调整
- cv.resize(img,dsize):用于调整图像大小,对图像进行缩放
- img:输入图像,通常为二维或三维Numpy数组
- dsize:输出图像所需尺寸,是一个元组(w,h)
import cv2 as cv
#读图
cat=cv.imread("../images/cat1.png")
#调整图像大小(w,h)
dst=cv.resize(cat,(640,480))
cv.imshow("cat",cat)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows()
输出结果如下图:原图像尺寸被缩小

-
图像绘制
- 绘制直线(cv.line(img,sart,end,color,thickness))
- img:需要绘制直线的图像
- sart/end:直线的起点和重点,一般为两个坐标点
- color:直线的颜色(对于彩色图像,使用BGR格式指定颜色)
- thickness:线条宽度
-
import cv2 as cv #读图 cat = cv.imread("../images/cat1.png") #绘制直线 cv.line(cat,(200,250),(200,350),(0,0,255),2) cv.imshow("cat",cat)
- 绘制矩形(cv.rectangle(img,leftupper,rightdown,color,thickness))
- img:需要绘制矩形的图像
- leftupper/rightdown:矩形的左上角和右下角坐标
- color:线条颜色
- thickness:线条宽度
-
#绘制矩形 cv.rectangle(cat,(426,370),(516,454),(0,255,0),2)
- 绘制圆(cv.circle(img,centerpoint,r,color,thickness))
- img:需要绘制圆形的图片
- centerpoint\r:圆心和半径
- color:线条颜色
- thickness:线条宽度,为-1时生成闭合图案并填充颜色
-
#绘制圆 cv.circle(cat,(427,309),30,(255,0,0),1,cv.LINE_AA)#line_aa抗锯齿,平滑
- 绘制直线(cv.line(img,sart,end,color,thickness))
完整绘图代码如下:
import cv2 as cv
#读图
cat = cv.imread("../images/cat1.png")
#绘制直线
cv.line(cat,(200,250),(200,350),(0,0,255),2)
cv.imshow("cat",cat)
#绘制矩形
cv.rectangle(cat,(426,370),(516,454),(0,255,0),2)
#绘制圆
cv.circle(cat,(427,309),30,(255,0,0),1,cv.LINE_AA)#line_aa抗锯齿,平滑
cv.imshow("cat",cat)
cv.waitKey(0)
cv.destroyAllWindows()
绘制结果如下所示:

- 读取视频
- cap=cv.VideoCapture(path)
- path:视频流资源路径设置为0时,代表默认摄像头捕获视频流
- ret,frame=cap.read()
- 返回值cap调用read()方法得到一个布尔值和一帧画像
- 布尔值代表是否成功读取到帧,若为False可能因为视频结束或者读取失败
- 布尔值若为True,frame则是当前帧的图像数据
- cap=cv.VideoCapture(path)
import cv2 as cv
#创建一个videocapture对象
#传具体路径、读取视频文件
cap=cv.VideoCapture("../images/videocap.mp4")
#循环读取每一帧图像
while True:
ret,frame=cap.read()
#判断是否读取成功
if not ret:
print("读取失败!")
break
cv.imshow("video",frame)
if cv.waitKey(40)&0xFF==ord('q'):
print("按键退出")
break
cap.release()
cv.destroyAllWindows()
读出的视频文件会跳出自动进行播放,其中循环语句中的代码解释如下:
- while True创建无限循环持续读取视频
- cap.read()读取一帧视频,ret表示读取是否成功,frame是帧数据
- 如果读取失败则打印提示并退出循环
- cv.imshow()显示当前帧
- cv.waitKey(40)等待40毫秒,按'q'键退出程序
这里注意cv.waitKey(40)&0xFF==ord("q")中:
- cv.waitKey(40):等待40毫秒检测按键事件
- &0xFF:按位与操作,确保只取低8位字节值
- ==ord('q'):比较按键的ASCII码是否等于'q'字符的ASCII码(113)
- 整体用于OpenCV中退出循环的条件判断
读取摄像头视频流只需读取视频路径时输入值为0即可,代码如下:
import cv2 as cv
#创建一个videocapture对象
#传具体路径、读取视频文件
#传0。从默认摄像头获取实时视频流
cap2=cv.VideoCapture(0)
#循环读取每一帧图像
while True:
ret,frame=cap.read()
#判断是否读取成功
if not ret:
print("读取失败!")
break
cv.imshow("video",frame)
if cv.waitKey(40)&0xFF==ord('q'):
print("按键退出")
break
cap.release()
cv.destroyAllWindows()
此时会弹出摄像头所获取的实时画面。
&spm=1001.2101.3001.5002&articleId=149781399&d=1&t=3&u=543feda99b9842078d111ddb96c739bf)
11万+

被折叠的 条评论
为什么被折叠?



