OpenCV 4.5计算机视觉开发实战:基于Python

OpenCV 4.5计算机视觉开发实战:基于Python
📸 计算机视觉概述

  1. 图像的基本概念
    图像和图形
    图像:由照相机、摄像机、扫描仪等输入设备捕捉实际的画面产生的数字图像,是由像素点阵构成的位图。
    图形:用数学规则产生的或具有一定规则的图案,由外部轮廓线条构成的矢量图。
    灰度与灰度级
    灰度:把白色与黑色之间按对数关系分为若干等级,称为灰度。
    图像的深度:存储每个像素所用的位数,也用于量度图像的色彩分辨率。
    数字图像的特点
    数字图像又称数码图像或数位图像,是二维图像用有限数值像素的表示。
    信息量大
    占用频带宽大
    相关性大
    非客观性
    图像单位与通道
    像素:字图像由许多密集的细小点所组成,这些细点构成一幅图像的基本单元,称为像素。
    通道:表示把图像分解成一个或多个颜色成分,通常可以分为单通道、三通道和四通道。
    图像分辨率与屏幕分辨率
    图像分辨率:每英寸图像内的点数,单位是像素每英寸。
    屏幕分辨率:屏幕每行的像素点数乘以每列的像素点数。
    图像存储
    通常计算机按照RGB方式存储三通道图像格式。
  2. 图像噪声
    图像噪声定义
    图像噪声可以理解为妨碍人的视觉器官或系统传感器对所接受图像源信息进行理解或分析的各种因素。
    图像处理的分类
    图像处理的主要分类包括:
    光学模拟处理
    电学模拟处理
    计算机数字处理
    噪声的来源
    外部噪声:系统外部干扰以电磁波或经电源串进系统内部引起。
    内部噪声:由光和电的基本性质所引起的噪声,包括电器的机械运动、器材材料本身引起的噪声等。
    数字图像处理常用方法
    图像变化、图像增强、图像分割、图像描述、图像分类(识别)、图像重建等。
    图像噪声的滤除
    通过图像平滑可以有效地减少和消除图像中的噪声,以改善图像质量,有利于抽取对象特征进行分析。
  3. 计算机视觉概述
    图像理解
    对于给定的一幅图像,图像理解程序不仅要描述图像本身,还要描述和解释图像所代表的景物,以便对图像代表的内容做出决定。
    计算机视觉的定义
    计算机视觉是使用计算机及相关设备对生物视觉的一种模拟。其主要任务是通过对采集的图片或视频进行处理,以获得相应场景的三维信息。
    图像处理技术
    图像处理技术把输入图像转换成具有所希望特性的另一幅图像,如提高信噪比或突出图像细节。
    计算机视觉的应用
    包括:
    控制过程(如工业机器人)
    导航(如自主汽车)
    事件检测(如视频监控)
    信息组织(如图像数据库)
    造型对象或环境(如医学图像分析)
    人机交互
    自动检测(如制造业)
    模式识别
    模式识别技术根据从图像抽取的统计特性或结构信息,把图像进行分类,如文字识别或指纹识别。
  4. OpenCV概述
    OpenCV简介
    OpenCV(开源计算机视觉库)是一个基于BSD许可(开源)发布的跨平台计算机视觉和机器学习软件库,支持Linux、Windows、Android和Mac OS操作系统。
    OpenCV的特点
    主要倾向于实时视觉应用,支持多种编程语言(如C#、Ch、Ruby、GO)。
    提供丰富的视觉处理算法,部分以C语言编写,便于算法移植。
    实时应用与性能优化
    OpenCV致力于真实世界的实时应用,通过优化C代码提升执行速度。
    购入Intel的IPP高性能多媒体函数库可进一步提高处理速度。
    🐍 Python与OpenCV开发环境搭建
    📥 Python 3.8下载与安装
    Python 是一种面向对象的解释型计算机程序设计语言,遵循 GPL(General Public License) 协议。

在交互模式的提示符 >>> 下直接输入代码后按回车键可以立即得到代码执行结果。
示例:输入 100 + 200,再打印 “hello, world”。
🌐 在线安装与卸载opencv-python
在线安装opencv-python
Python安装完成后,可以继续搭建OpenCV开发环境。
在线安装 指在安装过程中需要连接外网(Internet),边下载边安装。
卸载opencv-python
为了以后升级opencv-python,可以先卸载旧版本,再安装新版的opencv-python。
⚙️ PyCharm 2021.2下载与安装
配置PyCharm开发OpenCV程序
和其他语言类似,Python程序的编写可以使用Windows自带的控制台,但对于较为复杂的程序工程,建议使用专用的Python编译器 PyCharm。
PyCharm的下载与安装
下载PyCharm后,按照提示进行安装。
导入配套源码的方法
将源码所在的目录复制到项目目录中即可。
调试Python程序
在窗口下方的 Debug 视图中,可以直接看到变量的相关信息。
调试手段包括设置断点、单步执行和监视变量。
🔢 测试一下NumPy的数学函数
NumPy 支持大量的维度数组与矩阵运算,并提供了大量的数学函数库。

python
Copy
import cv2 as cv # 导入cv模块
import numpy as np

a = np.array([1.0, 5.55, 123, 0.567, 25.532])
print("np.round(2.6) : ", np.round(2.6))
print(“np.round(a, 1):”, np.round(a, 1))
print("np.round(2.8) : ", np.round(2.8))
print("cvFloor(2.5) : ", np.floor(2.5))
print("cvFloor(2.6) : ", np.floor(2.6))
print("cvCeil(2.5) : ", np.ceil(2.5))
print("cvCeil(2.6) : ", np.ceil(2.6))
常用数学函数
函数名 功能描述
round(a, decimals=0, out=None) 将小数 a 四舍五入到给定的小数位数。
floor(a) 取比小数 a 小的最大的整数,即向下取整。
ceil(a) 取比小数 a 大的最小的整数,即向上取整。
🙏 感谢观看
🖥️ OpenCV基本操作
“OpenCV是一个开源的计算机视觉库,经过多年的发展,针对不同的应用场景,划分了多个模块,每个模块专注于不同的功能。”

📚 目录
序号 主题
01 OpenCV架构
02 图像输入输出模块imgcodecs
03 OpenCV界面编程
04 单窗口显示多图片
05 销毁窗口
06 鼠标事件
07 键盘事件
08 滑动条事件
🔍 01 OpenCV架构
OpenCV已经发展得比较庞大,针对不同的应用划分了不同的模块。
🖼️ 02 图像输入输出模块imgcodecs
读取图像文件
函数声明:
KaTeX can only parse string typed expression
cv.imread(filename[,flags])→retval

参数说明:
filename:图像文件名
flags:读取模式,取值如下:
标志 值 说明
cv.IMREAD_ANYDEPTH 2 若载入的图像深度为16位或32位,就返回对应深度的图像。
cv.IMREAD_COLOR 1 将图像转换为彩色图像(BGR,3通道)。
cv.IMREAD_GRAYSCALE 0 始终将图像转换为灰度图(1通道)。
cv.IMREAD_UNCHANGED -1 不改变地载入原图。
获取图像高度和宽度
在Python中,可以利用numpy库提供的shape函数得到矩阵的行数和列数。
保存图片
函数声明:
KaTeX can only parse string typed expression
imwrite(filename,img[,params])→retval

参数说明:
filename:写入的文件名,必须加上后缀(例如“123.png”)。
🖥️ 03 OpenCV界面编程
OpenCV支持有限的界面编程,主要针对窗口、控件和鼠标事件,比如滑块。
函数声明:
KaTeX can only parse string typed expression
namedWindow(winname[,flags])→None
KaTeX can only parse string typed expression
numpy.hstack(tup)
示例代码:
python
Copy
import cv2 as cv
import numpy as np

def opecv_muti_pic():
img1 = cv.imread(‘1.jpg’)
img2 = cv.imread(‘2.jpg’)
img3 = cv.imread(‘3.jpg’)
imgs = np.hstack([img1, img2, img3])
cv.imshow(“mutil_pic”, imgs)
cv.waitKey(0)

opecv_muti_pic()
🚪 05 销毁窗口
在OpenCV中,销毁窗口时窗口也将自动关闭。
函数声明:
KaTeX can only parse string typed expression
destroyWindow(winname)→None
KaTeX can only parse string typed expression
destroyAllWindows()→None
🖱️ 06 鼠标事件
鼠标事件包括左键单击、双击等。OpenCV通过事件的响应处理鼠标数据。
函数声明:
KaTeX can only parse string typed expression
SetMouseCallback(windowName,onMouse,param=None)→None
事件类型:
事件类型 说明
EVENT_MOUSEMOVE 鼠标移动
EVENT_LBUTTONDOWN 左键点击
EVENT_RBUTTONDOWN 右键点击
EVENT_MBUTTONDOWN 中键点击
EVENT_LBUTTONUP 左键放开
EVENT_RBUTTONUP 右键放开
EVENT_MBUTTONUP 中键放开
EVENT_LBUTTONDBLCLK 左键双击
EVENT_RBUTTONDBLCLK 右键双击
⌨️ 07 键盘事件
键盘事件由waitKey函数实现。
函数声明:
KaTeX can only parse string typed expression
waitKey([delay])→retval

参数说明:
delay:延时的时间,单位是毫秒,默认值为0表示永久等待。
🎚️ 08 滑动条事件
滑动条用于视频播放帧中选择特定帧。
函数声明:
KaTeX can only parse string typed expression
createTrackbar(trackbarName,windowName,value,count,onChange)→None
KaTeX can only parse string typed expression
getTrackbarPos(trackbarName,windowName)→retval
KaTeX can only parse string typed expression
setTrackbarPos(trackbarName,windowName,pos)→None
回调函数类型:
python
Copy
def TrackbarCallback(pos, userdata):
pass
示例代码:
python
Copy
import cv2 as cv
import numpy as np

img = np.zeros((100, 200))
cv.imshow(“windowname”, img)
cv.waitKey(0)
cv.destroyAllWindows()
📊 NumPy概述
NumPy的基本介绍
“NumPy是一个运行速度非常快的数学库,主要用于数组计算,包含一个强大的N维数组对象ndarray、广播功能函数、整合C/C++/Fortran代码的工具和线性代数、傅里叶变换、随机数生成等功能。”

ndarray对象
ndarray:NumPy最重要的特点,是一系列同类型数据的集合,以0下标为开始进行集合中元素的索引。
数组属性
ndarray的组成内容包括:

属性 描述
数据指针 指向数据(内存或内存映射文件中的一块数据)的指针。
数据类型 描述在数组中固定大小值的格子(dtype)。
数组形状 表示数组形状(shape)的元组,表示各维度大小的元组。
跨度元组 整数,指的是为了前进到当前维度下一个元素需要“跨过”的字节数。
NumPy的使用
要使用NumPy包,必须先将其引入,语句为:

python
Copy
from numpy import *
import numpy as np
使用NumPy,开发人员可以执行以下操作:

数组的算术和逻辑运算
傅里叶变换和用于图形操作的例程
与线性代数有关的操作,NumPy拥有线性代数和随机数生成的内置函数
📑 NumPy的数据类型
名称 描述
bool_ 布尔型数据类型(True或者False)
int_ 默认的整数类型(类似于C语言中的long、int32或int64)
intc 与C的int类型一样,一般是int32或int64
intp 用于索引的整数类型(类似于C的ssize_t,一般情况下仍然是int32或int64)
int8 字节(-128~127)
int16 整数(-32768~32767)
int32 整数(-2147483648~2147483647)
int64 整数(-9223372036854775808~9223372036854775807)
uint8 无符号整数(0~255)
uint16 无符号整数(0~65535)
uint32 无符号整数(0~4294967295)
uint64 无符号整数(0~18446744073709551615)
float_ float64类型的简写
float16 半精度浮点数,包括1个符号位、5个指数位、以及10个尾数位
🧮 数组数据类型
数组数据类型概述
在 NumPy 中,数组的数据类型(dtype)定义了数组中元素的类型和大小。以下是一些常见的数据类型:

数据类型 描述
float32 单精度浮点数,包括 1 个符号位、8 个指数位、23 个尾数位
float64 双精度浮点数,包括 1 个符号位、11 个指数位、52 个尾数位
complex64 复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128 复数,表示双 64 位浮点数(实数部分和虚数部分)
uint32 无符号整数,范围为 0 到 4294967295
数组属性
NumPy 数组的属性称为秩(rank),即数组的维度数量。以下是一些重要的数组属性:

属性 描述
ndarray.ndim 秩,即轴的数量或维度的数量
ndarray.shape 数组的维度,对于矩阵,指的是
KaTeX can only parse string typed expression
n 行
KaTeX can only parse string typed expression
m 列
ndarray.size 数组元素的总个数,相当于
KaTeX can only parse string typed expression
n×m 的值
ndarray.dtype ndarray 对象的元素类型
ndarray.itemsize ndarray 对象中每个元素的大小,以字节为单位
ndarray.flags ndarray 对象的内存信息
ndarray.real ndarray 元素的实部
ndarray.imag ndarray 元素的虚部
ndarray.data 包含实际数组元素的缓冲区
数组的创建
NumPy 提供了多种方式来创建数组,以下是一些常用的方法:

numpy.asarray
python
Copy
numpy.asarray(a, dtype=None, order=None)
用途:将输入转换为 ndarray 类型。
numpy.empty
python
Copy
numpy.empty(shape, dtype=float, order=‘C’)
用途:创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组。
numpy.zeros
python
Copy
numpy.zeros(shape, dtype=float, order=‘C’)
用途:创建指定大小的数据,数组元素以 0 填充。
numpy.frombuffer
python
Copy
numpy.frombuffer(buffer, dtype=float, count=-1, offset=0)
用途:从 buffer 输入参数创建 ndarray 对象。
numpy.fromiter
python
Copy
numpy.fromiter(iterable, dtype, count=-1)
用途:从可迭代对象中建立 ndarray 对象,返回一维数组。
数组的切片与索引
ndarray 对象的内容可以通过 索引 或 切片 进行访问。索引指的是通过元素的具体位置来访问,而切片则是通过指定范围来获取多个元素。

🐍 NumPy 数组操作
访问和修改数组
在 NumPy 中,数组的访问和修改可以通过切片操作实现,类似于 Python 中的列表切片。

切片操作
切片对象可以通过内置的 slice 函数来创建,并设置参数 start、stop 和 step。例如:

python
Copy
a = np.arange(10)
s = slice(2, 7, 2) # 从索引2开始到索引7停止,间隔为2
print(a[s]) # 输出结果为 [2 4 6]
此外,也可以使用冒号分隔的切片参数进行切片操作:

python
Copy
b = a[2:7:2] # 从索引2开始到索引7停止,间隔为2
print(b) # 输出结果为 [2 4 6]
创建数组的函数
numpy.arange
用于创建一维数组,生成一个等差数列。原型如下:

python
Copy
numpy.arange(start, stop, step, dtype)
numpy.linspace
用于创建一个等差数列。原型如下:

python
Copy
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
高级索引
整数数组索引
整数数组索引允许使用整数数组作为索引获取目标数组的元素。例如:

python
Copy
x = np.array([[1, 2], [3, 4], [5, 6]])
y = x[[0, 1, 2], [0, 1, 0]] # 获取位置(0,0)、(1,1)和(2,0)的元素
print(y) # 输出结果为 [1 4 5]
布尔索引
布尔索引是通过布尔数组来索引目标数组,获取符合条件的元素。

python
Copy
x = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print(‘我们的数组是:’)
print(x)
print(‘\n大于5的元素是:’)
print(xx>5x > 5x>5) # 输出大于5的元素
迭代数组
NumPy 提供了 nditer 对象,可以灵活访问一个或多个数组的元素。它的基本任务是完成对数组元素的访问。

控制遍历顺序
可以通过显式设置来强制 nditer 对象使用某种顺序:

order=‘F’ 表示列序优先
order=‘C’ 表示行序优先
花式索引
花式索引是利用整数数组进行索引。根据索引数组的值来获取目标数组在某个轴的元素。

数组操作
修改数组形状
可以在不改变数据的条件下修改数组的形状,使用 numpy.reshape 函数。

翻转数组
使用 numpy.transpose 可以对数组进行维度交换。

其他数组操作
滚动轴:numpy.rollaxis(arr, axis, start) 用于向后滚动特定的轴到一个特定位置。
展平数组:numpy.flatten(order=‘C’) 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组。
交换轴:numpy.swapaxes(arr, axis1, axis2) 用于交换数组的两个轴。
数组的迭代
以下为 nditer 迭代器的一些参数描述:

参数 描述
c_index 可以跟踪 C 顺序的索引
f_index 可以跟踪 Fortran 顺序的索引
multi-index 每次迭代可以跟踪一种索引类型
external_loop 给出的值是具有多个值的一维数组,而不是零维数组
📸 图像处理模块学习指南
📜 课程概述
本课程讲解了基于 Python 3.8 的计算机视觉与图像处理,重点介绍了 OpenCV 4.5 的应用。

📋 目录
01 颜色变换 cvtColor
02 画基本图形
03 文字绘制
04 为图像添加边框
05 在图像中查找轮廓
🎨 01 颜色变换 cvtColor
颜色变换功能简介
颜色变换是 imgproc 模块中一个常用的功能。OpenCV 提供的 cvtColor() 函数可以实现颜色空间的转换。

示例代码
python
Copy
import cv2

将图片转换成灰度图

src_image = cv2.imread(“test.jpg”)
gray_image = cv2.cvtColor(src_image, cv2.COLOR_BGR2GRAY)

将图片转换成HSV

hsv_image = cv2.cvtColor(src_image, cv2.COLOR_BGR2HSV)

cv2.imshow(“src_image”, src_image)
cv2.imshow(“gray_image”, gray_image)
cv2.imshow(“hsv_image”, hsv_image)
cv2.waitKey(0)
函数声明
cvtColor(src, code[, dst[, dstCn]]) -> dst

参数说明
src: 输入图像,进行颜色空间变换的原图像。
code: 颜色空间转换代码,指定转换的类型。
dst: 输出图像,大小和深度与 src 相同。
dstCn: 目标图像通道数,默认值为 0。
✏️ 02 画基本图形
基本图形绘制
在 OpenCV 中,可以绘制多种基本图形,例如点、线段、矩形、多边形、圆和椭圆。

函数声明和示例
图形类型 函数名称 函数声明
画点 cv2.circle cv.circle(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img
画线段 cv2.line line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) → None
画矩形 cv2.rectangle cv.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]] ) -> img
画多边形 cv2.polylines polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]]) → None
填充多边形 cv2.fillPoly fillPoly(img, pts, color[, lineType[, shift[, offset]]]) → None
画圆 cv2.circle cv.circle(img, center, radius, color[, thickness[, lineType[, shift]]]) -> img
画椭圆 cv2.ellipse Ellipse(img, center, axes, angle, start_angle, end_angle, color, thickness=1, lineType=8, shift=0) → None
📝 03 文字绘制
文字绘制函数
OpenCV 提供了在图像上绘制文字的函数 putText()。

函数声明
putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) → None

🖼️ 04 为图像添加边框
边框设置函数
使用 copyMakeBorder() 函数为图像设置边界,定义额外的填充(边框)。

函数声明
cv.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]]) -> dst

🔍 05 在图像中查找轮廓
轮廓查找功能
通过 findContours() 函数可以检测物体的轮廓。

示例代码
python
Copy
import cv2

img = cv2.imread(“test2.jpg”)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

检测轮廓

contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 0, 255), 3) # 绘制轮廓

cv2.imshow(“img”, img)
cv2.waitKey(0)
函数声明
cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy

轮廓近似方法
CV_CHAIN_APPROX_NONE: 保存所有轮廓点。
CV_CHAIN_APPROX_SIMPLE: 仅保存拐点信息。
CV_CHAIN_APPROX_TC89_L1 或 CV_CHAIN_APPROX_TC89_KCOS: 使用 teh-Chinl chain 近似算法。
🙏 感谢观看
以上是本次课程的学习内容,涵盖了 OpenCV 中图像处理的基本功能和实现方法。

🖼️ 灰度变换与直方图修正
📚 目录
点运算
灰度变换
直方图修正
01 点运算
点运算的基本概念
点运算是指对图像中的每一个像素点进行计算,使其输出的每一个像素值仅由对应点的值来决定,可以理解为点到点之间的映射。

点运算的目标与分类
改善图像的质量,使图像能够显示更多的细节,提高图像的对比度(对比度拉伸)。
有选择地突出图像感兴趣的特征,或者抑制图像中不需要的特征。
可以有效地改变图像的直方图分布,使像素的分布更为均匀。
点运算的特点和应用
从算法原理上看,点处理指的是仅根据图像中像素的原灰度值按一定的规则来确定新的灰度值。

光度学标定
对比度增强
显示标定
轮廓线
裁剪
02 灰度变换
灰度变换的基本概念
改善图像的质量可以采用灰度变换法,通过扩展输入图像的动态范围达到图像增强的目的。

灰度变换的方法
根据函数性质,灰度变换方法分为:

线性灰度变换
分段线性灰度变换
非线性灰度变换(包括对数函数变换和幂律函数变换(伽马变换))
灰度化
如果每个像素的R、G、B完全相同,也就是
KaTeX can only parse string typed expression
R=G=B=D,那么该图像就是灰度图像,其中
KaTeX can only parse string typed expression
D被称为各个像素的灰度值。

对比度
对比度(contrast)是画面的明亮部分和阴暗部分的灰度比值。一幅图像对比度越高,图像中被照物体的轮廓越分明可见,图像越清晰。

直方图的概念
一幅图像由不同灰度值的像素组成,图像中灰度的分布情况是该图像的一个重要特征。

灰度的线性变换
线性灰度变换是将原图像的灰度动态范围按线性关系式扩展到指定范围或整个动态范围。

分段线性变换
分段线性灰度变换将原图像灰度范围划分为两段或更多段,对感兴趣的目标或灰度区间进行增强,对其他不感兴趣的灰度区间进行抑制。

对数变换和反对数变换
对数变换和反对数变换属于非线性变换,其公式为
KaTeX can only parse string typed expression
s=c×log(1+r)。

直方图均衡化
直方图均衡化是一种常见的增强图像对比度的方法,可以增强局部图像的对比度,在数据较为相似的图像中的作用更加明显。

幂律变换
也称伽马(Gamma)变换或指数变换,是一种常用的灰度非线性变换,主要用于图像的校正、对漂白的图片或者是过黑的图片进行修正。

03 直方图修正
(此部分内容在讲义中未具体提及,待后续讲义补充。)

感谢观看
(此部分内容仅为结束语,未涉及具体知识点。)

🖼️ 图像平滑
“图像平滑是一种实用的数字图像处理技术。一个较好的平滑处理方法应该既能消除图像噪声,又不使图像边缘轮廓和线条变模糊,这是数字图像平滑处理要追求的目标。”

01 图像平滑基础
图像平滑的目标是去除噪声的同时保留边缘信息。
核(Kernel): 在滤波器中,核是一个加权系数的集合。滤波器可以被看作是一个带有加权系数的窗口,在处理图像时,这个窗口会在图像上滑动。
02 线性滤波
滤波器类型 描述
归一化方框滤波器 最简单的滤波器,输出像素值是核窗口内像素值的均值,所有像素加权系数相等。
方框滤波与均值滤波 方框滤波和均值滤波核基本一致,主要区别在于是否归一化处理。均值滤波是方框滤波归一化后的特殊情况。
高斯滤波 一种线性平滑滤波,特别有效于去除高斯噪声。
高斯滤波器参数
卷积核(Kernel): 用于对图像矩阵进行平滑的矩阵,也称为过滤器(Filter)。
锚点: 卷积核与图像矩阵重叠的位置,内积运算后该位置的像素点会被计算值取代,通常选取奇数卷积核的中心点作为锚点。
步长: 卷积核在图像矩阵上每次移动的长度。
内积: 卷积核和图像矩阵对应像素点相乘,然后相加得到的总和。
注意事项

KaTeX can only parse string typed expression
σ=0 时,OpenCV会根据窗口大小计算出
KaTeX can only parse string typed expression
σ,因此在滑动条上从0滑动
KaTeX can only parse string typed expression
σ 时,图像会出现先变清晰又变模糊的现象。
03 非线性滤波
滤波器类型 描述
中值滤波 用像素点领域灰度值的中值替代该像素点的灰度值,能有效去除最大值和最小值的干扰。
中值平滑的实现 中值滤波在数字图像处理中属于空域平滑滤波的内容,适合消除椒盐噪声。
双边滤波 一种非线性滤波器,能够在平滑的同时保持边缘。采用加权平均的方法,以周边像素亮度值的加权平均代表某个像素的强度。
双边滤波参数
cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace): 函数用于应用双边滤波,其中的权重取决于邻域像素与当前像素的灰度差值。
优缺点总结
优点: 能够在平滑的同时保留图像的边缘信息。
缺点: 可能会在某些情况下削弱图像的细节。
感谢观看
以上是关于图像平滑的基本概念与技术,帮助理解不同滤波方法的应用。

🖼️ 几何变换基础
🌐 几何变换概述
图像的几何变换是指使用户获得或设计的原始图像,按照需要产生大小、形状和位置变化。图像的几何变换主要包括平移、旋转、缩放、翻转和剪切等操作。

📦 平移变换
平移变换定义
图像平移是将一幅图像中所有的点都按照指定的平移量在水平、垂直方向移动,平移后的图像与原图像相同。

平移变换类型
平移变换分为两种类型:

图像大小不改变:平移后原图像中会有一部分不在图像中。
图像大小改变:可以保全原图像的内容。
平移变换的数学表示
二维图像几何变换及变换中心在坐标原点的比例缩放、反射、错切和旋转等各种变换,都可以用
KaTeX can only parse string typed expression
2×2 的矩阵来表示和实现。

OpenCV 中的平移函数
使用 OpenCV 提供的函数 warpAffine 进行平移,函数声明如下:

python
Copy
warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
🔄 图像旋转
图像旋转定义
图像的旋转是数字图像处理中一个非常重要的环节,是图像的几何变换手法之一。

旋转的基本性质
一般图像的旋转是以图像的中心为原点,将图像上的所有像素都旋转一个相同的角度。
旋转时图像的位置变换,旋转后图像的大小一般会改变。
仿射变换
平移、旋转、缩放、翻转、剪切等变换都属于仿射变换。仿射变换是一种常用的图像几何变换,能够方便地描述图像的线性变换以及平移等非线性变换。

OpenCV 中的旋转函数
进行仿射变换的函数是 warpAffine,声明如下:

python
Copy
warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
📏 图像缩放
图像缩放定义
图像比例缩放是指将给定的图像在
KaTeX can only parse string typed expression
x 轴方向按比例缩放
KaTeX can only parse string typed expression
f
x

倍,在
KaTeX can only parse string typed expression
y 轴方向按比例缩放
KaTeX can only parse string typed expression
f
y

倍,从而获得一幅新的图像。

缩放原理
为了提高几何变换后的图像质量,常采用线性插值法。该方法的原理是,当求出的分数地址与像素点不一致时,求出周围四个像素点的距离比,根据该比率由四个邻域的像素灰度值进行线性插值。

OpenCV 中的缩放函数
在 OpenCV 中,实现图像缩放的函数是 resize,函数声明如下:

python
Copy
resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) → dst
参数说明
src:原图像
dst:输出图像
dsize:目标图像的大小
fx:在
KaTeX can only parse string typed expression
x 轴上的缩放比例
fy:在
KaTeX can only parse string typed expression
y 轴上的缩放比例
interpolation:插值方式,包括:
INTER_NN(最近邻插值)
INTER_LINEAR(默认值,双线性插值)
INTER_AREA(使用像素关系重采样,适合图像缩小时避免波纹出现)
INTER_CUBIC(立方插值)
🙏 感谢观看
以上是本次关于几何变换的讲解内容,涵盖了平移、旋转和缩放等基本概念及其在 OpenCV 中的实现方式。

🖼️ 图像边缘检测
📚 目录
01 概述
02 边缘检测研究的历史现状
03 边缘定义及类型分析
04 梯度的概念
05 图像边缘检测的应用
06 目前边缘检测存在的问题
07 边缘检测的基本思想
08 图像边缘检测的步骤
09 经典图像边缘检测法
01 概述
边缘检测是图像处理和计算机视觉中的基本问题,目的是标识数字图像中亮度变化明显的点。

边缘检测算法的不断提出与应用于工程实际。
边缘的显著变化反映了重要事件和变化,如深度不连续、表面方向不连续等。
02 边缘检测研究的历史现状
趋势:
不断改进现有算法。
引入新方法、新概念及多种方法的有效综合利用。
交互式检测研究的深入,特别是在医学图像分析中。
对特殊图像边缘检测的重视。
边缘检测评价的研究日益受到关注。
03 边缘定义及类型分析
边缘是指图像中灰度发生急剧变化的区域,主要存在于目标与目标、目标与背景、区域与区域之间。

边缘检测算子分类:
一阶微分为基础的边缘检测:通过计算图像的梯度值来检测边缘。
二阶微分为基础的边缘检测:通过寻找二阶导数中的过零点来检测边缘。
混合一阶与二阶微分:综合利用一阶与二阶微分特征。
04 梯度的概念
梯度是一阶导数的二维等效式,定义为矢量,表示函数增大时的最大变化率方向。

重要性质
对一阶导数和二阶导数的不熟悉需重新温习。
数字图像的梯度近似表达式为:
05 图像边缘检测的应用
边缘检测在多个领域的应用,包括:
航天和航空技术:处理月球、火星照片,应用于遥感技术。
生物医学工程:CT技术及显微图像处理分析。
公安军事:图片判读分析、指纹识别、人脸鉴别等。
交通管理系统:车牌定位、字符车牌分割和识别。
06 目前边缘检测存在的问题
实际图像含有噪声,噪声与边缘均为高频信号,且噪声分布未知。
边缘在不同尺度范围上出现,传统算法难以同时检测所有边缘。
常见误差包括:
丢失有效边缘
边缘定位误差
噪声误判为边缘
噪声消除与边缘定位是互相矛盾的问题。
07 边缘检测的基本思想
边缘检测的基本思想是利用边缘增强算子对边缘进行检测,通过设置阈值提取边缘点。

边缘检测流程
图像获取
图像滤波
图像增强
图像检测
图像定位
08 图像边缘检测的步骤
图像获取:将图像转化为灰度图像。
图像滤波:使用滤波器改善边缘检测性能。
图像增强:确定各点邻域强度变化值。
图像检测:使用梯度幅值阈值判据。
图像定位:通过阈值法和零交叉法实现边缘图像的精确定位。
09 经典图像边缘检测法
边缘检测算法提取对象与背景的交界线,主要算法包括:
Sobel算子:根据邻域灰度加权算法进行边缘检测。
Prewitt算子:一种边缘样板算子。
Roberts算子:基于交叉微分的梯度算法,通过局部差分计算检测边缘。
Log边缘检测算子:基于拉普拉斯二阶导数的算法。
新技术与方法:基于小波、分形、数学形态学、模糊学、神经网络和遗传算法的边缘检测技术。
🔍 图像分割
📖 图像分割概述
图像分割是将一幅数字图像按照某种目的划分成两个或多个子图像区域的过程。图像分割是机器视觉和图像处理领域的一个重要研究方向。

随着计算机技术的发展,图像作为信息载体的作用日益重要。
图像分割的研究成果每年都有大量涌现,涵盖了多种算法和应用。
📈 图像分割技术现状
图像分割算法种类繁多,涵盖了从传统方法到现代深度学习的方法。
研究者们对分割算法的分类和系统化研究能够更好地理解该领域的发展。
🔬 图像分割的应用
应用领域 具体实例
医学影像分析 将医学图像中的不同组织分成不同区域,帮助分析病情
军事研究领域 为目标自动识别提供参数,支持飞行器和武器导航
遥感气象服务 通过遥感图像分析获得城市地貌、作物生长状况等
交通图像分析 分割交通监控图像中的车辆目标,进行车牌识别
面向对象的图像压缩 提高压缩编码效率,提取特征以便网页分类和搜索
📏 图像分割的数学定义
设集合
KaTeX can only parse string typed expression
R 代表整幅图像的区域,对
KaTeX can only parse string typed expression
R 的分割可看作将
KaTeX can only parse string typed expression
R 分割成
KaTeX can only parse string typed expression
N 个满足特定条件的非空子集
KaTeX can only parse string typed expression
R
1

,R
2

,…,R
n


🔑 图像分割方法的分类
方法分类 说明
区域生长与分裂合并法 基于区域的分割方法。
基于图像的随机场模型法 利用随机场模型进行分割。
有监督的分类分割法 依赖于已有标签数据进行分割。
基于神经网络的分割方法 模拟生物神经元,通过学习进行图像分割。
基于阈值化的分割方法 根据图像灰度直方图信息确定分割阈值。
基于边缘的分割方法 通过检测不同均匀区域之间的边界实现分割。
基于聚类的分割方法 将数据集划分为若干组,使同组内相似度高,不同组相似度低。
基于区域的分割方法 通过选定相似性度量和评价聚类结果的准则进行分割。
🛠️ 使用OpenCV进行图像分割
图像阈值化分割
固定阈值分割
在OpenCV中使用 threshold 函数进行固定阈值分割。

python
Copy
retval = threshold(src, thresh, maxval, type[, dst])
自适应阈值分割
在OpenCV中使用 adaptiveThreshold 函数。

python
Copy
dst = adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
彩色图像分割
彩色图像通过不同的色彩值进行分割,常用的彩色空间有HSV、RGB、LAB等。
使用 grabCut 算法进行前景分割,用户只需简单地圈出前景区域。
grabCut函数
在OpenCV中实现的 grabCut 函数。

python
Copy
grabCut(img, mask, rect, bgdModel, fgdModel, iterCount[, mode]) → None
🌊 floodFill漫水填充分割
基本概念
漫水填充算法用于自动选中与种子像素相连的区域,常用于图像标记和分离。

floodFill函数
OpenCV中的 floodFill 函数。

python
Copy
retval, rect = floodFill(image, mask, seedPoint, newVal[, loDiff[, upDiff[, flags]]])
🌊 分水岭分割法
分水岭算法通过分析临近像素间的相似性,将相近像素连接形成封闭轮廓,是图像分割的基础研究之一。
🖼️ 图像金字塔
目录
01 基本概念
02 高斯金字塔
03 拉普拉斯金字塔
01 基本概念
图像金字塔是以多个分辨率来表示图像的一种有效且概念简单的结构。图像金字塔最初用于机器视觉和图像压缩。

一个图像金字塔是一系列以金字塔形状排列的、分辨率逐步降低的图像集合。
图像金字塔的类型
类型 描述
高斯金字塔 用来向下采样,是主要的图像金字塔。
拉普拉斯金字塔 用来从金字塔底层图像重建上层未采样的图像,可以对图像进行最大限度的还原,通常与高斯金字塔一起使用。
02 高斯金字塔
高斯金字塔是由底部的最大分辨率图像逐次向下采样得到的一系列图像。

最下面的图像分辨率最高,越往上图像分辨率越低。
采样过程
向上取样:通过小图像不断放大图像的过程。
向下取样:逐渐降低图像的分辨率。
函数
向上取样:
pyrUp(src, dst=None, dstsize=None, borderType=None)
向下取样:
pyrDown(src, dst=None, dstsize=None, borderType=None)
03 拉普拉斯金字塔
拉普拉斯金字塔可以从高斯金字塔计算得来,主要应用于图像融合。

在OpenCV 4版本中,拉普拉斯金字塔位于imgproc模块的Image Filtering子模块中。
函数原型
plaintext
Copy
Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
参数 描述
src 原图
dst 目标图像
ddepth 目标图像的深度
ksize 用于计算二阶导数滤波器的孔径大小,必须为正数和奇数
scale 计算拉普拉斯值的可选比例因子,默认情况下不应用缩放
delta 在将结果存储到dst之前添加到结果中的可选增量值
borderType 决定在图像发生几何变换或者滤波操作时边沿像素的处理方式
拉普拉斯金字塔的特点
拉普拉斯金字塔是高斯金字塔的修正版,通过计算残差图来还原到原图。
其构建过程是将降采样之后的图像进行上采样操作,然后与未降采样的原图进行差分,得到的就是残差图。
感谢观看
📸 图像形态学
01 图像形态学基本概念
“图像的形态学处理是以数学形态学为理论基础、借助数学方法对图像进行形态处理的技术。在图像的形态学处理中,图像所具有的几何特性将成为算法中最让人关心的信息。”

形态学应用
消除噪声
边界提取
区域填充
连通分量提取
凸壳
细化
粗化
分割出独立的图像元素
求取图像中明显的极大值区域和极小值区域
求取图像梯度
02 数学上的形态学
数学形态学由一组形态学的代数运算子组成,基本运算有四个:
膨胀(或扩张)
腐蚀(或侵蚀)
开启
闭合
拓扑学
“拓扑学是一门研究拓扑空间的学科,主要研究空间内在连续变化下维持不变的性质。”

数学形态的组成与操作分类
一般拓扑学建立拓扑的基础,并研究拓扑空间的性质。
代数拓扑学运用同调与同伦群等代数结构量测连通性的程度。
微分拓扑学研究在微分流形式上的可微函数。
数学形态学的应用
基于击中/击不中变换的目标识别
基于流域概念的图像分割
基于腐蚀和开运算的骨架抽取及图像编码压缩
基于测地距离的图像重建
基于形态学滤波器的颗粒分析
03 结构元素
“结构元素是用来处理图像的形状,通常都是一些比较小的图像。”

04 膨胀与腐蚀
膨胀:使图像中的目标“生长”或“变粗”的过程,由结构元素的形状控制。
腐蚀:将结构元素平移后得到的结果,满足条件的点组成的集合称作被腐蚀的结果。
05 开运算与闭运算
开运算:先进行腐蚀操作再进行膨胀操作,用于移除小的对象。
闭运算:先进行膨胀操作再进行腐蚀操作,用于填充前景物体中的小洞。
06 实现腐蚀和膨胀
OpenCV 函数
erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) → dst
morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) → dst
getStructuringElement(shape, ksize[, anchor]) → retval
示例代码
python
Copy
g_nStructElementSize = 3 # 结构元素的尺寸
element = getStructuringElement(MORPH_RECT,
Size(2g_nStructElementSize+1, 2g_nStructElementSize+1),
Point(g_nStructElementSize, g_nStructElementSize))
07 用形态学运算检测边缘
“形态学检测边缘的原理很简单,在膨胀时图像中的物体会向周围“扩张”;腐蚀时,图像中的物体会“收缩”。”

击中击不中变换
用击中结构去腐蚀原始图像得到击中结果。
用击不中结构去腐蚀原始图像的补集得到击不中结果。
取X和Y的交集就是击中击不中的结果。
08 利用形态学运算提取水平线和垂直线
处理步骤
利用函数 imread 输入图像彩色图像。
使用函数 cvtColor 转换为灰度图像。
使用函数 adaptiveThreshold 转换为二值图像。
定义结构元素。
使用形态学操作中的开操作(腐蚀+膨胀)提取水平与垂直线。
函数声明
python
Copy
adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) → dst

📹 OpenCV视频处理实战

目录

  1. OpenCV视频处理架构
  2. 捕获视频类VideoCapture对象

01 OpenCV视频处理架构

OpenCV视频I/O模块

OpenCV的视频I/O模块提供了一组用于读写视频或图像序列的类和函数。该模块将cv::VideoCapturecv::VideoWriter类作为一层接口面向用户,这两个类下面是很多不同种类的后端视频I/O API,有效地屏蔽了后端视频I/O的差异性,简化了用户层的编程。

用户层与底层的关系

  • 用户层(USER APPLICATION) 主要与 VideoCaptureVideoWriter 两个类打交道,而无须与底层打交道。
  • 在OpenCV中,视频的读操作是通过 VideoCapture 类来完成的,视频的写操作是通过 VideoWriter 类来实现的。

02 捕获视频类VideoCapture

构造VideoCapture对象

  • VideoCapture 既支持从视频文件(如 .avi、.mp4、.mpg 等格式)读取,也支持直接从摄像头(例如计算机自带的摄像头)中读取。
  • 要想获取视频,需要先创建一个 VideoCapture 对象。

读取视频帧

  • 读取方法是使用函数 read,该函数声明如下:

VideoCapture.read([image])→retval, image \text{VideoCapture.read([image])} \rightarrow \text{retval, image} VideoCapture.read([image])retval, image

播放视频文件

创建 VideoCapture 对象的方式:

  • 从视频文件中读取视频
  • 从摄像机中读取视频
  • 不带参数构造一个 VideoCapture 对象

播放过程

  1. 先构造 VideoCapture 对象
  2. 打开视频文件
  3. 用一个循环逐帧读取并显示读取到的视频帧
  4. 间隔一段时间读取下一个视频帧并显示,直到全部视频帧读取完毕

获取和设置视频属性

  • VideoCapture 的成员函数 get 可以用来获取视频文件的一些属性,比如帧数。该函数声明如下:

VideoCapture.get(propId)→retval \text{VideoCapture.get(propId)} \rightarrow \text{retval} VideoCapture.get(propId)retval

判断打开视频是否成功

  • 可以用成员函数 isOpened 来判断是否打开成功。函数声明如下:

VideoCapture.isOpened()→retval \text{VideoCapture.isOpened()} \rightarrow \text{retval} VideoCapture.isOpened()retval

  • 如果计算机中插了一个摄像头,那么 open 的第一个参数通常是 700,例如:

KaTeX parse error: Expected 'EOF', got '_' at position 42: …e.open(700, CAP_̲DSHOW);}


感谢观看

🅿️ 停车场车牌识别案例实战

📋 目 录

  • 01 需求分析
  • 02 技术可行性分析
  • 03 车牌定位技术
  • 04 车牌字符分割技术
  • 05 车牌字符识别技术

01 需求分析

国外技术分析

  • 国外较早研究和发展基于机器视觉技术的车牌识别技术,起始于20世纪初。
  • 随着社会经济的发展,汽车数量逐年上升,车牌自动识别系统的应用变得日益重要。

主要技术

  • 图像处理技术
  • 一维条形码技术
  • 二维数字识别码技术
  • 三维立体识别码技术
  • IC卡识别技术

国内技术分析

  • 中国的车牌识别研究起步较晚,面临误定位和车牌分割等技术难点。

车牌识别技术的难点

  • 误定位是研究重点,如何实现良好的车牌分割和倾斜度校正是主要挑战。

ALPR系统的关键子系统

  • 车牌定位
  • 字符识别

车牌识别系统概述

车牌识别系统由以下四个部分组成:

  1. 原始车辆图像采集
  2. 汽车牌照区域定位
  3. 汽车牌照内字符的分割
  4. 汽车牌照内字符的识别

03 车牌定位技术

车牌特征

  • 字符特征
  • 形状特征
  • 颜色特征
  • 灰度变化特征

车牌图像的灰度化

  • 使用分量法、最大值法、平均值法、加权平均法等进行图像的灰度化处理。

车牌图像的直方图均衡化

  • 采用直方图均衡化以实现车牌图像亮度接近化的转换处理。

车牌定位方法

  • 基于边缘检测
  • 基于遗传算法
  • 基于纹理特征
  • 基于数学形态学
  • 基于小波分析和变换
  • 基于神经网络的方法

车牌图像预处理

  • 预处理的目的是得到清晰的图像,以便后续分析。

04 车牌字符分割技术

字符分割方法

  • 基于识别基础的车牌字符分割法
  • 垂直投影分割方法
  • 自适应分割线聚类法

车牌倾斜度检测方法

  • 基于行扫描的灰度值跳变点数目变化率判断车牌是否水平。

车牌倾斜问题

  • 倾斜校正分为垂直倾斜和水平倾斜,根据倾斜类型进行处理。

车牌边框和铆钉的去除

  • 通过逐行扫描,去除干扰的行。

字符分割过程的注意事项

  • 切分结果需与字符尺寸一致,包括字符拆分和合并。

粘连车牌字符的分割

  • 在低质量图像中,二值化后出现的字符粘连现象难以分割。

断裂车牌字符的合并

  • 计算相邻块之间的距离,合并块以消除断裂。

05 车牌字符识别技术

模式识别

  • 影响字符识别的因素包括相机性能、图像采集时光照差异、车牌清洁度。

字符识别方法

  • 基于神经网络的识别方法
  • 基于特征分析的匹配方法
  • 基于模版的匹配方法

汉字识别的难点

  • 汉字字符识别难度更大,主要因素包括切分误差、污垢、低分辨率及光照影响。

字符识别原理及发展阶段

  • 字符识别的基本原理包括预处理、模式表达、判别和字典学习。

感谢观看

📊 OpenCV目标检测

目标检测概述

“目标检测是计算机视觉的一个重要任务,涉及到在图像或视频中识别和定位对象。”

  • 图像分类是计算机视觉的基本任务之一,在此基础上,目标检测物体定位图像分割等任务更为复杂和有趣。
  • 目标检测技术可以用于:
    • 检测单幅图像
    • 检测视频中的某一帧图像
    • 适用于日常拍摄的图像及红外、微波等其他方式获得的数字图像

目标检测的基本概念

  • 视频序列中的每个图像称为,视频由一帧帧图像构成。
  • 图像是通过不同的系统以不同方式观测实际物体而获得,可以直接或间接作用于肉眼产生视觉的实体。
  • 在现实生活中采集到的视频图像常常存在噪声,对视频中的目标进行检测与跟踪前,需选择合适的算法抑制噪声干扰,这是图像预处理中的重要步骤。

视频序列图像预处理

  • 对于标准的图像处理系统,降低噪声干扰是最关键的步骤。

基于深度学习的运动目标检测

YOLO算法

  • YOLO(You Only Look Once)是一种实时目标检测算法,能够快速检测视频中的运动目标并获取其运动位置。
  • YOLO算法的关键点包括:
    • 使用Batch Normalization对每个卷积层的输入进行归一化。
    • Anchors机制:使用k-means聚类方法生成不同尺寸的Anchors。
    • 新的基础网络结构Darknet-19
    • 优化的直接位置预测方法,计算预测边框的位置信息和置信度。

YOLOv2概述

  • 采用多尺度预测机制和简单的逻辑回归进行分类。
  • 需要准备以下文件以加载预训练的YOLOv3模型:
    • yolov3.cfg(网络配置文件)
    • yolov3.weights(权重文件)
    • coco.names(标签文件)

YOLOv3实战

  • 在YOLOv3中,模型加载和物体识别的具体流程包括准备以上三个文件,并通过OpenCV进行实战操作。

SSD算法

  • SSD(Single Shot MultiBox Detector)是一种目标检测算法,训练模型分析、特征层默认框的匹配策略、代价函数的设定及深度残差网络是其基本原理。
  • OpenCV提供的API示例:
    • dnn.blobFromImage(image[, scalefactor[, size[, mean[, swapRB[, crop[, ddepth]]]]]]) -> ret

实战SSD与人脸检测

  • 实战人脸检测中,使用AdaBoost算法原理:
    • 初始化训练数据的权值分布
    • 训练弱分类器
    • 将多个弱分类器组合成强分类器

其他内容

  • 本章内容涵盖了目标检测的基本概念以及基于深度学习的目标检测技术,提供了对YOLO和SSD算法的详细分析和实战指导。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值