0%

OpenCV

OpenCV

常用API

基本操作

读取 cv2.imread()

显示cv2.imshow()

保存 cv2.imwrite()

shape(高度,宽度,通道)

灰度化

将三通道彩色图像转换成单通道灰度图
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

直接读取成单通道的灰度图
image_gray2 = cv2.imread('./img/lena.png', cv2.IMREAD_GRAYSCALE)

二值化

cv2.threshold—全局二值化

retval, dst = cv2.threshold(src, thresh, maxval, type)

参数说明

  • src:输入图像,必须是单通道灰度图像(8-bit 或 32-bit 浮点型)。
  • thresh:阈值,用于将像素值分类。
  • maxval:当像素值超过阈值时赋予的新值(在二值化中通常为 255)。
  • type:阈值化类型,决定如何应用阈值。常用的类型包括:

cv2.THRESH_BINARY: 二值化,大于阈值的像素设为 maxval,否则设为 0。

cv2.THRESH_BINARY_INV: 反二值化,大于阈值的像素设为 0,否则设为 maxval。

cv2.THRESH_TRUNC: 截断,大于阈值的像素设为阈值,其余保持不变。

cv2.THRESH_TOZERO: 零化,大于阈值的像素保持不变,其余设为 0。

cv2.THRESH_TOZERO_INV: 反零化,大于阈值的像素设为 0,其余保持不变。

cv2.THRESH_OTSU: 自动计算阈值(适用于双峰直方图图像),需与 cv2.THRESH_BINARY 或 cv2.THRESH_BINARY_INV 结合使用。

cv2.THRESH_TRIANGLE: 使用三角法自动计算阈值,适用于单峰直方图图像。

返回值

  1. retval:
    • 实际使用的阈值。如果使用 cv2.THRESH_OTSU 或 cv2.THRESH_TRIANGLE,返回的是自动计算的阈值。
  2. dst:
    • 输出图像,与输入图像大小和类型相同。

OTSU阈值法

注意:OTSU在使用时候,需要配合其他的二值化方法去进行,其模式就是 cv2.THRESH_OTSU + 要二值化的方法的参数
使用OTSU,thresh参数没有任何用处
其中,ret存放的是二值化所用的阈值,如果我们使用固定阈值法时,ret没有任何作用
当我们使用OTSU去计算最合适的阈值时,ret就有用了
image_thresh里存放的是二值化的图(本质上是与image_gray大小相同的单通道数组)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 导入OpenCV的库
import cv2
import numpy as np
# 1. 读取要滤波的图像
image = cv2.imread('./img/lena.png')
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 定义阈值法所需要的阈值
thresh = 150
# 定义阈值法所需要的最大值
maxval = 255
# 使用opencv的函数去进行二值化
ret, image_thresh = cv2.threshold(image_gray, thresh, maxval, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
print(ret)
# 3. 图像显示
cv2.imshow('image', image)
cv2.imshow('image_gray', image_gray)
cv2.imshow('image_thresh', image_thresh)
cv2.waitKey(0)

图像自适应二值化—局部二值化

dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)

参数说明

  1. src:
  • 输入图像,必须是单通道灰度图像(8-bit)。
  1. maxValue:
  • 当像素值满足条件时赋予的新值(通常为 255)。
  1. adaptiveMethod:
  • 自适应阈值计算方法,可选以下两种:
  • cv2.ADAPTIVE_THRESH_MEAN_C: 使用局部区域的均值作为阈值。
  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C: 使用局部区域的加权均值(高斯加权)作为阈值。
  1. thresholdType:
  • 阈值化类型,只能是以下两种:
  • cv2.THRESH_BINARY: 大于阈值的像素设为 maxValue,否则设为 0。
  • cv2.THRESH_BINARY_INV: 大于阈值的像素设为 0,否则设为 maxValue。
  1. blockSize:
  • 局部区域的大小(必须是奇数),用于计算阈值。核的大小,通常为奇数 3,3, 5,5
  1. C:
  • 从计算出的阈值中减去的常数,用于微调阈值。通常是正数,但也有可能是0或负数

返回值

  • dst:
  • 输出图像,与输入图像大小和类型相同。
1
image_binary = cv2.adaptiveThreshold(image_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 7, 5)

视频处理

cv2.VideoCapture() 读取视频或摄像头。根据设备编号获取,一般摄像头都是0。可以传入视频的路径。
cap.read()读取摄像头的每一帧
cap.release()释放
cv2.VideoWriter() 保存视频。

读取摄像头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2

# 创建窗口
cv2.namedWindow('video', cv2.WINDOW_AUTOSIZE)
cv2.resizeWindow('video', 800, 600)

# 打开摄像头
cap = cv2.VideoCapture(0)

while True:
# 从摄像头读取视频帧, ret布尔值表示帧是否被正确读取,frame是读取的视频帧
ret, frame = cap.read()
# 将视频帧在窗口中显示
cv2.imshow('video', frame)
# 等待键盘事件,如果q,退出
key = cv2.waitKey(1)
if key == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

读取视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import cv2

# 创建窗口
cv2.namedWindow('video', cv2.WINDOW_AUTOSIZE)
cap = cv2.VideoCapture('img/deepseek.mp4')

while True:
# 读取视频帧, ret布尔值表示帧是否被正确读取,frame是读取的视频帧
ret, frame = cap.read()
# 将视频帧在窗口中显示
cv2.imshow('video', frame)
# 等待键盘事件,如果q,退出
key = cv2.waitKey(50)
if key == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

摄像头录视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import cv2

# 创建窗口,会自动设置大小
# cv2.namedWindow('video', cv2.WINDOW_AUTOSIZE)
# 可以调整窗口大小
cv2.namedWindow('video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('video', 800, 600)
# 打开摄像头
cap = cv2.VideoCapture(0)

# 获取摄像头的分辨率
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
# 创建多媒体文件
# cv2.VideoWriter_fourcc函数用于指定视频文件的编解码器,指定Motion JPEG(MJPG)作为视频的编解码器
video_fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# 参数:输出文件的名称、视频的编解码器、帧率以及视频的尺寸(宽度和高度)一般是摄像头真实采样分辨率。
vw = cv2.VideoWriter('./img/myvideo1.mp4', video_fourcc, fps, (frame_width, frame_height))
while True:
# 从摄像头读取视频帧, ret布尔值表示帧是否被正确读取,frame是读取的视频帧
ret, frame = cap.read()
if not ret:
break
# 将视频帧在窗口中显示
cv2.imshow('video', frame)
# 写数据到多媒体文件
vw.write(frame)
# 等待键盘事件,如果q,退出
key = cv2.waitKey(50)
if key == ord('q'):
break
cap.release()
vw.release()
cv2.destroyAllWindows()

绘图

绘制直线

1
cv2.line(image, pt1, pt2, color, thickness, lineType)

参数说明:
image:要绘制直线的图像。
pt1:直线的起点坐标,格式为 (x1, y1)。
pt2:直线的终点坐标,格式为 (x2, y2)。
color:直线的颜色,格式为 (B, G, R)。
thickness:直线的粗细(默认值为 1)。
lineType:线型(默认值为 cv2.LINE_8)。

绘制文本

1
cv2.putText(image, text, org, fontFace, fontScale, color, thickness, lineType)

参数说明:
image:要绘制文本的图像。
text:要绘制的文本内容。
org:文本的左下角坐标,格式为 (x, y)。
fontFace:字体类型(如 cv2.FONT_HERSHEY_SIMPLEX)。
fontScale:字体缩放比例。
color:文本颜色,格式为 (B, G, R)。
thickness:文本的粗细(默认值为 1)。
lineType:线型(默认值为 cv2.LINE_8)。

绘制矩形

1
cv2.rectangle(image, pt1, pt2, color, thickness, lineType)

参数说明:
image:要绘制矩形的图像。
pt1:矩形的左上角坐标,格式为 (x1, y1)。
pt2:矩形的右下角坐标,格式为 (x2, y2)。
color:矩形的颜色,格式为 (B, G, R)。
thickness:矩形的边框粗细(如果为 -1,则表示填充矩形)。
lineType:线型(默认值为 cv2.LINE_8)。

绘制圆形

1
cv2.circle(image, center, radius, color, thickness=1, lineType=LINE_8, shift=None)

参数说明
image: 输入图像,圆形将绘制在此图像上。
center: 圆心的坐标,格式为 (x, y)。
radius: 圆的半径(以像素为单位)。
color: 圆的颜色,格式为 (B, G, R)。例如,(0, 255, 0) 表示绿色。
thickness (可选): 圆的线宽。如果为负数(例如 -1),则填充圆形内部。默认为 1。
lineType (可选): 线条类型,默认为 cv2.LINE_8。其他选项包括 cv2.LINE_4 和 cv2.LINE_AA(抗锯齿)。
shift (可选): 圆心坐标和半径的小数位数。通常不需要设置。

图像形态学变换

卷积核

cv2.getStructuringElement 是 OpenCV 中用于创建形态学操作所需的结构元素(Structuring Element)的函数。结构元素是一个小的形状(如矩形、圆形、十字形等),用于定义形态学操作(如腐蚀、膨胀、开运算、闭运算等)的邻域范围。

1
cv2.getStructuringElement(shape, ksize, anchor)

参数说明

  1. shape: 结构元素的形状,可以是以下常量之一:
    cv2.MORPH_RECT: 矩形结构元素。
    cv2.MORPH_ELLIPSE: 椭圆形结构元素。
    cv2.MORPH_CROSS: 十字形结构元素。
  2. ksize: 结构元素的大小,格式为 (宽度, 高度)。例如,(3, 3) 表示一个 3x3 的结构元素。
  3. anchor(可选): 结构元素的锚点位置,默认为中心点 (-1, -1)。

返回值 返回一个指定形状和大小的结构元素(NumPy 数组)。

腐蚀

腐蚀操作就是使用核在原图(二值化图)上进行从左到右、从上到下的滑动(也就是从图像的左上角开始,滑动到图像的右下角)。在滑动过程中,令核值为1的区域与被核覆盖的对应区域进行相乘,得到其最小值,该最小值就是卷积核覆盖区域的中心像素点的新像素值,接着继续滑动。由于操作图像为二值图,所以不是黑就是白,这就意味着,在被核值为1覆盖的区域内,只要有黑色(像素值为0),那么该区域的中心像素点必定为黑色(0)。这样做的结果就是会将二值化图像中的白色部分尽可能的压缩,如下图所示,该图经过腐蚀之后,“变瘦”了。

1
dst = cv2.erode(src, kernel, anchor=(-1, -1), iterations=1, borderType= BORDER_CONSTANT, borderValue=0)

参数说明

  1. src: 输入图像,可以是灰度图像或二值图像(通常为 uint8 类型)。
  2. kernel: 结构元素(Structuring Element),用于定义腐蚀操作的邻域范围。 可以通过 cv2.getStructuringElement 创建。
  3. anchor(可选): 结构元素的锚点位置,默认为中心点 (-1, -1)。
  4. iterations(可选): 腐蚀操作的迭代次数,默认为 1。
  5. borderType(可选): 边界填充类型,默认为 cv2.BORDER_CONSTANT。
  6. borderValue(可选): 边界填充值,默认为 0。

返回值 返回腐蚀后的图像

膨胀

膨胀与腐蚀刚好相反,膨胀操作就是使用核在原图(二值化图)上进行从左到右、从上到下的滑动(也就是从图像的左上角开始,滑动到图像的右下角),在滑动过程中,令核值为1的区域与被核覆盖的对应区域进行相乘,得到其最大值,该最大值就是核覆盖区域的中心像素点的新像素值,接着继续滑动。由于操作图像为二值图,所以不是黑就是白,这就意味着,在卷积核覆盖的区域内,只要有白色(像素值为255),那么该区域的中心像素点必定为白色(255)。这样做的结果就是会将二值化图像中的白色部分尽可能的扩张,如下图所示,该图经过腐蚀之后,“变胖”了。

1
dst = cv2.dilate(src, kernel, anchor=(-1, -1), iterations=1, borderType= BORDER_CONSTANT, borderValue=0)

参数说明

  1. src: o 输入图像,可以是灰度图像或二值图像(通常为 uint8 类型)。
  2. kernel: o 结构元素(Structuring Element),用于定义膨胀操作的邻域范围。 o 可以通过 cv2.getStructuringElement 创建。
  3. anchor(可选): 结构元素的锚点位置,默认为中心点 (-1, -1)。
  4. iterations(可选): 膨胀操作的迭代次数,默认为 1。
  5. borderType(可选): 边界填充类型,默认为 cv2.BORDER_CONSTANT。
  6. borderValue(可选): 边界填充值,默认为 0。

返回值 返回膨胀后的图像。

开运算

开运算(Opening Operation) 是形态学图像处理中的一种基本操作,它是**腐蚀(Erosion)和膨胀(Dilation)**的组合。开运算先对图像进行腐蚀操作,然后再对腐蚀结果进行膨胀操作。开运算的主要作用是去除小物体、平滑物体边界,同时保留物体的主要形状。
开运算的作用

  1. 去除小物体:
    开运算可以去除比结构元素小的物体或噪声。
  2. 平滑物体边界:
    开运算可以使物体的边界变得更加平滑。
  3. 分离物体:
    如果两个物体之间有细小的连接,开运算可以将它们分离。
  4. 保留主要形状:
    开运算不会显著改变物体的主要形状。

cv2.morphologyEx 是 OpenCV 中用于形态学操作的函数,支持多种形态学操作,包括开运算、闭运算、形态学梯度、顶帽运算和黑帽运算等。它的功能比单独的腐蚀(cv2.erode)和膨胀(cv2.dilate)更强大,可以一次性完成复杂的形态学操作。

1
dst = cv2.morphologyEx(src, op, kernel, anchor=(-1, -1), iterations=1, borderType=BORDER_CONSTANT, borderValue=0)

参数说明

  1. src: o 输入图像,可以是灰度图像或二值图像(通常为 uint8 类型)。
  2. op: o 形态学操作类型,可以是以下常量之一: cv2.MORPH_OPEN: 开运算(先腐蚀后膨胀),用于去除小物体、平滑边界。 cv2.MORPH_CLOSE:
    闭运算(先膨胀后腐蚀),用于填补空洞、连接断裂部分。 cv2.MORPH_GRADIENT:
    形态学梯度(膨胀结果减去腐蚀结果),用于提取物体边缘。 cv2.MORPH_TOPHAT:
    顶帽运算(原图像减去开运算结果),用于提取比结构元素小的亮区域。 cv2.MORPH_BLACKHAT:
    黑帽运算(闭运算结果减去原图像),用于提取比结构元素小的暗区域。
  3. kernel: o 结构元素(Structuring Element),用于定义形态学操作的邻域范围。 o 可以通过 cv2.getStructuringElement 创建。
  4. anchor(可选): o 结构元素的锚点位置,默认为中心点 (-1, -1)。
  5. iterations(可选): o 形态学操作的迭代次数,默认为 1。
  6. borderType(可选): o 边界填充类型,默认为 cv2.BORDER_CONSTANT。
  7. borderValue(可选): o 边界填充值,默认为 0。 返回值 • 返回形态学操作后的图像。

闭运算

先膨胀后腐蚀
开运算 vs 闭运算

特性 开运算 (cv2.MORPH_OPEN) 闭运算 (cv2.MORPH_CLOSE)
操作顺序 先腐蚀后膨胀 先膨胀后腐蚀
主要作用 去除小物体、平滑边界 填补空洞、连接断裂部分
适用场景 去除噪声、分离物体 填补空洞、连接物体
对物体形状的影响 保留主要形状 保留主要形状

形态学梯度

形态学梯度是数学形态学(Mathematical Morphology) 的核心运算之一,核心逻辑是对图像先后执行 “膨胀” 与 “腐蚀” 操作,再通过两者的像素级差值,提取目标物体的边缘轮廓。该方法广泛应用于计算机视觉、图像分割、目标检测等领域,本质是利用膨胀扩大目标区域、腐蚀缩小目标区域的特性,使两者差异对应目标与背景的过渡边界(即边缘)。
**形态学梯度 = 膨胀(I)− 腐蚀(I)**这种方法常用于增强图像中物体的边缘信息,能够有效地突出高亮区域的外围。

检测算法 核心原理 优势 劣势 适用场景
形态学梯度 膨胀 - 腐蚀差值 边缘连续、实时性强、参数可控 抗噪声弱、边缘粗 实时目标轮廓提取、低对比度图像
Sobel 算子 计算灰度图像梯度幅值(水平 / 垂直) 定向边缘检测强、抗噪声较好 边缘离散、对细节敏感 定向边缘提取(道路、文本)
Canny 算子 高斯平滑→梯度计算→非极大值抑制→双阈值分割 边缘精细、抗噪声强、定位准 计算复杂、实时性弱 高精度边缘检测(医学影像、工业测量)
以下代码实现基本、内部、外部形态学梯度,可直观观察效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import cv2

import numpy as np

import matplotlib.pyplot as plt

# 1. 读取灰度图像

img = cv2.imread("sample.jpg", 0) # 0表示灰度模式

# 2. 定义结构元素(3×3正方形,可调整为(5,5)等)

kernel = np.ones((3, 3), np.uint8)

# 3. 计算三种梯度

basic_gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) # 基本梯度

internal_gradient = img - cv2.morphologyEx(img, cv2.MORPH_ERODE, kernel) # 内部梯度

external_gradient = cv2.morphologyEx(img, cv2.MORPH_DILATE, kernel) - img # 外部梯度

# 4. 显示结果

plt.figure(figsize=(12, 8))

plt.subplot(221), plt.imshow(img, cmap="gray"), plt.title("原始图像")

plt.subplot(222), plt.imshow(basic_gradient, cmap="gray"), plt.title("基本梯度")

plt.subplot(223), plt.imshow(internal_gradient, cmap="gray"), plt.title("内部梯度")

plt.subplot(224), plt.imshow(external_gradient, cmap="gray"), plt.title("外部梯度")

plt.show()

顶帽运算

顶帽运算,又称 “礼帽运算”,是数字图像处理中基于形态学操作的重要技术,核心是通过 “开运算” 与原始图像的差值,提取图像中比周围背景更亮的细小区域(如亮斑、亮线条),广泛应用于图像预处理中的细节增强、噪声去除等场景。
顶帽运算的本质是原始图像减去其开运算结果

黑帽运算

黑帽运算,是数字图像处理中基于形态学操作的关键技术,核心是通过 “闭运算” 与原始图像的差值,提取图像中比周围背景更暗的细小区域(如暗斑、暗线条),常与顶帽运算配合,用于暗细节增强、目标检测等场景,是图像预处理的重要工具之一。
黑帽运算的本质是对原始图像进行闭运算后,用闭运算结果减去原始图像

对比维度 顶帽运算(Top-Hat) 黑帽运算(Black-Hat)
核心公式 I - Opening(I) Closing (I) - I(闭运算减原始图像)
提取目标 比背景更亮的细小区域 比背景更暗的细小区域
典型用途 提取亮斑、亮线条 提取暗斑、暗线条
适用场景 深色背景中的亮目标检测 浅色背景中的暗目标检测

图像运算

加add(a,b)

变亮

1
2
3
img_lena = cv2.imread('img/lena.png')
img = np.ones_like(img_lena) * 100
img_result = cv2.add(img_lena, img)

减subtract(a,b)

变暗

1
2
3
img_lena = cv2.imread('img/lena.png')
img = np.ones_like(img_lena) * 100
img_result = cv2.subtract(img_lena, img)

图像的乘法multiply(a, b)变亮更快

图像的除法divide(a, b)变暗更快

图像的溶合addWeighted(A, alpha, B, beta, gamma)

1
addWeighted(A, alpha, B, beta, gamma)

参数说明:
alpha和beta是权重,两者和是1
gamma静态权重

要求两个图像的shape完全一致

1
resize(src, dsize, fx=None, fy=None, interpolation=None)

src:输入原图像。
dsize:输出图像的大小,格式为(宽,高)。如果为0,则需要指定fx和fy。
fx:沿x轴的缩放比例。设置dsize可以不用设置fx和fy。
fy:沿y轴的缩放比例。

图像的位运算-非操作bitwise_not(img)

图像的位运算-与操作bitwise_and(img1, img2)

图像的位运算-或运算、异或运算

bitwise_or(img1, img2):黑0白1处变为白1,全白为白,全黑为黑
bitwise_xor(img1, img2):黑白处变为白,全白为黑,全黑为黑

四种逻辑运算核心对比

运算类型 输入数量 核心规则 关键特征 典型应用
非(NOT) 1 输入反向(0→1,1→0) 唯一单输入运算,结果与输入完全相反 状态切换、信号反相
与(AND) 2 全1出1,有0出0 需所有条件满足,结果“严格”为真 多条件同时判断、门禁控制
或(OR) 2 有1出1,全0出0 至少一个条件满足,结果“包容”为真 多条件任选判断、故障报警
异或(XOR) 2 同出0,异出1 条件互斥,不能同时满足 数据加密、奇偶校验、数值交换

图像几何学变换

缩放cv2.resize( )

用于调整图像的大小(即图像的缩放)。这个函数可以将图像缩放到指定的尺寸,同时保持图像的宽高比(除非指定了新的宽高比)。图像缩放是图像处理中的基本操作之一,常用于图像预处理、数据增强或适应不同的显示设备。

1
2
3
4
5
6
7
8
9
dst = cv2.resize(src, dsize [, fx[, fy[, interpolation]]])
• src:输入图像,即要缩放的原始图像。
• dsize:输出图像的尺寸,通常是一个元组 (width, height)。如果指定了这个参数,那么 fx 和 fy 将被忽略。
• fx:宽度方向的缩放因子。如果指定了 dsize,则这个参数将被忽略。否则,它决定了输出图像的宽度是输入图像宽度的多少倍。
• fy:高度方向的缩放因子。如果指定了 dsize,则这个参数将被忽略。否则,它决定了输出图像的高度是输入图像高度的多少倍。
• interpolation:插值方法,用于决定图像缩放时像素值的计算方式。OpenCV 提供了多种插值方法,如 cv2.INTER_LINEAR(线性插值,默认值)、cv2.INTER_NEAREST(最近邻插值)、cv2.INTER_CUBIC(三次样条插值)、cv2.INTER_AREA(效果最好)等。

返回值
函数返回缩放后的图像。如果指定了 dst 参数,则函数不返回值,而是将结果存储在 dst 中。

在numpy中,先行后列,所以是[y, x]。对于opencv来说,讲究坐标xy。两者转换。

翻转cv2.flip( )

用于翻转图像。这个函数可以沿水平轴、垂直轴或同时沿两个轴翻转图像,从而得到镜像效果。函数根据指定的翻转标志对输入图像进行翻转操作。翻转是逐像素进行的,不改变图像的分辨率或颜色空间。

1
2
3
4
5
6
7
8
9
10
dst = cv2.flip(src, flipCode)
• src:输入图像,即要翻转的原图像。
• flipCode
:翻转的标志,控制翻转的方式。它可以是以下值之一:
0:表示绕x轴进行上下翻转。
1:表示绕y轴进行左右翻转。
-1:表示同时沿 x 轴和 y 轴翻转(水平和垂直翻转),相当于将图像旋转 180 度。

返回值
函数返回翻转后的图像,与输入图像具有相同的类型和大小。

旋转cv2.rotate( )

可以对图像进行 90 度、180 度或 270 度的旋转。这个函数非常适合快速实现简单的旋转操作。

1
2
3
4
5
6
7
8
9
10
11
cv2.rotate(src, rotateCode)

参数
1. src: 输入图像(需要旋转的图像)。
2. rotateCode: 旋转代码,指定旋转的方式。可选值包括:
cv2.ROTATE_90_CLOCKWISE: 顺时针旋转 90 度。
cv2.ROTATE_180: 旋转 180 度。
cv2.ROTATE_90_COUNTERCLOCKWISE: 逆时针旋转 90 度(相当于顺时针旋转 270 度)。

返回值
• 返回旋转后的图像。

平移cv2.warpAffine( )

图像平移(Image Translation)是图像处理中的一种基本几何变换,指的是将图像中的所有像素点沿着水平方向(x 轴)和/或垂直方向(y 轴)移动一定的距离。平移不会改变图像的内容,只会改变图像的位置。

平移可以用以下变换矩阵表示:
M =
[1 0 tx]
[0 1 ty]
tx 是水平方向(x 轴)的平移距离。ty 是垂直方向(y 轴)的平移距离。
对于图像中的每个像素点 (x, y),平移后的新坐标 (x’, y’) 可以通过以下公式计算:
x’ = x + tx
y’ = y + ty

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 对图像进行翻转操作
import cv2
import numpy as np
# 1. 读取图片
image = cv2.imread('./img/lena.png')
h, w, ch = image.shape
# 手动创建变换矩阵2x2单元矩阵,然后横向偏移100,竖向不进行偏移.
# 必须是float32,要求精度
M = np.float32([[1, 0, 100], [0, 1, 0]])
# 竖向平移300
# M = np.float32([[1, 0, 100], [0, 1, 300]])
img_new = cv2.warpAffine(image, M, (w, h))
# 3. 输出,显示
cv2.imshow('image', image)
cv2.imshow('img_new', img_new)
cv2.waitKey(0)

变换矩阵getRotationMatrix2D( )

cv2.getRotationMatrix2D 是 OpenCV 库中的一个函数,用于计算二维图像的旋转矩阵。这个旋转矩阵可以将图像绕指定的中心点旋转一定的角度,同时保持图像的尺寸不变(除非另外指定)。这个函数通常用于图像的旋转操作。函数根据指定的旋转中心、旋转角度和缩放因子计算出一个旋转矩阵。这个矩阵描述了图像如何绕中心点旋转,并且(如果指定了缩放因子)如何缩放。旋转是相对于图像坐标系的原点进行的,但可以通过指定不同的中心点来改变旋转的轴心。

1
retval = cv2.getRotationMatrix2D(center, angle, scale)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
retval = cv2.getRotationMatrix2D(center, angle, scale)
• center:旋转的中心点坐标,通常是一个元组 (x, y)。
• angle:旋转的角度,以度为单位。正值表示逆时针旋转,负值表示顺时针旋转。
• scale:图像缩放因子。默认值是 1.0,表示不缩放图像。如果需要缩放图像,可以指定一个大于或小于 1.0 的值。

返回值
函数返回一个 2x3 的 NumPy 数组,表示旋转矩阵。这个矩阵可以用于后续的图像变换操作,如 cv2.warpAffine 函数,来实际旋转图像。
M =
[[a, b, c],
[d, e, f]]
其中:
• a = scale * cos(angle)
• b = scale * sin(angle)
• c = (1 - a) * center_x - b * center_y
• d = -scale * sin(angle)
• e = scale * cos(angle)
• f = (1 - e) * center_y - d * center_x

仿射变换 warpaffine( )

cv2.warpAffine 是 OpenCV 中用于执行仿射变换的函数。仿射变换是一种线性变换,包括平移、旋转、缩放和剪切等操作。cv2.warpAffine 可以根据提供的变换矩阵对图像进行几何变换。

1
cv2.warpAffine(src, M, dsize, flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=0)

参数

  1. src: 输入图像。
  2. M: 2x3 的变换矩阵(通常通过 cv2.getRotationMatrix2D 或其他方法生成)。
  3. dsize: 输出图像的尺寸,格式为 (width, height)。
  4. flags: (可选)插值方法,默认为 cv2.INTER_LINEAR。常见选项包括:
  • cv2.INTER_NEAREST: 最近邻插值。
  • cv2.INTER_LINEAR: 双线性插值(默认)。
  • cv2.INTER_CUBIC: 双三次插值。
  • cv2.INTER_AREA: 区域插值(适合缩小图像)。
  1. borderMode: (可选)边界填充模式,默认为 cv2.BORDER_CONSTANT。常见选项:
  • cv2.BORDER_CONSTANT: 用固定值填充边界。
  • cv2.BORDER_REPLICATE: 复制边界像素。
  • cv2.BORDER_REFLECT: 反射边界像素。
  1. borderValue: (可选)当 borderMode=cv2.BORDER_CONSTANT 时,用于填充边界的值,默认为 0(黑色)。

返回值
返回变换后的图像。

插值方法

像插值算法是为了解决图像缩放或者旋转等操作时,由于像素之间的间隔不一致而导致的信息丢失和图像质量下降的问题。当我们对图像进行缩放或旋转等操作时,需要在新的像素位置上计算出对应的像素值,而插值算法的作用就是根据已知的像素值来推测未知位置的像素值。
图形仿射变换插值方法主要用于在变换过程中平滑处理像素或顶点的位置变化。常见的插值方法包括最近邻插值、双线性插值和双三次插值,它们的主要区别如下:

  1. 最近邻插值(Nearest Neighbor Interpolation)
    • 原理:选择离目标点最近的像素值。
    • 优点:计算简单,速度快。
    • 缺点:图像质量较低,容易出现锯齿。
    • 适用场景:对实时性要求高、图像质量要求不高的场景。

  2. 双线性插值(Bilinear Interpolation)
    • 原理:利用目标点周围四个最近像素,通过线性插值计算新像素值。
    • 优点:图像质量较好,计算适中。
    • 缺点:可能导致图像模糊。
    • 适用场景:图像质量要求较高、计算资源有限的场景。

  3. 双三次插值(Bicubic Interpolation)
    • 原理:利用目标点周围16个像素,通过三次多项式插值计算新像素值。
    • 优点:图像质量高,细节保留较好。
    • 缺点:计算复杂,速度较慢。
    • 适用场景:对图像质量要求极高的场景,如专业图像处理。

  4. Lanczos插值
    • 原理:使用Lanczos窗口函数进行插值,考虑更多周围像素。
    • 优点:图像质量非常高,细节和边缘保持较好。
    • 缺点:计算复杂,速度慢。
    • 适用场景:高质量图像缩放和变换。

总结
• 最近邻插值:速度快,质量低。
• 双线性插值:质量较好,计算适中。
• 双三次插值:质量高,计算复杂。
• Lanczos插值:质量最高,计算最复杂。

边界填充

边界复制(cv2.BORDER_REPLICATE)

边界反射(cv2.BORDER_REFLECT)

边界反射101(cv2.BORDER_REFLECT_101)

常数填充(cv2.BORDER_CONSTANT)

外包装(cv2.BORDER_WRAP)

透视变换

图像的透视变换(Perspective Transformation)是一种将图像从一个视角投影到另一个视角的几何变换。与仿射变换(Affine Transformation)不同,透视变换可以处理更复杂的几何变形,例如将倾斜的图像校正为正面视角,或将图像投影到某个平面上。

透视变换的特点

  1. 非线性变换:
    透视变换是非线性的,可以处理图像的透视效果(近大远小)。
    仿射变换是线性变换,只能处理旋转、平移、缩放和剪切。

  2. 保持直线性:
    透视变换后,图像中的直线仍然是直线,但直线的角度和长度可能会发生变化。

  3. 应用场景:
    图像校正(如文档校正、车牌校正)。
    虚拟视角变换(如将图像投影到某个平面上)。
    3D 视觉效果(如将 2D 图像映射到 3D 空间)。

OpenCV 提供了 cv2.getPerspectiveTransform 和 cv2.warpPerspective 函数来实现透视变换。

透视变换矩阵getPerspectiveTransform

1
cv2.getPerspectiveTransform(src, dst)

• src: 源图像中的 4 个点的坐标,形状为 (4, 2),数据类型为 float32。
• dst: 目标图像中对应的 4 个点的坐标,形状为 (4, 2),数据类型为 float32。
• 返回值: 一个 3x3 的透视变换矩阵,数据类型为 float32

透视变换warpPerspective

1
cv2.warpPerspective(src, M, dsize, dst=None, flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=0)

• src: 输入图像。
• M: 3x3 的透视变换矩阵。
• dsize: 输出图像的尺寸,格式为 (width, height)。
• flags: 插值方法,默认为 cv2.INTER_LINEAR。
• borderMode: 边界填充模式,默认为 cv2.BORDER_CONSTANT。
• borderValue: 边界填充值,默认为 0(黑色)。

滤波

低通滤波

二维卷积filter2D

通过自定义卷积核,可以实现各种低通滤波效果。
是 OpenCV 中用于对图像进行二维卷积操作的函数。它可以对图像应用自定义的卷积核(Kernel),从而实现各种图像处理效果,如模糊、锐化、边缘检测等

1
cv2.filter2D(**src, ddepth, kernel,** anchor=None, delta=None, borderType=None)

参数说明

  1. src: 输入图像,可以是单通道或多通道图像。
  2. ddepth: 输出图像的深度(数据类型)。通常设置为 -1,表示输出图像与输入图像具有相同的深度。
  3. kernel: 卷积核(滤波器),是一个二维数组(NumPy 数组)。
  4. anchor: (可选)卷积核的锚点,默认为 (-1, -1),表示锚点位于卷积核的中心。
  5. delta: (可选)在卷积操作后添加到每个像素值的常数,默认为 0。
  6. borderType: (可选)边界填充模式,默认为 cv2.BORDER_DEFAULT。常见的边界填充模式包括:
    cv2.BORDER_CONSTANT: 用固定值填充边界。
    cv2.BORDER_REPLICATE: 复制边界像素。
    cv2.BORDER_REFLECT: 反射边界像素。

返回值 返回卷积操作后的图像。

均值滤波cv2.blur

均值滤波是一种最简单的滤波处理,它取的是卷积核区域内元素的均值。
比如有一张44的图片,现在使用一个33的卷积核进行均值滤波,也就是卷积核对图片进行卷积,为了确保卷积核的中心能够对准边界的像素点进行滤波操作,对于边界的像素点,则会进行边界填充。在OpenCV中,默认的是使用BORDER_REFLECT_101的方式进行填充。

1
cv2.blur(src, ksize[,anchor[, borderType]])
1
2
3
4
• src:输入图像,可以是多通道图像。
• ksize:模糊核的大小。它是一个元组,表示核的宽度和高度,比如 (3, 3) 或 (5, 5)。核的大小应该是正奇数,且宽度和高度可以相同也可以不同。核越大,模糊效果越明显。
• anchor:锚点(可选)。它表示核的中心点位置,通常默认为 (-1, -1),意味着核的中心位于当前像素点。对于大多数情况,这个参数不需要修改。
• borderType:边界填充类型(可选)。这个参数用于指定边界外像素的外推方法,比如 cv2.BORDER_DEFAULT、cv2.BORDER_REFLECT 等。在大多数情况下,默认值就足够了。
方框滤波 cv2.boxFilter
1
cv2.boxFilter(src, ddepth, ksize, anchor=None, normalize=None, borderType=None)
1
2
3
4
5
6
7
8
9
10
11
12
13
参数说明
1. src: 输入图像,可以是单通道或多通道图像。
2. ddepth: 输出图像的深度(数据类型)。通常设置为 -1,表示输出图像与输入图像具有相同的深度。
3. ksize: 滤波器的大小,格式为 (width, height)。例如,(5, 5) 表示一个 5x5 的滤波器。
4. anchor: (可选)滤波器的锚点,默认为 (-1, -1),表示锚点位于滤波器的中心。
5. normalize: (可选)是否对滤波器进行归一化。默认为 True,表示对滤波器进行归一化(即取平均值)。如果设置为 False,则直接对邻域像素求和。
6. borderType: (可选)边界填充模式,默认为 cv2.BORDER_DEFAULT。常见的边界填充模式包括:
cv2.BORDER_CONSTANT: 用固定值填充边界。
cv2.BORDER_REPLICATE: 复制边界像素。
cv2.BORDER_REFLECT: 反射边界像素。

返回值
• 返回滤波后的图像。

normalize=True等同于均值滤波

高斯滤波 cv2.GaussianBlur

前面两种滤波方式,卷积核内的每个值都一样,也就是说图像区域中每个像素的权重也就一样。高斯滤波的卷积核权重并不相同:中间像素点权重最高,越远离中心的像素权重越小。
cv2.GaussianBlur 是 OpenCV 库中的一个函数,用于对图像进行高斯模糊处理。高斯模糊是一种图像平滑技术,它通过与高斯函数核进行卷积来减少图像中的噪声和细节,使得图像变得更加平滑。

1
cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
1
2
3
4
5
6
7
8
9
• src:输入图像,可以是多通道图像。
• ksize:高斯核的大小。它应该是一个正奇数,比如 (3, 3) 或 (5, 5)。这个值决定了模糊的程度,核越大,模糊效果越明显。
• sigmaX:高斯核函数在 X 方向的标准偏差。这个参数控制了模糊的程度,值越大,模糊效果越强。
• dst:输出图像(可选)。如果指定了这个参数,函数将把结果写入这个图像中,而不是创建一个新的图像。
• sigmaY:高斯核函数在 Y 方向的标准偏差(可选)。如果这个值为 0,那么函数会根据 sigmaX 的值来计算 Y 方向的标准偏差。如果 sigmaY 不为 0,那么它将独立地控制 Y 方向的模糊程度。
• borderType:边界填充类型(可选)。这个参数用于指定边界外像素的外推方法,例如 cv2.BORDER_DEFAULT、cv2.BORDER_REFLECT 等。

‌返回值‌:
函数返回的是模糊处理后的图像。
中值滤波 cv2.medianBlur

中值又叫中位数,是所有数排序后取中间的值。中值滤波没有核值,而是在原图中从左上角开始,将卷积核区域内的像素值进行排序,并选取中值作为卷积核的中点的像素值,其过程如下所示:
中值滤波就是用区域内的中值来代替本像素值,所以那种孤立的斑点,如0或255很容易消除掉,适用于去除椒盐噪声和斑点噪声。中值是一种非线性操作,效率相比前面几种线性滤波要慢。

双边滤波 cv2.bilateralFilter

模糊操作基本都会损失掉图像细节信息,尤其前面介绍的线性滤波器,图像的边缘信息很难保留下来。然而,边缘(edge)信息是图像中很重要的一个特征,所以这才有了双边滤波。
双边滤波是一种非线性的、边缘保持的、降噪的滤波器,它能够在平滑图像的同时保留边缘细节。与高斯滤波等线性滤波器不同,双边滤波同时考虑了空间距离和像素值之间的差异,因此能够在降噪的同时更好地保留图像的边缘信息。

1
cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])
1
2
3
4
5
6
7
8
9
• src:输入图像,可以是多通道图像。
• d:在滤波过程中一个像素邻域的直径。如果这个值是负数,那么它会被计算为从 sigmaSpace 推导出来的值。
• sigmaColor:颜色空间滤波器的 sigma 值。这个参数决定了多少邻域内的像素会被考虑在内,基于它们的颜色相似度。一个较大的值意味着更宽的色彩范围会被认为相似,并且参与到滤波过程中。
• sigmaSpace:坐标空间滤波器的 sigma 值。这个参数决定了多少邻域内的像素会被考虑在内,基于它们的空间位置。一个较大的值意味着更远的像素会被考虑进来进行滤波。
• dst:输出图像(可选)。如果指定了这个参数,函数将把结果写入这个图像中,而不是创建一个新的图像。
• borderType:边界填充类型(可选)。这个参数用于指定在处理边界像素时应该采用哪种边界模式,比如 cv2.BORDER_DEFAULT。

‌返回值‌:
函数返回的是双边滤波处理后的图像。

高通滤波

Sobel算子

每次只能求一个方向的边缘。要么对dx求导计算竖边;要么对dy求导计算横边
cv2.Sobel 是 OpenCV 库中的一个函数,用于计算图像的一阶导数,即图像的梯度。这个函数常用于边缘检测,因为边缘通常对应于图像中灰度值变化最快的地方,也就是梯度最大的地方。Sobel 算子结合了高斯平滑和微分运算,因此它在一定程度上能够抵抗噪声。

1
cv2.Sobel(src, ddepth, dx, dy, ksize=3[, scale=1, delta=0, borderType= BORDER_DEFAULT)
1
2
3
4
5
6
7
8
9
10
11
• src:输入图像,它可以是灰度图像或彩色图像
• ddepth:输出图像的所需深度。当参数值为 -1 时,输出图像与输入图像具有相同的深度。为了避免梯度值溢出,通常选择更深的数据类型,如 cv2.CV_64F。
• dx:x 方向上的导数阶数,求竖着的边。值0表示不计算 x 方向的导数、1计算一阶导数或2计算二阶导数。
• dy:y 方向上的导数阶数,求横着的边。与 dx 类似,这个值也是 0、1 或 2。
• ksize:Sobel 核的大小,它必须是 1、3、5、7 或 9 中的一个值。核的大小影响了平滑效果和梯度的计算。
• scale:计算梯度时的缩放因子,默认值是 1。它用于控制结果的缩放程度。
• delta:在将计算结果存储到目标图像之前,可选地将其加上一个值。这个参数在默认情况下是 0。
• borderType:边界填充类型(可选)。这个参数用于指定在处理边界像素时应该采用哪种边界模式,比如 cv2.BORDER_DEFAULT。

‌返回值‌:
• 函数返回的是计算梯度后的图像,它是一个与输入图像大小相同的灰度图像(即使输入是彩色图像,输出也是灰度图像,因为梯度是分别对每个通道计算的,然后可能会合并,但通常只关心灰度梯度)。
Laplacian算子

cv2.Laplacian 是 OpenCV 库中的一个函数,用于计算图像的拉普拉斯算子(Laplacian Operator)。拉普拉斯算子是一种二阶微分算子,常用于图像的边缘检测,因为它能够突出图像中的强度变化,特别是边缘部分。在图像处理中,拉普拉斯算子通常用于检测图像中的区域之间的边界。
可以同时求两个方向的边缘,对噪音敏感,需要先去噪。

1
cv2.Laplacian(src, ddepth, ksize=1, scale=1, delta=0, borderType=BORDER_DEFAULT)
1
2
3
4
5
6
7
8
• src:输入图像,它应该是灰度图像。
• ddepth:输出图像的所需深度。当参数值为 -1 时,输出图像与输入图像具有相同的深度。
• ksize:滤波器的大小,它必须是正奇数。默认值是 1,表示不进行额外的平滑处理,直接使用拉普拉斯核。如果你想在进行拉普拉斯变换之前对图像进行平滑处理,可以设置一个更大的值。
• scale:计算拉普拉斯算子时的缩放因子,默认值是 1。它用于控制结果的缩放程度。
• delta:在将计算结果存储到目标图像之前,可选地将其加上一个值。这个参数在默认情况下是 0。
• borderType:边界填充类型(可选)。这个参数用于指定在处理边界像素时应该采用哪种边界模式,比如 cv2.BORDER_DEFAULT。
‌返回值‌:
• 函数返回的是计算拉普拉斯算子后的图像,它通常是一个与输入图像大小相同的灰度图像,但突出了边缘部分。

滤波FAQ

低通滤波是一种信号处理技术,用于去除高频成分,保留低频成分。在图像处理和信号处理中,低通滤波常用于平滑图像、降噪或模糊处理。

低通滤波与高通滤波:
低通滤波可以去除噪音或平滑图像:
线性:均值滤波、方框滤波、高斯滤波、
非线性:中值滤波、双边滤波
高通滤波可以帮助查找图像的边缘。
每次只能求一个方向的边缘。要么对dx求导计算竖边;要么对dy求导计算横边

1.高斯滤波代码会写
2.在不知道用什么滤波器好的时候,优先高斯滤波,然后均值滤波。
斑点和椒盐噪声优先使用中值滤波。
要去除噪点的同时尽可能保留更多的边缘信息,使用双边滤波。

线性滤波方式:均值滤波、方框滤波(normalize=True等同于均值滤波)、高斯滤波(速度相对快)。
非线性滤波方式:中值滤波、双边滤波(速度相对慢)。

sobel只考虑水平或者垂直一个方向的梯度
Laplacian滤波核就是,计算上下左右的和卷积核中心点的梯度

Canny边缘检测

1
cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])
1
2
3
4
5
6
-   image:输入图像,必须是**灰度图像**。
- threshold1:第一个阈值(低阈值)。
- threshold2:第二个阈值(高阈值)。设置的值小保留边缘多,值大保留边缘少。
- edges(可选):输出边缘图,通常不需要指定,函数会返回一个新的边缘图。
- apertureSize:Sobel算子的大小(可选),默认值是3。
- L2gradient:一个布尔值,指示是否使用L2范数进行梯度计算(可选),默认值是False。

Canny算法的步骤:

  • 高斯模糊去噪
  • 计算梯度强度和方向
  • 非极大值抑制
  • 双阈值检测和边缘连接

轮廓

寻找轮廓cv2.findContours()

寻找轮廓需要将图像做一个二值化处理,并且根据图像的不同选择不同的二值化方法来将图像中要绘制轮廓的部分置为白色,其余部分置为黑色。也就是说,我们需要对原始的图像进行灰度化、二值化的处理,令目标区域显示为白色,其他区域显示为黑色。
cv2.findContours 是 OpenCV 库中用于检测图像轮廓的函数。它通常用于图像处理中的对象检测、形状分析等任务。该函数会返回图像中所有检测到的轮廓。

1
contours,hierarchy = cv2.findContours(image,mode,method)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
**参数说明**

1. **image**: 输入图像,通常是二值化后的图像(例如经过阈值处理或边缘检测后的图像)。注意,cv2.findContours 会直接修改输入图像,因此如果需要保留原图,请先复制一份。
2. **mode**: 轮廓检索模式,决定如何提取轮廓。常用的模式有:
- **cv2.RETR_EXTERNAL:** 只检测最外层的轮廓。
- cv2.RETR_LIST: 检测所有轮廓,但不建立轮廓之间的层级关系。
- cv2.RETR_TREE: 检测所有轮廓,并建立完整的轮廓层级关系。
3. **method**: 轮廓近似方法,决定如何存储轮廓点。常用的方法有:
- cv2.CHAIN_APPROX_NONE: 存储所有轮廓点。
- **cv2.CHAIN_APPROX_SIMPLE:** 压缩水平、垂直和对角方向的轮廓点,只保留端点。

**返回值**
1. **contours**: 检测到的轮廓列表。每个轮廓是一个包含轮廓点的数组。
2. **hierarchy**: 轮廓的层级信息,表示轮廓之间的关系(例如父子关系)。
绘制轮廓cv2.drawContours

cv2.drawContours 是 OpenCV 库中的一个函数,用于在图像上绘制轮廓。这个函数通常用于图像处理中,特别是在进行轮廓检测、物体检测等任务时,用于将检测到的轮廓可视化。

1
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
1
2
3
4
5
6
7
8
9
10
**参数说明**
1. **image**: 输入图像,轮廓将绘制在此图像上。
2. **contours**: 轮廓**列表**,通常由 cv2.findContours 返回。
3. **contourIdx**: 指定要绘制的轮廓索引。如果为负数(例如 -1),则绘制所有轮廓。
4. **color**: 轮廓的颜色,格式为 (B, G, R)。例如,(0, 255, 0) 表示绿色。
5. **thickness** (可选): 轮廓线的宽度。如果为负数(例如 -1),则填充轮廓内部。
6. **lineType** (可选): 线条类型,默认为 cv2.LINE_8。其他选项包括 cv2.LINE_4 和 cv2.LINE_AA(抗锯齿)。
7. **hierarchy** (可选): 轮廓的层级信息,通常由 cv2.findContours 返回。如果不需要绘制特定层级的轮廓,可以忽略。
8. **maxLevel** (可选): 绘制轮廓的最大层级。默认为 0,表示只绘制指定的轮廓。
9. **offset** (可选): 轮廓点的偏移量,通常不需要设置。

凸包

通俗的讲,凸包其实就是将一张图片中物体的最外层的点连接起来构成的凸多边形,它能包含物体中所有的内容。

凸包特征检测cv2.convexHull

cv2.convexHull 是 OpenCV 中用于计算轮廓的凸包的函数。凸包是包含轮廓所有点的最小凸多边形。它在形状分析、对象检测和手势识别等任务中非常有用。

1
hull = cv2.convexHull(points[,clockwise[, returnPoints]]])
1
2
3
4
5
6
7
-   points:输入的点集,通常是一个二维的 Numpy 数组,其中每一行代表一个点的坐标(x, y)。
- clockwise:布尔值,指示凸包的顶点是否按顺时针方向排列。默认值是 False,表示按逆时针方向排列。
- returnPoints:布尔值,指示函数是否应返回凸包顶点的坐标。如果为 True(默认值),则函数返回凸包顶点的坐标;如果为 False,则函数返回原始点集中凸包顶点的索引。

返回值:
- 当 returnPoints 为 True 时,返回凸包顶点的坐标。
- 当 returnPoints 为 False 时,返回原始点集中凸包顶点的索引。
绘制凸包多边形cv2.polylines

是 OpenCV 库中的一个函数,用于在图像上绘制多边形线条。这个函数非常适用于在图像上标记或突出显示特定的形状或区域,比如通过轮廓或凸包找到的形状。

1
img = cv2.polylines(img, pts, isClosed, color, thickness=1, lineType= LINE_8, shift=0)
1
2
3
4
5
6
7
8
9
10
-   img:输入/输出参数,这是要绘制多边形的图像。
- pts:多边形的顶点坐标,通常是一个二维的 Numpy 数组,其中每一行代表一个顶点的坐标(x, y)。对于绘制多个多边形,可以提供一个包含多个多边形顶点集的列表。
- isClosed:布尔值,指示多边形是否应该闭合。如果设置为 True,则多边形的最后一个顶点将与第一个顶点连接,形成一个闭合的多边形。
- color:多边形的颜色,通常是一个 BGR(蓝、绿、红)颜色元组,例如 (255, 0, 0) 代表蓝色。
- thickness:(可选)线条的厚度。默认值是 1。如果你想要更粗的线条,可以增加这个值。
- lineType:(可选)线条的类型。默认值是 cv2.LINE_8,表示 8-连通线。其他选项包括 cv2.LINE_4(4-连通线)和 cv2.LINE_AA(抗锯齿线),后者通常用于获得更平滑的线条效果。
- shift:(可选)点坐标的小数位数。默认值是 0。这个参数通常用于绘制非常精确的图形时。

返回值:
- img:这是输入图像的修改版本,现在包含了绘制的多边形线条。

轮廓特征检测-外接矩形

cv2.boundingRect是 OpenCV 库中的一个函数,用于计算并返回能够完全包含输入轮廓的最小矩形区域的坐标。这个矩形区域是水平的,并且其边与图像坐标轴平行。该函数通常用于轮廓检测、物体检测等任务中,以便快速获取物体的大致位置和尺寸。

1
x, y, w, h = cv2.boundingRect(contour)
1
2
3
4
5
6
**参数说明**
- **contour**: 输入的轮廓点集,通常是由 cv2.findContours 返回的轮廓。

**返回值**
- **x, y**: 矩形左上角的坐标。
- **w, h**: 矩形的宽度和高度。

轮廓特征检测-最小外接矩形

获取最小外接矩形cv2.minAreaRect

cv2.minAreaRect是 OpenCV 库中的一个函数,用于计算并返回能够完全包含输入轮廓的最小面积矩形(通常是旋转矩形)的坐标。与 cv2.boundingRect 不同,cv2.minAreaRect 返回的矩形是可能旋转的,以更好地贴合轮廓的形状,从而提供更紧凑的包围。

1
rotated_rect = cv2.minAreaRect(points)
1
2
3
4
5
6
7
8
**参数说明**
- **points**: 输入的点集,通常是一个轮廓(由 cv2.findContours 返回的轮廓点)。

**返回值**
- **rotated_rect**: 返回一个旋转矩形,格式为 ((cx, cy), (width, height), angle),其中:
- (cx, cy): 矩形中心点坐标。
- (width, height): 矩形的宽度和高度。
- angle: 矩形的旋转角度(范围:[-90, 0])。
获取旋转矩形的四个点坐标cv2.boxPoints

cv2.boxPoints 是 OpenCV 中用于将旋转矩形(cv2.minAreaRect 返回的结果)转换为四个顶点坐标的函数。旋转矩形由中心点、宽度、高度和旋转角度定义,而 cv2.boxPoints 可以将其转换为四个顶点的坐标,方便绘制或进一步处理。

1
points = cv2.boxPoints(box)
1
2
3
4
5
**参数说明**
- **box**: 旋转矩形,通常由 cv2.minAreaRect 返回,格式为 ((cx, cy), (width, height), angle)。

**返回值**
- **points**: 返回旋转矩形的四个顶点坐标,形状为 (4, 2) 的 NumPy 数组。

轮廓特征检测-最小外接圆cv2.minEnclosingCircle

cv2.minEnclosingCircle是 OpenCV 库中的一个函数,用于找到能够完全包含输入轮廓或点集的最小外接圆。这个函数对于确定一组点的圆形边界非常有用,特别是在进行物体检测、形状分析或聚类分析时。

1
cv2.minEnclosingCircle(points)
1
2
3
4
5
6
7
-   **points**‌:这是一个二维点集,通常是一个轮廓或一组散点,表示为一个形状为 [-1, 1, 2] 的 NumPy 数组。每一行代表一个点,点的坐标以 (x, y) 的形式给出。
返回值

该函数返回一个包含三个元素的元组 (center, radius, _),其中:
- ‌**center**‌:是一个包含圆心坐标的元组 (x, y)。
- ‌**radius**‌:是外接圆的半径。
- 第三个返回值是一个可选的布尔值,表示操作是否成功,但在 OpenCV 的 Python 接口中通常不使用这个返回值。

模板匹配

模板匹配(Template Matching) 是一种在图像中查找与给定模板图像最相似区域的技术。它的核心思想是通过滑动模板图像在输入图像上进行比较,找到与模板最匹配的位置。模板匹配广泛应用于目标检测、图像识别、物体跟踪等计算机视觉任务。

cv2.matchTemplate 是 OpenCV 中用于模板匹配的函数。它通过滑动模板图像在输入图像上进行比较,找到最匹配的位置。模板匹配常用于目标检测、图像识别等任务。

1
result = cv2.matchTemplate(image, templ, method, mask=None)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
**参数说明**
1. **image**: 输入图像,必须是 8 位或 32 位浮点型。
2. **templ**: 模板图像,大小不能超过输入图像,且数据类型与输入图像相同。
3. **method**: 匹配方法,指定如何计算匹配程度。常用的方法有:
- cv2.TM_SQDIFF: 平方差匹配法, 值越小匹配越好。
- cv2.TM_SQDIFF_NORMED: 归一化平方差匹配法,值越小匹配越好。
- cv2.TM_CCORR: 相关匹配法,值越大匹配越好。
- cv2.TM_CCORR_NORMED: 归一化相关匹配法,值越大匹配越好。
- cv2.TM_CCOEFF: 相关系数匹配法,值越大匹配越好。
- cv2.TM_CCOEFF_NORMED: 归一化相关系数匹配法,值越大匹配越好。
4. **mask** (可选): 掩码图像,大小与模板图像相同,用于指定模板图像的哪些部分参与匹配。

**返回值**
- **result**: 匹配结果矩阵,每个像素值表示模板与输入图像对应位置的匹配程度。
- 数组的大小为 (W*H),其中
W = image.cols - templ.cols + 1,
H = image.rows - templ.rows + 1

cv2.minMaxLoc 是 OpenCV 中用于查找数组(通常是图像或矩阵)中最小值和最大值及其位置的函数。它常用于模板匹配、图像分析等任务中,用于定位最佳匹配位置或极值点

1
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(src[, mask])
1
2
3
4
5
6
7
8
9
**参数说明**
1. **src**: 输入数组(通常是单通道图像或矩阵)。
2. **mask** (可选): 掩码图像,用于指定只处理掩码非零的区域。

**返回值**
1. **min_val**: 数组中的最小值。
2. **max_val**: 数组中的最大值。
3. **min_loc**: 最小值的位置,格式为 (x, y)。
4. **max_loc**: 最大值的位置,格式为 (x, y)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import cv2
import numpy as np

image = cv2.imread('./img/picture_mb.png')
image_tem = cv2.imread("./img/muban.png")
cv2.imshow('image', image)

# 获取模板图的高和宽,方便后面进行绘图
h, w = image_tem.shape[:2]

# 进行模板匹配的操作。res中存储模板在原图像上每个位置匹配的结果
# 数组res的大小为 (WxH),其中W = image.cols - templ.cols + 1,H = image.rows - templ.rows + 1
res = cv2.matchTemplate(image, image_tem, cv2.TM_CCOEFF_NORMED)
# print("image.shape", image.shape) # image.shape (321, 346, 3)
# print("image_tem.shape", image_tem.shape) # image_tem.shape (27, 16, 3)
# print("res.shape", res.shape) # res.shape (295, 331)
# print(res)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# 对返回的结果做进一步处理.值越大要求匹配度越高,精准度越高。值越小可能匹配度相似度要求越低
threshold = 0.57
# 对某数组的数据进行判断,如果满足条件,就返回其对应值的坐标索引
# 这里要注意的是,他返回的是行和列的坐标。
# 对应到Opencv里,就是某一个点的y和x的坐标
location = np.where(res > threshold)

# 5. 对得到的点的坐标进行翻转处理,并再原图中框出来
# OpenCV期望的格式是(x, y),即先列后行。但是np.where返回的是(行, 列)的格式,即(y, x)。
# 为了将这个格式转换为OpenCV期望的格式,我们需要对索引进行翻转。这是取location[::-1]的原因
for left_top in zip(*location[::-1]):
right_bottom = (left_top[0] + w, left_top[1] + h)
cv2.rectangle(image, left_top, right_bottom, (0, 0, 255))
cv2.imshow('image1', image)
cv2.waitKey(0)

霍夫变换

霍夫变换是一种从图像中检测几何形状(如直线、圆等)的技术。对于直线检测,霍夫变换将图像空间中的点转换到参数空间(霍夫空间),通过在参数空间中寻找交点来确定直线。

霍夫变换的步骤

  1. 边缘检测
  • 首先对图像进行边缘检测(如使用 Canny 边缘检测),得到二值边缘图像。
  1. 参数空间映射
  • 将图像空间中的边缘点映射到参数空间。
  1. 累加器统计
  • 在参数空间中使用累加器统计交点。
  1. 峰值检测
  • 找到累加器中的峰值,这些峰值对应图像中的形状。

霍夫直线cv2.HoughLinesP

cv2.HoughLinesP 是 OpenCV 中用于检测图像中线段(有限长度的直线)的函数。它基于 概率霍夫变换(Probabilistic Hough Transform),是 cv2.HoughLines 的改进版本。相比于 cv2.HoughLines,cv2.HoughLinesP 直接返回线段的端点坐标,计算效率更高,适合检测有限长度的线段。

1
lines = cv2.HoughLinesP(image, rho, theta, threshold, minLineLength, maxLineGap)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
参数说明:
1. image:
输入图像,必须是单通道的二值图像(如边缘检测的结果)。
通常使用 cv2.Canny 等边缘检测算法处理后的图像。
2. rho:
霍夫空间中 ρ 的分辨率(以像素为单位)。
例如,常用值rho = 1 表示霍夫空间的 ρ 以 1 像素为单位递增。
3. theta:
霍夫空间中 θ 的分辨率(以弧度为单位)。
例如,常用值theta = np.pi/180 表示 θ 以 1 度为单位递增。
4. threshold:
累加器的阈值。
只有得票数(交点数量)超过该阈值的线段才会被检测到。
阈值越高,检测到的线段越少。
5. minLineLength:
线段的最小长度。小于此长度的线段会被忽略。
如果图像中有很多短线段,可以增加该值以过滤掉较短的线段。
6. maxLineGap:
线段之间的最大允许间隔。如果希望将接近的线段合并为一条直线,可以增加该值。
如果两条线段之间的间隔小于此值,它们会被合并为一条线段。
maxLineGap 只对 同一条直线上的线段 起作用。如果图像中的线段不在同一条直线上,maxLineGap 再大也不会将它们合并

返回值:
• lines:
返回检测到的线段的列表,每条线段用 (x1, y1, x2, y2) 表示。
(x1, y1) 和 (x2, y2) 是线段的两个端点坐标。

霍夫圆 cv2.HoughCircles

1
circles = cv2.HoughCircles(image, method, dp, minDist, param1=None, param2=None, minRadius=None, maxRadius=None)
1
2
3
4
5
6
7
8
9
10
11
12
参数说明:
- image:输入图像,应该是一个灰度图像(单通道)。
- method:检测圆形的方法。目前 OpenCV 只实现了 cv2.HOUGH_GRADIENT,它是基于图像梯度的方法。
- dp:累加器分辨率的倒数。例如,对于 dp=1.5,累加器将比图像小 1.5 倍。它决定了检测到的圆形的精度。
- minDist:检测到的圆之间的最小距离。如果两个圆之间的距离小于这个值,那么较小的圆将被忽略。
- param1:Canny 边缘检测器的高阈值(低阈值是高阈值的一半)。这是一个很重要的参数,因为它决定了边缘检测的准确性,进而影响圆形检测的结果。
- param2:累加器阈值。这个值越小,能够检测到的圆形就越多。它表示在累加器中累积的圆形候选点的数量阈值,只有累积点数超过这个阈值的圆形才会被返回。
- minRadius:圆形半径的最小值。
- maxRadius:圆形半径的最大值。

返回值:
- circles:检测到的圆形的参数。如果未检测到圆形,则返回 None。否则,它返回一个三维数组,其中每一行表示一个检测到的圆形的参数:(x, y, radius),其中 (x, y) 是圆形的中心坐标,radius 是圆形的半径。

图像亮度变换

np.clip 是 NumPy 库中的一个函数,用于将数组中的元素限制在指定的范围内。它会将数组中小于下限的值替换为下限,大于上限的值替换为上限,而介于两者之间的值保持不变。

1
np.clip(array, min, max, out=None)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
参数说明:
1. array:
输入的数组(可以是 NumPy 数组或类似数组的对象)。
2. min:
下限值。所有小于 min 的元素会被替换为 min。
如果不需要下限,可以设置为 None。
3. max:
上限值。所有大于 max 的元素会被替换为 max。
如果不需要上限,可以设置为 None。
4. out (可选):
用于存储结果的输出数组。如果不提供,会返回一个新的数组。

返回值:
• 返回一个裁剪后的数组,元素值被限制在 [min, max] 范围内。

特征检测

特征检测是计算机视觉中的一种技术,用于从图像或视频中提取显著且具有代表性的信息,这些信息通常用于后续的任务,如目标识别、图像匹配和运动跟踪。

角点检测

角点是图像中亮度变化剧烈或各个方向上梯度变化明显的点。与边缘不同,角点在多个方向上都有明显的梯度变化。
角点检测是计算机视觉中的一种技术,用于识别图像中具有显著变化的点,通常位于两条或多条边缘的交汇处。这些点被称为“角点”,它们在图像中具有独特的局部特征,适合用于图像匹配、目标识别和运动跟踪等任务。

Harris角点检测

cv2.cornerHarris 是 OpenCV 库中用于实现 Harris****角点检测 的函数。Harris角点检测是一种经典的角点检测算法,用于识别图像中的角点(即两条边缘交汇的点)。这些角点通常具有较高的图像梯度变化,适合用于图像匹配、目标跟踪等任务。

Shi-Tomasi角点检测

Shi-Tomasi角点检测是Harris角点检测的改进版本,在Harris算法的基础上进行了优化,可以不用设置k值,能够更准确地检测角点,尤其是在需要高质量角点的场景中(如目标跟踪、图像匹配等)。Shi-Tomasi角点检测的核心思想是通过最小特征值来判断角点。

SIFT关键点检测

SIFT(Scale-Invariant Feature Transform,尺度不变特征变换)是一种经典的图像特征检测和描述算法,SIFT算法能够在不同尺度、旋转和光照条件下检测图像中的关键点,并生成具有高区分度的特征描述符。由于其鲁棒性和准确性,SIFT被广泛应用于图像匹配、目标识别、3D重建等领域。

常用操作

羽化边缘

  1. 建立边缘模糊遮罩图片
  2. 根据遮罩黑白比例,合成主角与背景

使用 np.zeros 建立黑色画布后,在画布中心加入白色的圆形,接着进行高斯模糊,就完成一张边缘模糊的遮罩图片。

1
2
3
4
5
6
7
8
9
10
import cv2
import numpy as np

mask = np.zeros((300,300,3), dtype='uint8') # 建立 300x300 的黑色畫布
cv2.circle(mask,(150,150),100,(255,255,255),-1) # 在畫布上中心點加入一個半徑 100 的白色圆形
mask = cv2.GaussianBlur(mask, (35, 35), 0) # 進行高斯模糊

cv2.imshow('oxxostudio', mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

输入图片说明

因为 OpenCV 的遮罩方法(参考 “影像遮罩”)所产生的遮罩 “不具有半透明” 的功能,因此如果要实现边缘渐层半透明的边缘羽化效果,必须根据黑色白色的比例进行主角与背景的混合。下面的代码执行后,会读取一张和遮罩同样尺寸的图片,以及生成同尺寸的一张白色背景,根据遮罩的黑白比例,将白色区域套用到图片,将黑色区域套用到背景,就能产生边缘羽化的图片效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import cv2
import numpy as np

mask = np.zeros((300,300,3), dtype='uint8')
cv2.circle(mask,(150,150),100,(255,255,255),-1)
mask = cv2.GaussianBlur(mask, (35, 35), 0)
mask = mask / 255 # 除以 255,計算每個像素的黑白色彩在 255 中所佔的比例

img = cv2.imread('mona.jpg') # 開啟圖片
bg = np.zeros((300,300,3), dtype='uint8') # 產生一張黑色背景
bg = 255 - bg # 轉換成白色背景
img = img / 255 # 除以 255,計算每個像素的色彩在 255 中所佔的比例
bg = bg / 255 # 除以 255,計算每個像素的色彩在 255 中所佔的比例

out = bg * (1 - mask) + img * mask # 根據比例混合
out = (out * 255).astype('uint8') # 乘以 255 之後轉換成整數

cv2.imshow('oxxostudio',out)
cv2.waitKey(0)
cv2.destroyAllWindows()

输入图片说明

来自邊緣羽化效果 ( 邊緣模糊化 ) - OpenCV 教學 ( Python ) | STEAM 教育學習網

添加水印

  1. 从原始图片截取处要添加水印的位置roi

  2. 掩膜制作,让显示logo的位置为黑色0,其余地方为白色1

  3. 让roi和掩膜进行与操作得到img_tmp,logo的位置为黑色0

  4. 让img_tmp和logo进行加操作得到img_dst

  5. 将img_dst重新放回原始图片对应的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 导入OpenCV的库
import cv2

# 1. 读取原始图像和模板图
image_np = cv2.imread('./img/lena.png')
logo = cv2.imread('./img/logo.png')
logo = cv2.resize(logo, (80, 120))
# cv2.imshow('image_np', image_np)
# 获取logo图的大小
rows, cols = logo.shape[:2]
# 截取原始图像的ROI区域
roi = image_np[100:100+rows, 100:100+cols]
cv2.imshow('roi1', roi)
# 2. 对logo进行灰度化和二值化,制作成一张掩膜
logo_gray = cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(logo_gray, 127, 255, cv2.THRESH_BINARY_INV)
# 3. 进行与运算
image_and = cv2.bitwise_and(roi, roi, mask=mask)
# 4. 图像融合
dst = cv2.add(image_and, logo)
# 5. 将融合后的图像重新赋值到原始图像中
image_np[100:100+rows, 100:100+cols] = dst
# 6. 显示结果
cv2.imshow('logo', logo)
cv2.imshow('roi2', roi)
cv2.imshow('mask', mask)
cv2.imshow('image_and', image_and)
cv2.imshow('image_np1', image_np)
cv2.waitKey(0)

输入图片说明

马赛克

在浏览图片时,如果将小张的图片不断放大,就会看见图片的像素变大,成为一格格的马赛克。运用同样的原理,只要对图片使用 “两次 resize()” 的方式,就能快速实现马赛克的效果。

下面的程序一开始运用 img.shape 获取图片尺寸,接着使用 cv2.resize () 方法(interpolation=cv2.INTER_LINEAR)进行缩小,接着再度使用 cv2.resize () 方法搭配(interpolation=cv2.INTER_NEAREST)进行放大,就会出现马赛克效果。

1
2
3
4
5
6
7
8
9
10
11
import cv2
img = cv2.imread('mona.jpg')
size = img.shape # 取得原始圖片的資訊
level = 15 # 縮小比例 ( 可當作馬賽克的等級 )
h = int(size[0]/level) # 按照比例縮小後的高度 ( 使用 int 去除小數點 )
w = int(size[1]/level) # 按照比例縮小後的寬度 ( 使用 int 去除小數點 )
mosaic = cv2.resize(img, (w,h), interpolation=cv2.INTER_LINEAR) # 根據縮小尺寸縮小
mosaic = cv2.resize(mosaic, (size[1],size[0]), interpolation=cv2.INTER_NEAREST) # 放大到原本的大小
cv2.imshow('oxxostudio', mosaic)
cv2.waitKey(0) # 按下任意鍵停止
cv2.destroyAllWindows()
-------------本文结束感谢您的阅读-------------