Day9: OpenCV学习(一)—— 图像基础

系列文章目录

上一篇:Day8:Python工程化 —— 模块、包


文章目录

  • 系列文章目录
  • 前言
  • 一、安装和导入
  • 1. 安装
  • 二、图像认识
    • 1. 图像
    • 2. 图像分类
  • 三、基础图像操作
    • 1. 图像读取
    • 2. 图像显示
    • 3. 图像裁剪
    • 4. 图形尺寸修改
    • 5. 图像保存
    • 6. 图像绘制
    • 7. 视频捕获即显示
  • 总结


前言

OpenCV(Open Source Computer Vision Library) 是一个开源的计算机视觉和机器学习软件库。由一系列 C++ 类和函数构成,用于图像处理、计算机视觉领域的算法实现。其有以下优势:

  • 开源免费: 完全开源,可以自由使用,降低开发成本和技术门槛。且社区活跃,问题易于找到解决方案
  • 高性能: 底层使用 C/C++ 编写,执行速度快
  • 跨平台: 支持 Windows / Linux / macOS / Android / iOS,方便部署
  • 跨语言: 编程语言支持多样,如C++、Python(最流行)、Java、MATLAB、Go、Rust(部分)

从本篇文章开始,我们将开始OpenCV-Python库的学习。


一、安装和导入

1. 安装

不推荐在(base)环境中安装,而应该在一个创建好的虚拟环境进行安装,以防止在一个环境中安装混乱的各种包库,引发版本冲突。下方是通过清华源的镜像进行安装的。

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python

可以通过在python代码中(需要在装有虚拟环境的解释器下)执行如下代码检测是否安装成功

import cv2 as cv
print(cv.__version__)

二、图像认识

1. 图像

  • 图像是信息在空间中的二维分布,是像素的矩阵
  • 每个像素(Pixel)是一个最小的图像单位,存储了颜色信息
  • 图像分辨率是宽度(width) × 高度(height)

2. 图像分类

  1. 灰度图像(Grayscale): 单通道,用二维数组表示(height, width)
  2. 彩色图像(RGB): 三通道,用三维数组表示(height, width,channel),其中chanel为3
  3. RGBA: :四通道,用三维数组表示(height, width,channel),其中channel为4

三、基础图像操作

在使用OpenCV进行图像操作需要在Python模块中先导入cv2

import cv2 as cv	# 下方都用cv这个别名进行方法调用

1. 图像读取

cv.imread(filename, flags)

其中参数filename是要读取的图片的路径,可以是绝对路径也可以是相对路径(如果是项目的话建议使用相对路径),参数flags决定读取的方式,可以使用整形字面量,也可以使用cv2中定义的常量,具体对应关系和作用如下:

常量 数值 作用说明
cv2.IMREAD_COLOR (默认) 1 彩色图方式加载图像(默认值),忽略 alpha 通道。返回 BGR 格式图像。
cv2.IMREAD_GRAYSCALE 0 灰度图方式加载图像,返回二维数组(单通道)。
cv2.IMREAD_UNCHANGED -1 原样读取图像,保留 alpha 通道(如 PNG 的透明背景),返回 BGRA。

该函数返回的是所读取图像的Numpy数组(ndarray)表示形式,具体形式跟flags有关,若读取失败则返回None

2. 图像显示

cv.imshow(winname, mat)

其中参数winname代表用于显示图像的窗体的名字,mat传入的是要显示的图像的ndarray形式。可以结合上面的imread()使用,因为其返回值就是图像的ndarray表示形式。也可以自己通过Numpy的操作自己创建符合图像

要保证图像能够长时间显示并实现交互,还需要进行等待(如果不等待,代码将不断向下执行,执行完毕后将自动关闭所有窗体):

cv.waitKey(delay)

该函数将在接收到键盘输入后返回该按键字符的ASCII码值,delay为等待时间,单位是毫秒,当delay0(或者小于0)时,将进行无线等待,直到键盘输入值。

虽然在代码执行完毕后会自动关闭所有窗体,但是还是应该显示地关闭窗体,增强代码的可控性和健壮性:

cv.destroyAllWindows()

当然,也可以通过窗体名指定关闭某个窗体:

cv2.destroyWindow(winname)

3. 图像裁剪

需要用到Numpy数组的 切片 操作(不同维度分别切片,用逗号隔开)
示例:

# 读取一张图像
img1 = cv.imread('img1.jpg')	# 默认读取为彩色图
part = cv[200:400, 300:400, :]	# 等效于part = cv[200:400, 300:400]

imread读取的默认是三通道彩色图像(BGR),其数组形状为(height, width, channel),要进行裁剪,则要在数组的 (也就是图像的 )和 (也就是图像的 )上进行切片,通道 这一维不变。上述示例所裁剪的部分是第200行 ~ 399行,第300列 ~ 399列部分的图像

4. 图形尺寸修改

dst = cv2.resize(src, dsize)

src为原图像(ndarray形式),dsize是一个序列(优先选择tuple),顺序是(width, height),注意与’ndarray‘中的(height, width, channel)的顺序区分。该函数不会对原图像进行修改,而是返回一个新的图像(ndarray形式)

5. 图像保存

在一系列的图像处理操作后,我们可能要将得到的结果(往往是ndarray形式)保存为计算机中图片的形式,此时就要进行图像的 保存

cv.imwrite(filename, img)

其中filename是要保存图片到那个路径,写路径时还要把该图片文件的后缀也写上(.jpg.png.bmp等),img则是要保存的图像(ndarray形式)

6. 图像绘制

  1. 绘制直线
cv.line(img, pt1, pt2, color, thickness, lineType)
  1. 绘制矩形
cv.rectangle(img, left_upper, right_lower, color, thickness, lineType)
  1. 绘制圆形
cv.circle(img, center, radius, color, thickness, lineType)

img表示作为背景的图像(画板)pt1, pt2代表绘制直线时的两个端点。left_upper, right_lower代表绘制矩形时的左上角和右下角坐标(坐标系的原点在左上角),radius代表绘制圆形时的半径,color代表绘制所用颜色,其形式为一个序列类型(通常是tuple),thickness代表绘制线条的粗细,为整数,如果-1则表示将内部全部填充(也就是实心),但是直线的thickness必须大于0。lineType表示绘制所用线条的类型。

常见的lineType取值如下:

常量 数值 说明
cv2.LINE_8 8 8-connected line(默认),标准抗锯齿效果,速度快
cv2.LINE_4 4 4-connected line,线条连接更紧密,较少使用
cv2.LINE_AAcv2.CV_AA 16 Anti-aliased line,抗锯齿线条,线条边缘更平滑,绘制较慢

7. 视频捕获即显示

  1. 先要创建一个捕获器实例
cap = cv.VideoCapture(filename)

filename是要进行捕获的视频的路径,当filename=0时,将从默认的摄像头捕获视频流

  1. 循环获取并显示视频的帧
# 无限循环
While True:
	# 读取视频流的帧
	ret, frame = cap.read()		# ret 是一个布尔值,表示该帧是否读取成功,可以用作视频播放结束自动退出循环
	# 视频播放完后,ret值为False,跳出循环
	if not ret:
		break
	# 读取成功后显示该帧
	cv.imshow('frame', frame)
	# 通过键盘交互手动退出视频帧的循环获取(cv.waitKey()返回一个32为整数, 与0xFF相与是为了取其低8位(得到ASCII码部分),以保证跨平台安全,即可判断其是否是'q')
	if cv.waitKey(20) & 0xFF == ord('q'):
		break
		
  1. 结束后释放该捕获器实例并显式关闭所有窗体
cap.release()	# cap是之前所创建的VideoCapture实例
cv.destroyAllWindows()

总结

经过本章的学习,我们对OpenCV有了初步的了解,并且对计算机中的图像有了一定的认识,在此基础上,还认识到OpenCV-Python中的图像的本质(Numpy数组),还能够通过OpenCV-Python库中的一些函数对图像进行一些简单的操作(如读取显示保存裁剪调整尺寸绘制)、捕获视频。

你可能感兴趣的:(Day9: OpenCV学习(一)—— 图像基础)