Sub.1 OpenCV介绍
OpenCV:开放源代码计算机视觉库,由一系列C++类和函数构成,用于图像处理、CV领域算法实现。
Pt.1 OpenCV优势
- 开源免费
- 多语言支持:C++原生接口、Java、Python等
- 跨平台:支持多种操作系统
- 丰富API:完善的传统计算机视觉算法,涵盖主流的机器学习算法,同时添加了对深度学习的支持。
Pt.2 OpenCV-Python
- 原始OpenCV C++ 实现的Python包装器(C++高效性和Python的简洁易用)
- 可使用C/C++扩展,在其中编写计算密集型代码
- OpenCV-Python使用Numpy,所有数组结构都换转换为Numpy数组
Pt.3 环境安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
Sub.2 图像基础知识
It.1 图像表示
- 图像的基本单元:像素
- 每个像素存储着图像的颜色、亮度和其他特征。
- OpenCV常用的是8位图像:每个通道的像素值由8位2进制表示。
-
- 范围:0~255
- 0表示最黑,1表示最白
- RGB三原色图:
-
- 红绿蓝,三种颜色被称为RGB三通道(每个通道0~255)
- RGB颜色模式可以合成 256^3 种颜色(1600W)
It.2 图像存储
OpenCV中,坐标系:以左上角为原点,往右为W正方向,往下为H正方向
- 在OpenCV中,无论读取还是创建图像,结果都是一个NumPy数组
-
- 彩色图像:三维数组(三通道图像)
- 灰度图像:二维数组(单通道图像)
- 图像本质是像素值的矩阵
-
- 形状(shape)
-
-
img.shape
属性来获取图像尺寸,包括高(height)、宽(width)、通道数(channels).- 彩色图像(如RGB):返回的是一个包含三个值的元组(H, W, C)
- 灰度图像:返回的是一个包含两个值的元组 (H, W)
-
-
- 数据类型(dtype)
-
-
- uint8 0~255 (256个值)
-
-
- 像素表示
-
-
- 单通道图像(灰度图像):每个像素由一个数值表示,代表亮度(0最暗、255最亮)
- 多通道图像(彩色图像):OpenCV中,默认以 BGR (蓝绿红)顺序存储
-
Sub.3 基本图像操作
It.1 创建窗体
cv2.namedWindow(winname [,窗口属性])
- 窗口属性:窗口大小是否可调整
-
cv2.WINDOW_AUTOSIZE
:默认,根据图像自动调整大小,用户不可调整。cv2.WINDOW_NORMAL
:窗口大小用户可调整。
It.2 读取图像
cv2.imread(path [,读取方式])
- 读取方式:
-
- 默认彩色,
cv2.IMREAD_COLOR
- 灰度图像:
cv2.IMREAD_GRAYSCALE
- 默认彩色,
- 文件路径:
-
./
表示当前目录。../
表示当前目录的上一级目录(父目录)
It.3 显示图像
cv2.imshow(winname, img)
- winname以字符串类型表示
- 会自动创建窗口
注意:
- 在调用显示图像的API后,要调用cv2.waitKey(0)给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来。
-
cv2.waitKey(0)
:无限期地等待任何键盘按键,直到用户决定关闭。(常用于图像显示窗口)cv2.waitKey(n)
:n>0 表示等待n毫秒,同时允许用户通过按键中断循环或发出命令。(常用于视频播放或实时摄像头捕获场景,以便控制每一帧停留时间)
- cv2.destroyAllWindows([winname])
It.4 保存图像
cv2.imwrite(path, img)
path
:图片保存的路径和图片名,如cv2.imwrite("./images/001.jpg",img)img
:保存的图像
It.5 图像切片(图片剪裁)
img[y : y+h, x : x+w]
- 提取从(x, y) 开始,高度为h,宽为w的矩形区域
import cv2 as cv
# 读取图像
img = cv.imread("./images/CuteCat.jpg")
cat = cv.resize(img,(600,600))
print(cat.shape)
# 定义剪裁起始点(坐标小于图片宽高)
x = 200
y = 200
# 定义裁剪图像的宽高(像素为单位)
h = 400
w = 400
# 通过切片裁剪图像
cat_roi = cat[y : y+h, x : x+w]
print(cat_roi.shape)
# 显示图像
cv.imshow("cat", cat)
cv.imshow("cat_roi", cat_roi)
cv.waitKey(0)
cv.destroyAllWindows()
- tips:
-
- 需要边界检查,越界会报错
- 数据类型:ndarray
It.6 图像大小调整
cv2.resize(img, dsize, dts)
disze
: (W, H)- 会返回新图像'
import cv2
# 读图
img = cv2.imread("path")
# 写法1:直接设置修改的尺寸 (W,H)
re1 = cv2.resize(img, (600,600))
# 写法2:设置缩小/放大的比例
re2 = cv2.resize(img, (0,0), fx=0.5, fy=0.5)
re3 = cv2.resize(img, None, fx=0.5, fy=0.5) # 两种都可
Sub.3 图像绘制
原地操作,直接改变原图像
It.1 绘制直线
cv2.line(img, start, end, color, thickness)
color
:彩色图像使用 BGR格式指定颜色(OpenCV以默认以BGR顺序存储)thickness
:线条宽度。
It.2 绘制圆形
cv2.circle(img, centerpoint, r, color, thickness)
centerpoint
、r
:圆心和半径。thickness
:为-1时生成闭合图案并填充颜色。cv2.LINE_AA
:反走样技术,抗锯齿,使边缘更加平滑。
-
- lineType参数,默认是
cv2.LINE_8
- 反走样技术通过混合颜色和像素边缘来减少锯齿状效果。
- lineType参数,默认是
It.3 绘制矩形
cv2.rectangle(img, leftupper, rightdown, color, thickness)
It.4 绘制文本
cv2.putText(img, text, org, fontFace, Fontscale, color, thickness)
- cv2.putText(图像,文本,写入位置,字体样式,字体大小,颜色,线条粗细)
-
- 这个方法无法绘制中文
import cv2 as cv
# 图像绘制:原地操作,不会返回新的图像
img = cv.imread("./images/CuteCat.jpg")
cat = cv.resize(img, (500, 500))
# 绘制直线, color 按 BGR顺序排列
cv.line(cat,(0,0),(500,500),(255,0,0),3)
# 绘制圆形,线条粗细 -1 表示填充
cv.circle(cat,(100,100),50,(0,255,0),-1,cv.LINE_AA)
# cv.LINE_AA 抗锯齿(反走样技术,如果不使用,默认参数是cv.LINE_8)
# 绘制矩形
cv.rectangle(cat, (300,300), (400,400), (0,0,255), 3)
# 绘制文本:像图片中添加文字
cv.putText(img=cat,
text="Cat Cute People Bad",
org=(100,450),
fontFace=cv.FONT_HERSHEY_COMPLEX,
fontScale=1,
color=(255,255,255),
thickness=2,
lineType=cv.LINE_AA)
# 显示图像
cv.imshow("draw", cat)
cv.waitKey(0)
cv.destroyAllWindows()
输出
It.5 绘制多边形
cv2.polylines(img, pts, isClosed, color, thickness=1)
pts
: 包含多边形顶点坐标的数组
-
- 使用时:
-
-
- 参数是包含特征点的数组
- 需要转换为整数,使用
.astype(np.int32)
- 最后,将其封装到列表里
- 多个多边形,可以依次放入列表
[pts1, pts2, ...]
-
原理
- 像素坐标是整数,需要转换类型来保证
- 封装到列表:src的shape一般是
(n,2)
→ 代表有n个顶点,2对应(x,y)坐标。
[]
封装到列表后,就变成了[array(shape=(n, 2))]
,OpenCV会将列表中的这个数组当成一个整体,然后去自动解析为 (n,1,2)的数组,进行后续处理。
isClosed
:是否封闭图形 → True 则连接首尾顶color
:可以是三元组 / 四元组 / 整数 → BGR / BGRA / 灰度值
Sub.4 读取视频
cap = cv2.VideoCapture(path)
- 返回一个视频捕获对象
- path:视频流资源路径,设置为0代表从默认摄像头捕获实时视频流
ret, frame = cap.read()
ret
(布尔值):是否成功读取帧。
-
- True:读取成功,frame为当前帧图像(BGR 格式的 numpy 数组)
- False:读取失败(如视频结束、路径错误、摄像头未连接)
frame
:当前帧图像数据。
代码示例
import cv2 as cv
# 创建VideoCapture对象
cap = cv.VideoCapture(0) # 摄像头索引或本地视频路径,记得使用r字符串
while True:
ret,frame=cap.read()
if not ret:
print("出错")
break
cv.imshow("frame",frame)
# cv.waitKey(40)&0xFF :等待40毫秒判断是否有按键触发,有返回ASCII码,没有返回-1
if cv.waitKey(40)&0xFF == ord('q'):
break
# 释放摄像头资源
cap.release()
cv.destroyAllWindows()
- 获取按键事件
-
- ord(c) 字符转编码; chr(i) 编码转字符
- 0xFF : 16进制,在二进制里是11111111,在这里和获取到的按键按位与 &
作用:把返回值的低8位保留下来,确保得到的是按键对应的 8 位 ASCII 码值。