【OpenCV篇】OpenCV——01day.图像基础
目录
前言
1 0penCV介绍
1.1 0penCV优势
1.2 OpenCV-Python
2 环境安装
3 图像表示
4 图像存储
4.1彩色图像
5 基本图像操作
5.1 创建窗体
5.2 读取图像
5.3 显示图像
5.4 保存图像
5.5 创建黑白图像
5.6 图像切片(图片剪裁)
5.7 图像大小调整
6 图像绘制
6.1 绘制直线
6.2 绘制圆形
6.3 绘制矩形
6.4 绘制文本(向图片中添加文字)
6.5 读取视频
总结
前言
这篇文章介绍了OpenCV-Python的基本概念和核心功能,会讲到环境安装、图像原理、图像的基础操作等内容
1 0penCV介绍
OpenCV(Open Source Computer Vision Library)是一个功能强大的开源计算机视觉和机器学习库。该库基于C++编写,提供丰富的图像处理算法和计算机视觉工具,广泛应用于实时图像分析、目标检测、三维重建等视觉计算任务。其模块化架构包含优化的核心算法和扩展功能,支持跨平台部署,为开发者提供了高效的视觉应用开发解决方案。
1.1 0penCV优势
- 开源免费:OpenCV采用开源协议,用户可自由使用、修改和分发,无需支付许可费用。这一特性显著降低了开发成本,尤其适合学术研究和小型项目。
- 多语言支持:提供C++原生接口,同时封装了Python、Java等流行语言的API。这种多语言兼容性使得开发者能根据项目需求选择合适的编程环境,兼顾性能与开发效率。
- 跨平台能力:支持Windows、Linux、macOS、iOS和Android等主流操作系统。跨平台特性确保算法能在不同设备上无缝部署,适应从服务器到移动端的多样化场景。
- 功能覆盖:内置超过2500种优化算法,涵盖图像处理、特征提取、目标检测等传统计算机视觉任务,并集成深度学习模块(如DNN)。API设计兼顾经典方法与前沿技术,满足从基础到进阶的开发需求。
1.2 OpenCV-Python
1、OpenCV-Python 是 OpenCV C++ 实现的 Python 接口,既保留了 C++ 的高性能,又具备 Python 的易用性。它支持图像处理、计算机视觉算法以及机器学习任务,广泛应用于研究和工业领域。Python 语言本身执行速度较慢,但 OpenCV-Python 通过底层 C++ 加速弥补了这一缺点。其核心计算由 C++ 实现,再封装为 Python 模块,因此在保持高效的同时简化了代码编写。
2、OpenCV-Python 使用 NumPy 进行数组运算,所有 OpenCV 数据结构(如 Mat)均自动转换为 NumPy 数组。这种设计带来以下优势:
- 可直接调用 NumPy 的优化函数进行高效矩阵运算。
- 便于与 SciPy、Matplotlib 等科学计算库集成,扩展数据处理和可视化能力。
2 环境安装
# 终端安装命令
pip install opencv-python # 镜像源
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
3 图像表示
像素的基本概念与存储方式:
像素作为数字图像的最小单元,承载着颜色、亮度等视觉信息。计算机通过二进制编码系统存储和处理像素数据,将每个像素转换为由0和1组成的数字序列。在8位图像系统中,单通道像素值范围为0-255,其中0表示纯黑,255表示纯白。
数字图像的实际应用:
在OpenCV等计算机视觉库中,8位图像是默认处理格式。灰度图像使用单通道存储亮度信息,而彩色图像通过三通道矩阵存储RGB值。这种标准化设计保证了图像处理算法的高效性和兼容性,例如边缘检测、色彩转换等操作均基于像素级数值计算实现。
彩色图像的构成原理:
RGB色彩模型是数字图像处理的基础模型,通过红(Red)、绿(Green)、蓝(Blue)三个颜色通道的混合实现丰富色彩表现。每个通道采用8位存储,数值范围0-255,三通道的组合可生成约1677万种颜色(256×256×256)。例如:
- 纯红色表示为
(255, 0, 0)
- 纯白色对应
(255, 255, 255)
- 纯黑色为
(0, 0, 0)
在使用“画图”软件进行自定义调色时,其数值单位就是像素。如下图所示:
4 图像存储
在OpenCV中,无论是读取还是创建图像,结果都是一个NumPy数组。
-
彩色图像:三维数组
-
灰度图像:二维
图像本质上是像素值的二维或三维矩阵(对于彩色图像)。
-
形状(Shape):图像的尺寸由其高(height)、宽(width)和通道数(channels)决定。可以通过img.shape()属性获取这些信息。
-
对于彩色图像,返回的是一个包含三个值的元组 (h(height),w( width), c(channels))。
-
对于灰度图像,返回的是一个包含两个值的元组 (height, width),因为灰度图像只有一个通道。
-
-
数据类型(dtype):图像中的每个像素值的数据类型决定了可以存储的最大值。例如,8位无符号整数(uint8)允许的范围是从0到255。
-
像素表示:
-
单通道图像(灰度图像):每个像素由一个数值表示,代表该点的亮度。值越低(接近0),颜色越暗;值越高(接近255),颜色越亮。
-
多通道图像(彩色图像): 在OpenCV中,默认情况下,彩色图像是以BGR(蓝-绿-红)顺序存储
-
注意:默认情况下,彩色图像是以BGR(蓝-绿-红)的顺序存储
4.1彩色图像
RGB 像素表示原理:彩色图像中的每个像素通常由红(Red)、绿(Green)、蓝(Blue)三个分量组成,每个分量的取值范围为 0 到 255 的整数。这种表示方法基于三原色叠加原理,能够组合出丰富的颜色。
图像矩阵结构为:RGB 图像通过三个独立的二维矩阵存储颜色信息,矩阵的行列数(M x N)与图像分辨率一致。三个矩阵分别对应像素的红色分量、绿色分量和蓝色分量,共同构成完整的彩色图像数据。
数据类型与存储:RGB 图像通常采用 8 位无符号整型(uint8)存储每个颜色通道,单个像素占用 3 字节存储空间。这种格式兼顾了颜色表现范围和存储效率,是数字图像处理中彩色图像的标准表示形式。
5 基本图像操作
讲一些cv2的方法
5.1 创建窗体
cv2.namedWindow(winname [,窗口属性])
使用cv2.namedWindow() 方法创建一个新的窗口。你可以为这个窗口指定一个名称,并且可以选择窗口的属性(例如,是否可调整大小)。
cv2.namedWindow(winname, flags)
-
winname
- 类型:字符串(str)
- 作用:指定窗口的唯一标识名称。后续操作(如 imshow()、destroyWindow()
)需通过此名称引用窗口。
-
flags(可选)
- 类型:整数(int)
- 作用:控制窗口的属性,默认为 cv2.WINDOW_AUTOSIZE。常用标志如下:
- cv2.WINDOW_NORMAL:窗口大小可手动调整,图像显示会适应窗口尺寸。
- cv2.WINDOW_AUTOSIZE(默认):窗口自动适应图像尺寸,不可手动调整。
- cv2.WINDOW_FREERATIO:图像比例可自由调整,不受窗口约束。
例如:创建一个名为“window”的窗口
import cv2 as cv
cv.namedWindow("window", cv.WINDOW_NORMAL)
5.2 读取图像
cv2.imread(path [,读取方式])
img = cv2.imread(filename, flags)
参数:filename:图像路径
读取方式:彩色·默认、灰色等
import cv2 as cv
img = cv.imread("../images/test.jpg") # 读取图像
print(type(img)) # 验证:输出 <class 'numpy.ndarray'>
./
表示当前目录。
../
表示当前目录的上一级目录(即父目录)。当你需要引用或访问当前目录所在位置的上一层目录中的文件或文件夹时使用 ../
。
5.3 显示图像
cv2.imshow(winname,img)
参数:
winname:显示图像的窗口名,以字符串类型表示
img:要显示的图像
注意:在调用显示图像的API后,要调用cv2.waitKey(0)给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来。
cv.waitKey(0):表示无限期地等待任何键盘按键。这种用法常见于图像显示窗口中,确保图像在窗口中显示直到用户决定关闭它。
cv.waitKey(n):n>0,意味着程序将等待n毫秒。这种方式常用于视频播放或实时摄像头捕获场景,以便控制每一帧停留的时间,同时允许用户通过按键来中断循环或发出命令
cv2.destroyAllWindows([winname])
cv2.destroyAllWindows():会在当前程序执行到该语句时立即销毁打开的窗口,并释放与这些窗口相关的资源。
winname:窗口名,关闭指定名称的窗口。可省略,销毁所有已打开的窗口。
cv2.imshow("Demo", img)
cv2.waitKey(0) # 0表示一直存在,等待用户关闭
cv2.destroyAllWindows()
5.4 保存图像
cv2.imwrite(path,img)
参数:
path:图片保存的路径和图片名
img:要保存的图像
cv2.imwrite("pig.jpg", img) # 支持jpg/png等格式
5.5 创建黑白图像
因为我们在numpy中学过如何创建纯0的数组,所以我们使用使用np.zeros()创建全黑图像,再修改像素值成为全白图像。再接上4.1的内容,我们可以创建一个彩色图像,因为像素值是在(0,255)中表示,我们可以用前面学过的random来创建随机值,我们就能得到一个随机的彩色图像
import numpy as np
import cv2 as cv# 创建全0数组 表示黑色图像
height = 512
width = 512
c = 3
black = np.zeros((height, width, c), dtype = np.uint8)
cv.imshow("black", black)# 使用np.full()创建全是1的白色图像
white = np.full((height, width, c), 255, dtype = np.uint8)
cv.imshow("white", white)# 索引修改像素值 表示白色图像 这三种方法都可以使用,结果都相同
black[:, :, :] = 255
# black[:, :] = 255 [b, g, r] = [255, 255, 255]
# black[:] = 255
cv.imshow("bb", black)# 创建随机像素值图像
random = np.random.randint(0, 256, (height, width, c), dtype = np.uint8)
cv.imshow("random", random)cv.waitKey(0)
cv.destroyAllWindows()
展示一下随机彩色图像:
5.6 图像切片(图片剪裁)
在Opencv中,图像切片用于从图像中提取一个子区域(矩形区域)。
假设你有一个图像img,它的类型是numpy.ndarray。的含义如下:
x:子区域左上角的x坐标
y:子区域左上角的y坐标
w:子区域的宽度
h:子区域的高度
切片操作:img[y:y+h,x:x+w]提取的是从(x,y)开始,高度为h,宽度为w的矩形区域
示例读取一张名为game的png图像,然后裁剪的左上顶点为(26,162)右下顶点为(48,162),将裁剪的值返回human,然后打印这个值:
import cv2 as cv# 读取图像
human = cv.imread('../images/game.png')# 切片 arr[h1:h2, w1:w2] h2 = h1 + h w2 = w1 + w 26,162 48,182 w,h
human1 = human[162:182, 26:48]
cv.imshow('human', human1)cv.waitKey(0)
cv.destroyAllWindows()
注意:
边界检查:确保(y,x)和(y+h,x+w)都在图像的边界内,否则会出现索引越界错误
数据类型:img通常是numpy.ndarray类型,切片操作返回的也是numpy.ndarray类型。
5.7 图像大小调整
cv2.resize是Opencv库中用于调整图像大小的函数,在图像处理中很常用,特别是在要对图像进行缩放以适应不同需求时。
cv2.resize(img,dsize)
img:输入图像,通常是二维或三位NumPy数组。
dsize:输出图像的尺寸,是一个二元组(w,h)
import cv2 as cv# 读取图像
pig = cv.imread("../images/pig.png")
print(pig.shape)
cv.imshow("pig", pig)# 调整图像大小
pig2 = cv.resize(pig, (1080, 480))
cv.imshow("pig2", pig2)
print(pig2.shape)# 等比例调整图像大小
pig3 = cv.resize(pig, (0, 0), fx=0.5, fy=0.5)
cv.imshow("pig3", pig3)
print(pig3.shape)cv.waitKey(0)
cv.destroyAllWindows()
6 图像绘制
6.1 绘制直线
cv2.line(img,sart,end,color,thickness)
参数
img:要绘制直线的图像
start、end:直线的起点和终点
color:直线的颜色(对于彩色图像,使用 BGR 格式指定颜色)
thickness:线条宽度
示例在6.3
6.2 绘制圆形
cv2.circle(img,centerpoint,r,color,thickness)
参数:
img:要绘制圆形的图片
centerpoint、r:圆心和半径
color:线条颜色
tnickness:线条宽度,为-1时生成闭合图案并填充颜色
示例在6.3
6.3 绘制矩形
cv2.rectangle(img,leftupper,rightdown,color,thickness)
参数:
img:要绘制矩形的图像
leftupper、rightdown:矩形的左上角和右下角坐标
color:线条的颜色
thickness:线条的宽度
import cv2 as cvcat = cv.imread("../images/1.jpg")
# 绘制直线 cv.line(img, sart, end, color, thickness) (w, h)
cv.line(cat, (80, 110), (237, 110), (115, 155, 255), 10)# 绘制矩形 cv.rectangle(img, start, end, color, thickness)
cv.rectangle(cat, (80, 90), (237, 336), (255, 100, 255), 10)# 绘制圆形 cv.circle(img, center, radius, color, thickness)
# LINE_AA 反走样技术 抗锯齿 平滑 默认使用LINE_8
cv.circle(cat, (200, 200), 30, (255, 255, 0), 5, cv.LINE_AA)cv.imshow("cat", cat)
cv.waitKey(0)
cv.destroyAllWindows()
⭐⭐⭐插播一个知识点
cv.LINE_8 (默认使用LINE_8)
- 8连通连接:使用8连通方式连接线条的像素点。
- 特点:线条在绘制时可能显得更粗,因为允许对角连接,像素点之间的连接更灵活。
- 适用场景:适用于需要快速绘制且对锯齿不敏感的场景。
cv.LINE_4
- 4连通连接:使用4连通方式连接线条的像素点。
- 特点:仅允许水平和垂直方向的连接,对角方向的像素不会直接连接,线条可能显得更细且锯齿更明显。
- 适用场景:适用于需要更细线条或对绘制速度要求较高的场景。
cv.LINE_AA
- 抗锯齿:使用抗锯齿技术绘制线条。
- 特点:线条边缘更平滑,减少了锯齿现象,但绘制速度较慢。
- 适用场景:适用于需要高质量图像输出的场景,如生成可视化图表或打印图像。
6.4 绘制文本(向图片中添加文字)
cv2.putText(img,text,station,font,Fontscale,color,thickness,cv2.LINE_AA)
参数:
img:要添加文字的图像
text:要写入的文本数据
station:文本的放置位置
font:字体样式
Fontscale:字体大小
thickness:字体线条宽度
cv2.LINE_AA:使用反走样技术绘制文本边框
上面6.3也介绍过LINE_AA,反走样是一种提高图形质量的技术,通过混合颜色和像素边缘来减少锯齿状效果,使文本看起来更加平滑、清晰。
6.5 读取视频
cap = cv2.VideoCapture(path)
path:视频流资源路径设置为0,代表从默认摄像头捕获视频流
ret,frame = cap.read()
返回值cap调用read()方法得到一个布尔值和一帧图像,布尔值表示是否成功读取到帧,如果为False,可能是因为视频结束或读取失败,如果为True,frame则是当前帧的图像数据。
import cv2 as cv
# 创建一个VideoCapture对象 cap = cv.VideoCapture(path)
# 读取视频文件
cap = cv.VideoCapture("../images/videocap.mp4")
# 从默认摄像头获取实时视频流
cap = cv.VideoCapture(0)
# 循环读取每一帧
while True:# 调用read()方法,读取每一帧图像ret, img = cap.read()# 判断是否读取成功if not ret:breakcv.imshow("cap", img)# 等待40ms,判断是否有案件发生if cv.waitKey(30)&0xff == ord("q"):print("按键退出!")breakcap.release()
cv.waitKey(0)
cv.destroyAllWindows()
总结
这篇是OpenCV的开始,前面的知识还在简单,先把基础打好,后面才会学起来才会比较容易,熟悉图像的操作处理,把最基础的知识先掌握好,以下三个是可能出现的问题
1. imread() 返回None怎么办?
检查文件路径是否存在特殊字符
使用绝对路径:cv2.imread(r"D:\images\test.jpg")
2. 窗口无法关闭?
确认代码中有 cv2.waitKey() 和 cv2.destroyAllWindows()
3. 视频捕获黑屏?
检查摄像头权限,查看电脑外部的摄像头是否开启,笔记本电脑上摄像头有外部锁,看是否已经打开
也可以尝试降低分辨率:cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)