一、介绍
OpenCV(开放源代码计算机视觉库)是一个开源的计算机视觉和机器学习软件库。由一系列 C++ 类和函数构成,用于图像处理、计算机视觉领域的算法实现
-
开源免费:完全开源,可以自由使用,降低开发成本和技术门槛。
-
多语言支持:除C++原生接口外,还支持Java、Python等编程语言。
-
跨平台:支持多种操作系统,Windows、Linux、ios、Android等,方便开发和部署。
-
丰富API:完善的传统计算机视觉算法,涵盖主流的机器学习算法,同时添加了对深度学习的支持。
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)集成更容易。
二、环境安装
pip install opencv-python
三、图像表示
像素是图像的基本单元,每个像素存储着图像的颜色、亮度和其他特征。一系列像素组合到一起就形成了完整的图像,在计算机中,图像以像素的形式存在并采用二进制格式进行存储。根据图像的颜色不同,每个像素可以用不同的二进制数表示。
计算机采用0/1编码的系统,数字图像也是利用0/1来记录信息,我们平常接触的图像都是8位数图像。opencv中常用的是8位图像,大多数彩色和灰度图像使用8位表示每个通道的像素值,范围从0到255,其中0,代表最黑,1,表示最白。
日常生活中常见的图像是RGB三原色图。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位无符号整形,通常用于表示和存放彩色图像。
五、基本图像操作
5.1创建窗体
cv2.namedWindow(winname [,窗口属性])
-
窗口属性:窗口大小是否可调整
-
cv2.WINDOW_AUTOSIZE
:默认,窗口会根据加载的图像自动调整到合适的大小,并且用户不能拖动窗口边缘来调整窗口大小。 -
cv2.WINDOW_NORMAL
:窗口大小是可调整的,用户可以通过鼠标拖动窗口边缘来自由改变窗口大小。
-
# 创建窗体:cv2.namedWindow(窗体名, 属性) cv.namedWindow("mywindow",cv.WINDOW_AUTOSIZE)#默认窗口大小不可调整 cv.namedWindow("window1",cv.WINDOW_NORMAL)#窗口大小可调整
5.2读取图像
cv2.imread(path [,读取方式])
- 读取方式:彩色·默认、灰色等
./
表示当前目录。
../
表示当前目录的上一级目录(即父目录)。当你需要引用或访问当前目录所在位置的上一层目录中的文件或文件夹时使用 ../
。
# 读取图像:cv2.imread(路径.读取方式) img=cv.imread("./images/cat1.png",cv.IMREAD_COLOR) img2=cv.imread("./images/cat1.png",cv.IMREAD_GRAYSCALE)
5.3显示图像
cv2.imshow(winname,要显示的图像)
注意:在调用显示图像的API后,要调用cv2.waitKey(0)给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来。
-
cv.waitKey(0):表示无限期地等待任何键盘按键。这种用法常见于图像显示窗口中,确保图像在窗口中显示直到用户决定关闭它。
-
cv.waitKey(n):n>0,意味着程序将等待n毫秒。这种方式常用于视频播放或实时摄像头捕获场景,以便控制每一帧停留的时间,同时允许用户通过按键来中断循环或发出命令。
cv2.destroyAllWindows([winname])
-
cv2.destroyAllWindows()
:会在当前程序执行到该语句时立即销毁打开的窗口,并释放与这些窗口相关的资源。 -
winname
:窗口名,关闭指定名称的窗口。可省略,销毁所有已打开的窗口。
# 显示图像:cv2.imshow(窗体名, 要显示的图像)cv.imshow("img",img)#显示图像前不创建,会自动生成窗体名 cv.imshow("img2",img2) cv.waitKey(0) cv.destroyAllWindows()
5.4保存图像
cv2.imwrite(path,要保存的图像)
# 保存图像:cv2.imwrite(路径, 要保存的图像) cv.imwrite("./images/gray.png",img2)
5.5创建黑白图像
使用np.zeros()
创建全黑图像,再修改像素值成为全白图像。
numpy.zeros((height,width,channels),dtype=np. uint8)
# 定义图像宽高和通道数 h=480 w=520 c=3 # 使用np.zeros创建一个全零矩阵,黑色图像,uint8 black_img=np.zeros((h,w,c),dtype=np.uint8) # 显示图像 cv.imshow("black",black_img)
# 修改像素值为255,创建全白图像 black_img[:,:,:]=255 cv.imshow("white",black_img) # 生成随机像素值的图像 black_img[:,:,:]=np.random.randint(0,256,(h,w,c)) cv.imshow("random",black_img) cv.waitKey(0) cv.destroyAllWindows()
5.6图像切片(图片剪裁)
-
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
的矩形区域
-
# 读取图像 img=cv.imread("images/cat1.png") # 定义剪切出的图像起点和宽高 print(img.shape) x=100 y=200 # 宽高 w=300 h=300 img2=img[y:y+h,x:x+w] cv.imshow("img",img) cv.imshow("img2",img2) cv.waitKey(0) cv.destroyAllWindows()
5.7图像大小调整
cv2.resize(图像,(宽,高))
-
img:输入图像,通常是二维或三位NumPy数组。
-
dsize:输出图像的尺寸,是一个二元组
(w,h)
,
cat=cv.imread("images/cat1.png") print(cat.shape) # 调整图像大小:cv2.resize(图像, (宽, 高)) new_img=cv.resize(cat,(400,400)) cv.imwrite("images/cat2.png",new_img) cv.imshow("cat",cat) cv.imshow("new",new_img) cv.waitKey(0) cv.destroyAllWindows()
六、图像绘制
6.1绘制直线
cv2.line(图像,起点,终点,颜色,线条粗细)
cv.line(cat,(200,100),(400,300),(255,0,0),2) cv.imshow("cat",cat)
6.2绘制圆形
cv2.circle(图像,圆心坐标,半径,颜色,线条粗细(-1则填充为闭合图像))
cv.circle(cat,(300,300),300,(0,255,0),2,cv.LINE_AA) # cv.LINE_AA:反走样技术,抗锯齿,使边缘更加平滑,默认是cv2.LINE_8 cv.imshow("cat",cat)
6.3绘制矩形
cv2.rectangle(图像,左上坐标,右下坐标,颜色,线条粗细)
cv.rectangle(cat,(100,100),(300,300),(0,0,255),2) cv.imshow("cat",cat)
6.4绘制文本
向图像里添加文字
cv2.putText(图像,文字,位置,字体,字体大小,字体颜色,字体粗细,cv2.LINE_AA)
-
cv2.LINE_AA:使用反走样技术绘制文本边框
-
反走样是一种提高图形质量的技术,通过混合颜色和像素边缘来减少锯齿状效果,使文本看起来更加平滑、清晰。
-
cv.putText(cat,"hello yuyu!",(300,300),cv.FONT_ITALIC,3,(255,0,0),2,cv.LINE_AA) cv.imshow("cat",cat)
6.5读取视频
cap = cv2.VideoCapture(path)
-
path:视频流资源路径设置为0,代表从默认摄像头捕获视频流
-
ret,frame = cap.read()
-
返回值cap调用read()方法得到一个布尔值和一帧图像,布尔值表示是否成功读取到帧,如果为False,可能是因为视频结束或读取失败,如果为True,frame则是当前帧的图像数据。
-
捕获摄像头的实时视频流
# 创建VideoCapture对象 cap=cv.VideoCapture("images/1.mp4")#读取本地视频 cap=cv.VideoCapture(0)#从摄像头读取实时视频 # 循环读取每一帧图像: while True: ret,frame=cap.read() #判断是否读到某一帧,没有读到报错并退出 if not ret: print("错了!") break cv.imshow("video",frame) # 等待40ms判断是否有按键触发,有返回ASCII码,没有返回-1 if cv.waitKey(40)&0xFF==ord("q"): break cap.release() cv.destroyAllWindows()