文章目录
前言
今天我们将要进入opencv的学习,Python中的opencv利用了numpy的一些框架,所以我们学习opencv之前还要具备numpy的相关知识。
一、opencv基础知识
1.opencv相关概念
1.1背景
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和图像处理库,由 Intel 发起开发,现由 OpenCV.org 维护。它支持多种编程语言,包括 C++、Python 和 Java,并且能在多个平台(Windows、Linux、macOS、Android 等)运行。
在 Python 中,我们使用 opencv-python 模块进行开发,拥有强大的图像处理与视觉识别能力。
1.2特点
功能强大:
算法覆盖全面,从基础图像处理到高级机器学习。
性能优越:
使用 C++ 编写并具 GPU 加速,适合实时处理
社区活跃:
由基金会维护,文档齐全,社区支持强,样例丰富。
1.3主要功能与应用
图像处理:
滤波、边缘检测、形态转换、角点特征提取(如 Harris、SIFT、ORB)
物体识别与检测:
面部检测(Haar 级联、DNN)、行人检测、目标跟踪
机器学习集成:
图像分类、聚类、对象识别与行为分析等。
摄像头与视频处理:
实时视频流的处理、运动检测、3D 重建、拼接图像、立体视觉等
深度学习支持:
支持加载 ONNX、TensorFlow、Caffe 等格式的网络进行目标检测、分类等
1.4.opencv-python
OpenCV-Python
是原始OpenCV C++
实现的Python包装器。它结合了OpenCV C++ API
的高性能与 Python 语言的易用性和简洁性。通过 OpenCV-Python,开发者可以轻松地进行图像处理、计算机视觉任务以及机器学习应用。
与C / C++
等语言相比,Python
速度较慢。Python可以使用C / C++扩展,这使我们可以在C / C++中编写计算密集型代码,并创建可用作Python模块的Python包装器。
两个好处: 首先,代码与原始C / C++代码一样快(因为它是在后台工作的实际C++代码),其次,在Python中编写代码比使用C / C++更容易。
OpenCV-Python
使用Numpy
,这是一个高度优化的数据库操作库。所有OpenCV数组结构都转换为Numpy数组。这也使得其与使用Numpy的其他库(如SciPy
和Matplotlib
)集成更容易。
安装opencv-python
在终端里面,可以用pip命令安装opencv-python
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
2.计算机中的图像概念
2.1图像表示
像素
是图像的基本单元
,每个像素存储着图像的颜色
、亮度
和其他特征
。一系列像素组合到一起就形成了完整的图像,在计算机中,图像以像素的形式存在并采用二进制
格式进行存储。根据图像的颜色不同,每个像素可以用不同的二进制数表示。
计算机采用0/1编码的系统,数字图像也是利用0/1来记录信息,我们平常接触的图像都是8位数
图像。opencv中常用的是8位图像,大多数彩色和灰度图像使用8位表示每个通道的像素值,范围从0到255
,其中0代表最黑,255表示最白
。
日常生活中常见的图像是RGB三原色图
。RGB图上的每个点都是由红(R)、绿(G)、蓝(B)
三个颜色按照一定比例混合而成的,几乎所有颜色都可以通过这三种颜色按照不同比例调配而成。在计算机中,RGB三种颜色被称为RGB三通道
,每个通道的取值都是0-255,根据这三个通道存储的像素值,来对应不同的颜色。
2.2图像存储
在OpenCV中,无论是读取还是创建图像,结果都是一个NumPy数组。
彩色图像:三维数组
灰度图像:二维数组
图像本质上是像素值的二维或三维矩阵(对于彩色图像)。
- 形状(Shape):
- 图像的尺寸由其高(height)、宽(width)和通道数(channels)决定。可以通过
img.shape
属性获取这些信息。 - 对于
彩色
图像(如RGB),返回的是一个包含三个值
的元组(height, width, channels)
。 - 对于
灰度
图像,返回的是一个包含两个值
的元组(height, width)
,因为灰度图像只有一个通道。
- 图像的尺寸由其高(height)、宽(width)和通道数(channels)决定。可以通过
- 数据类型(dtype):
- 图像中的每个像素值的数据类型决定了可以存储的最大值。例如,8位无符号整数(
np.uint8
)允许的范围是从0到255。
- 图像中的每个像素值的数据类型决定了可以存储的最大值。例如,8位无符号整数(
- 像素表示
- 单通道图像(灰度图像):每个像素由一个数值表示,代表该点的亮度。值越低(接近0),颜色越暗;值越高(接近255),颜色越亮。
- 多通道图像(彩色图像):
在OpenCV中,默认情况下,彩色图像是以BGR(蓝-绿-红)顺序存储
彩色图像
每个像素通常是由红(R)、绿(G)、蓝(B)三个分量来表示的,分量介于(0,255)。RGB图像每一个像素的颜色值(由RGB三原色表示)直接存放在图像矩阵中,由于每一像素的颜色需由R、G、B三个分量来表示,M、N分别表示图像的行列数,三个M x N的二维矩阵分别表示各个像素的R、G、B三个颜色分量。RGB图像的数据类型一般为8位无符号整形,通常用于表示和存放彩色图像。
示例
生成一个512*512大小的彩色图片 每一个像素点随机颜色
import cv2 as cv
import numpy as np
if __name__ == '__main__':
# 生成随机彩色图
dst = np.random.randint(0,256,(512, 512, 3), dtype=np.uint8)
cv.imshow('dst', dst)
# 显示
cv.waitKey(0)
cv.destroyAllWindows()
二、opencv基础操作
1.图像的读取
基本格式:
cv2.imread(path [,读取方式])
参数说明:
filename:图像路径
./
表示当前目录。../
表示当前目录的上一级目录(即父目录)。当你需要引用或访问当前目录所在位置的上一层目录中的文件或文件夹时使用../
读取方式:彩色·默认、灰色等
示例
import cv2 as cv
if __name__ == '__main__':
# 读取图像 cv.imread(path, cv.IMREAD_COLOR) 默认读为BGR彩色图像
cat = cv.imread('../images/1.jpg')
print(cat.dtype) # np.uint8 无符号8位整数
print(cat.shape) # (h, w, c)
2.图像的显示
基本格式:
cv2.show('winname',img)
参数说明:
winname:显示图像的窗口名,以字符串类型表示
img:要显示的图像
cv.waitKey(0)
:表示无限期地等待任何键盘按键。这种用法常见于图像显示窗口中,确保图像在窗口中显示直到用户决定关闭它。cv.waitKey(n)
:n>0,意味着程序将等待n毫秒。这种方式常用于视频播放或实时摄像头捕获场景,以便控制每一帧停留的时间,同时允许用户通过按键来中断循环或发出命令。释放内存
cv2.destroyAllWindows([winname]) # 释放内存
cv2.destroyAllWindows()
:会在当前程序执行到该语句时立即销毁打开的窗口,并释放与这些窗口相关的资源。winname
:窗口名,关闭指定名称的窗口。可省略,销毁所有已打开的窗口。
注意: 在调用显示图像的API后,要调用
cv2.waitKey(0)
给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来。
示例
import cv2 as cv
if __name__ == '__main__':
cat = cv.imread('../images/1.jpg')
# 显示图像 cv.imshow(window, img)
cv.imshow('myimg', cat) # 无窗体就会自动创建窗口'myimg'
cv.waitKey(0) # 给图像留下绘制时间,等待n毫秒:n毫秒后关闭窗口,0表示一直等待
# 释放资源
cv.destroyAllWindows()
3.保存图像
基本格式:
cv2.imread(path, img)
参数说明:
- path:图片保存的路径及图片名
- 注意加上图片文件类型后缀(.png / .jpg等)
- img:要保存的图像
import cv2 as cv
if __name__ == '__main__':
cat = cv.imread('../images/1.jpg')
cv.write('./cat.jpg',cat)
4.创建黑白图及随机像素彩图
使用numpy
中的np.zeros()
创建黑色图像
使用numpy
中的np.full()
创建白色图像
使用numpy
中的np.random.randint()
创建随机彩图
示例
import numpy as np
import cv2 as cv
if __name__ == '__main__':
# 创建黑色图像
height = 360
width = 540
c = 3
black = np.zeros((height, width, c))
cv.imshow('black', black)
# 使用np.full()创建白色图像
white = np.full((height, width, c), fill_value=255, dtype=np.uint8)
cv.imshow('white', white)
'''
或者black[:] = 255;
或者black[:,:] = 255;
或者black[:,:,:] = 255
后两种运用了numpy中的广播机制
'''
# 生成随机彩色图
dst = np.random.randint(0,256,(height, width, c), dtype=np.uint8)
cv.imshow('dst', dst)
# 显示
cv.waitKey(0)
cv.destroyAllWindows()
5. 图像切片(图片剪裁)
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
if __name__ == '__main__':
# 读取图像
cat = cv.imread('../images/1.jpg')
print(cat.shape)
# 切片w,h(289,231)(368,297) 数组中是 h,w
eye = cat[231:298, 289:369]
eye = cv.resize(eye, (500, 500))
cv.imshow('eye', eye)
cv.waitKey(0)
cv.destroyAllWindows()
6.图像大小调整
cv2.resize
是Opencv库中用于调整图像大小的函数,在图像处理中很常用,特别是在要对图像进行缩放以适应不同需求时。
基本格式:
cv2.resize(img,dsize)
参数说明:
- img:输入图像,通常是二维或三位NumPy数组。
- dsize:输出图像的尺寸,是一个二元组
(w,h)
,
示例
import cv2 as cv
if __name__ == '__main__':
# 读取图像
pig = cv.imread('../images/pig.png')
print(pig.shape) # (650, 1080, 3)
# 调整图像大小
pig2 = cv.resize(pig, (500, 500))
cv.imshow('pig2', pig2)
cv.waitKey(0)
cv.destroyAllWindows()
7.图形绘制
7.1绘制直线
基本格式:
cv2.line(img,sart,end,color,thickness)
参数说明:
- img:要绘制直线的图像
- start、end:直线的起点和终点
- color:直线的颜色(对于彩色图像,使用 BGR 格式指定颜色)
- thickness:线条宽度
7.2绘制矩形
基本格式:
cv2.rectangle(img,leftupper,rightdown,color,thickness)
参数说明:
- img:要绘制矩形的图像
- leftupper、rightdown:矩形的左上角和右下角坐标
- color:线条的颜色
- thickness:线条的宽度,-1时生成闭合图案并填充颜色
7.3绘制圆形
基本格式:
cv2.circle(img,centerpoint,r,color,thickness)
参数说明:
- img:要绘制圆形的图片
- centerpoint、r:圆心和半径
- color:线条颜色
- tnickness:线条宽度,为-1时生成闭合图案并填充颜色
- lineType=cv2.LINE_AA:使用反走样技术绘制边框(默认cv2.LINE_8)
7.4综合示例
import cv2 as cv
if __name__ == '__main__':
cat = cv.imread('../images/1.jpg')
# 绘制直线cv2.line(img,起始坐标,终止坐标,color,thickness,lineType'平滑度-抗锯齿')
cv.line(cat, (50,40), (300, 40),color=(0,255,255),thickness=3)
# 绘制矩形cv2.rectangle(img,左上坐标,右下坐标,color,thickness,lineType'平滑度-抗锯齿')
cv.rectangle(cat,(78,106),(280, 306),color = (100,100,100), thickness=2)
# 绘制圆形cv2.circle(img,圆心坐标,半径,color,thickness,lineType'平滑度-抗锯齿')
cv.circle(cat,(325,269),30,color = (200,100,100), thickness=3,lineType=cv.LINE_AA)
# 图形显示
cv.imshow('cat', cat)
cv.waitKey(0)
cv.destroyAllWindows()
8.视频读取
基本格式:
cap = cv2.VideoCapture(path)
ret,frame = cap.read()
参数说明:
- path:视频流资源路径,如果设置为0,代表从默认摄像头捕获视频流
- 返回值cap调用read()方法得到一个布尔值和一帧图像,布尔值表示是否成功读取到帧,如果为False,可能是因为视频结束或读取失败,如果为True,frame则是当前帧的图像数据。
示例
import cv2 as cv
if __name__ == '__main__':
# 创建一个VideoCapture对象
cap = cv.VideoCapture(0)
# 循环读取每一帧
while True:
# 调用read()方法读取每一帧
ret, img = cap.read()
# 判断是否读取成功
if not ret:
print('播放完成')
break
cv.imshow('dst', img)
# 捕获按键,判断是否中断
if cv.waitKey(40)&0xFF == ord('q'):# 获取返回值的低8位
print("按键退出")
break
# 释放
cap.release()
cv.destroyAllWindows()
总结
今天算是opencv的入门,相较于之前的python基础来说要轻松一点,就是要注意的细节比较多,稍微要了解的就是视频读取时’捕获按键,判断是否中断’这里的原理,了解清楚之后就没什么太难的东西了。
让我们下期再见!