opencv使用方法
一、基本方法使用(opencv)
1.图片裁切
1.1 实现逻辑
图像都可转为三维数组,只不过彩色图片的颜色通道有三个(BGR),
灰度为一个通道,也可以直接在读取图片时指定读取灰色图片cv2.IMREAD_GRAYSCALE
使用imread()方法打开的图片,打开的三维数组,最里面的[]代表某个像素点的颜色
在三维数组中,每一层列表代表图像的一行,每个元素代表该行中的一个像素。每个像素由三个数值组成,分别表示蓝、绿、红三个通道的强度值(BGR顺序)。
[
[[0,0,0], [1,1,1]] # 最里面的[B,G,R]
]
同时,三个通道BGR对应的下标为0,1,2
1.2 使用方法
- cv2.imread() # 打开图片 可以指定cv2.imread(cv2.IMREAD_GRAYSCALE)打开灰色图
- cv2.imshow() # 显示图像
- cv2.waitKey() # 等待键盘事件关闭图像窗口,0代表无限长时间
- cv2.destroyAllWindows() # 关闭已创建的窗口图像
1.3代码示例
import cv2
img = cv2.imread("../static/cat1.webp")
cat = img[0:500, 0:600]
cv2.imshow("cat", cat)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.颜色通道提取与合并
2.1 使用方法
- b, g, r = cv2.split(img) # 分离三个颜色通道
- red_img = img.copy() # 复制数组
- img.shape() # 返回图像形状(height, wideth, channels)
- cv2.merge((b,g,r)) # 合并颜色通道
2.2 代码示例
import cv2
img = cv2.imread("./cat1.webp")
b, g, r = cv2.split(img)
red_img = img.copy()
height = red_img.shape[0]
red_img[:height//2, :, 2] = 0 # 表示第三个颜色通道所有像素点
red_img[:, :, 1] = 0
3.边界填充
ps: 一个400400的图像,通过边缘反射或填充黑边方法将图片增大至500500
4.数值计算
4.1 使用方法
- img = cv2.imread() # 读取图片
- img2 = img + 10 # 相当于每个像素点的数值都加10
- img3 = img2 + img # 如果同一个像素点的数值大于255,那么就用img3 % 255,结果为余数
- img4 = cv2.add(img, img2) # 也是同像素点相加,不同于上方法数值大于255后取余,这个相加后的的结果也是0~255区间,大于255的也改为255
5.读取视频流
5.1 使用方法
5.2 代码实例
import cv2
# 读取视频
vc = cv2.VideoCapture('../static/test.mp4')
#检查是否打开正确
if vc.isOpened():
oepn,frame = vc.read()
else:
open = False
while open:
ret, frame = vc.read()
if frame is None:
break
if ret:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow("result", gray)
if cv2.waitKey(100) & 0xFF == 27:
break
vc.release()
cv2.destroyAllWindows()
2.图片形态学
2.1腐蚀操作
2.1.1 实现逻辑
先使用numpy得到一个正方形矩阵(腐蚀核),将这个正方形矩阵滑动输入图像,
将矩阵内的像素点值替换,实现腐蚀操作的基本思想是将每个像素点的值替换为该像素周围像素的最小值。这样,对于前景(白色)像素,其周围的黑色像素会一步一步地侵蚀前景区域,从而缩小前景对象的大小
ps: 将有价值的东西变得越来越少
2.1.2 函数方法介绍
- cv2.erode() 方法用于腐蚀操作。它的第一个参数是要进行腐蚀操作的图像,第二个参数是腐蚀核,也称为结构元素。结构元素是一个矩阵,它定义了要应用于输入图像的腐蚀算法。第三个参数是迭代次数,表示要重复应用腐蚀算法的次数。
- cv2.imshow() 方法用于显示图像。它需要两个参数:窗口名称和要显示的图像。
- cv2.waitKey() 方法用于等待键盘输入。它等待指定的毫秒数,并在此期间等待用户按下某个键。如果用户按下了某个键,则返回该键的 ASCII 码值。否则,返回 -1。
- cv2.destroyAllWindows() 方法用于销毁所有的窗口。
2.1.3 代码实例
import cv2
import numpy as np
dog = cv2.imread("./dog.png")
kernel = np.ones((3, 3), np.uint8)
erosion = cv2.erode(dog, kernel, iterations=3)
cv2.imshow("erosion", erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.2膨胀操作
ps: 膨胀操作是形态学处理中的一种常见操作,可用于去除小的噪点、
连接断开的边缘、拓宽图像中的线条等
2.2.1 函数方法介绍
- cv2.dilate(img, kernel, iterations) # 接收三个参数,输入图像(img)、膨胀核(kernel)和迭代次数(iterations)
2.2.2 代码实例
import cv2
import numpy as np
img = cv2.imread("../static/bai_yuan.png")
kernel = np.ones((50, 50), np.uint8)
erosion = cv2.dilate(img, kernel, iterations=1)
cv2.imshow("erosion", erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.3 开运算与闭运算
2.3.1 函数方法介绍
- 开运算:先腐蚀,后膨胀
- 闭运算:先膨胀,后腐蚀
- cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
- 运算操作
- cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
- src:输入图像。
- op:需要进行的形态学操作,可以是以下值之一:
- cv2.MORPH_ERODE:腐蚀操作。
- cv2.MORPH_DILATE:膨胀操作。
- cv2.MORPH_OPEN:开运算操作。
- cv2.MORPH_CLOSE:闭运算操作。
- cv2.MORPH_GRADIENT:形态学梯度操作。
- cv2.MORPH_TOPHAT:顶帽操作。
- cv2.MORPH_BLACKHAT:黑帽操作。
- kernel:用于元素的结构化元素。
- dst:输出图像。
- anchor:锚点位置,默认为(-1,-1)。
- iterations:操作的迭代次数。
- borderType:边界处理方式。
- borderValue:边界值。
2.3.2 代码实例
import numpy as np
import cv2
img = cv2.imread("../static/bai_yuan.png")
kernel = np.ones((100, 100), np.uint8)
erosion = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # 开运算
# erosion = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) # 闭运算
cv2.imshow("erosion", erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. 梯度计算
3.1 函数方法介绍
- 梯度=膨胀-腐蚀
- 最后得到图像轮廓,轮廓大小与腐蚀核有关
- cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
3.1.2 代码示例
import cv2
import numpy as np
img = cv2.imread("../static/bai_yuan.png")
kernel = np.ones((2, 2), np.uint8)
erosion = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
cv2.imshow("erosion", erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.2 礼帽与黑帽
3.2.1 函数方法讲解
- 礼帽与黑帽
- 礼帽 = 原始输入-开运算结果(保留能腐蚀掉的数据)
- cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
- 黑帽 = 闭运算结果-原始输入(保留有价值图像的轮廓)
- cv2.morphologyEx(img, cv2.MORPH_MORPH_BLACKHAT, kernel)
3.3 sobel算子
3.3.1 基本思想
-
Sobel算子是一种常用的图像边缘检测算子,它可以帮助我们找到图像中灰度变化最为剧烈的地方,从而实现边缘检测。Sobel算子通常用于处理灰度图像,其逻辑可以分为以下几个步骤:
- 原始图片 -> 图片灰度化 -> 计算水平和垂直方向的梯度 -> 计算梯度幅值和方向 -> 边缘检测
-
灰度化:首先将彩色图像转换为灰度图像,这样有利于后续的处理。灰度化可以通过简单的加权平均法或者其他复杂的方法来实现。
-
计算水平和垂直方向的梯度:Sobel算子包括两个3x3的卷积核,分别对图像进行水平和垂直方向上的卷积操作。具体来说,对于水平边缘,Sobel算子使用的卷积核如下:
-1 0 1
-2 0 2
-1 0 1
对于垂直边缘,Sobel算子使用的卷积核如下:
-1 -2 -1
0 0 0
1 2 1
分别将这两个卷积核应用于灰度图像,可以得到水平方向和垂直方向上的梯度值。
- 计算梯度幅值和方向:根据水平和垂直方向上的梯度值,可以计算每个像素点处的梯度幅值和梯度方向,一般使用以下公式:
gradient_magnitude = sqrt((horizontal_gradient)^2 + (vertical_gradient)^2)
gradient_direction = arctan(vertical_gradient / horizontal_gradient)
其中,sqrt表示平方根,arctan表示反正切函数。
- 边缘检测:根据计算得到的梯度幅值和方向,可以进行边缘检测,常见的做法是设定一个阈值,当梯度幅值超过该阈值时,认为该像素点处存在边缘。
ps: 总的来说,Sobel算子通过计算图像中每个像素点处的梯度,进而找到灰度变化剧烈的区域,从而实现了图像的边缘检测。
3.3.2 函数方法讲解
- dst = cv2.Sobel()(src, alpha, beta) 输出绝对值
- src=img:输入图像
- ddepth=cv2.CV_64F:输出图像的深度为 64 位浮点型
- dx=1, dy=0:表示在 x 方向上求导,即进行水平边缘检测
- ksize=3:Sobel 算子的大小为 3x3
- dst = cv2.convertScaleAbs(src, alpha, beta) 输出绝对值
- src:输入图像或数组
- alpha:乘数因子
- beta:加数因子
- ps:其作用是将输入数组的每个元素进行缩放,并取绝对值,然后将结果转换为无符号8位整型。就是将sobel得到的像素点的负数转正数(0~255)像素点负值的话将默认0,不输出绝对值,图像就是下图
3.3.3 代码示例
img = cv2.imread("../static/li_na.png", cv2.IMREAD_GRAYSCALE)
sobel_x = cv2.Sobel(src=img, ddepth=cv2.CV_64F, dx=1, dy=0, ksize=3)
sobel_x = cv2.convertScaleAbs(src=sobel_x)
sobel_y = cv2.Sobel(src=img, ddepth=cv2.CV_64F, dx=0, dy=1, ksize=3)
sobel_y = cv2.convertScaleAbs(src=sobel_y)
sobel_xy = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)
cv2.imshow("img", sobel_xy)
cv2.waitKey(0)
cv2.destroyAllWindows()
4 图像平滑处理
4.1 高斯滤波与中值滤波
4.1.1 基本思想
-
高斯滤波(Gaussian Filtering)
-
高斯滤波是一种线性平滑滤波器,它利用高斯函数对图像进行加权平均,以降低图像中的高频噪声。其基本思想是对每个像素的灰度值,通过一个指定大小和标准差的高斯核进行加权平均,得到新的像素值。
-
原理:
对图像中的每个像素,以其为中心,构建一个指定大小和标准差的高斯核。
将高斯核与图像进行卷积操作,得到新的像素值。 -
特点:
高斯滤波对高斯噪声有较好的去除效果,因为高斯噪声通常符合正态分布。
适用于对连续性较强的图像进行平滑处理。
-
-
中值滤波(Median Filtering)
中值滤波是一种非线性滤波器,它采用像素邻域内像素值的中值作为新的像素值,用于去除图像中的椒盐噪声等离群点。- 原理:
对图像中的每个像素,取其邻域内像素值的中值作为新的像素值。
遍历整个图像,重复以上操作。 - 特点:
中值滤波对椒盐噪声和脉冲噪声有良好的去除效果,因为它采用中值而不受离群点的影响。
在保留图像边缘信息方面表现较好,适用于对包含大量噪声的图像进行处理。
- 原理:
-
综上所述,高斯滤波适用于对连续性较强的图像进行平滑处理,而中值滤波则更适用于对含有椒盐噪声等离群点的图像进行处理。选择滤波方法应根据具体的图像特点和噪声类型进行综合考虑。
4.1.2 方法讲解
- 高斯滤波
-
dst = cv2.GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
- src: 输入图像,可以是灰度图像或彩色图像。
- ksize: 高斯核的大小,指定为 (width, height) 的元组。这个参数决定了高斯核的大小,通常取奇数值,如 (3, 3)、(5, 5) 等。
- sigmaX: X 方向上的标准差,如果为 0,则会根据核的大小自动计算标准差。
- dst: 输出图像,与输入图像具有相同的大小和数据类型。
- sigmaY: Y 方向上的标准差,如果省略,则默认与 sigmaX 相同。
- borderType: 边界模式,默认为 BORDER_DEFAULT。
-
- 中值滤波
-
dst = cv2.medianBlur(src, ksize, dst=None)
- src: 输入图像,可以是灰度图像或彩色图像。
- ksize: 滤波器的孔径大小,通常为一个大于 1 的奇数值。
- dst: 输出图像,与输入图像具有相同的大小和数据类型。
-
4.1.3 代码示例
高斯滤波
img = cv2.imread("../static/li_na.png")
gaussian = cv2.GaussianBlur(img, (3, 3), 1)
cv2.imshow("img", median)
cv2.waitKey(0)
cv2.destroyAllWindows()
中值滤波
img = cv2.imread("../static/li_na.png")
median = cv2.medianBlur(img, 3)
cv2.imshow("img", median)
cv2.waitKey(0)
cv2.destroyAllWindows()
4.2 图片阈值过滤
4.2.1 实现逻辑
将输入图像转换为二进制格式的图像,就可以将图像中的像素值进行阈值化处理,使得像素值高于或低于阈值的部分变为预先设定的值。
4.2.2 使用函数方法
- retval, dst = cv2.threshold(src, thresh, maxval, type)
- src 是输入图像,单通道的灰度图像。
- thresh 是设定的阈值。取值范围(0~255)
- maxval 是在阈值处理过程中,超过阈值的像素被赋予的值。取值范围(0~255)
- type 是阈值处理的类型,包括:
- cv2.THRESH_BINARY:二进制阈值化。
- cv2.THRESH_BINARY_INV:反向二进制阈值化。
- cv2.THRESH_TRUNC:截断阈值化。
- cv2.THRESH_TOZERO:超过阈值的像素保持不变,低于阈值的变为0。
- cv2.THRESH_TOZERO_INV:低于阈值的像素保持不变,高于阈值的变为0。
- 函数返回值 retval 是计算的阈值,dst 是经过阈值处理后的输出图像
4.2.3 代码示例
img = cv2.imread('../static/cat.jpg', 0) # 以灰度模式读入图像
ret, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('Thresholded Image', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
5 边缘检测
5.1 Canny边缘检测
5.1.1 实现逻辑
- 使用高斯滤波器- 平滑图像,消除噪声
- 计算图像中每个像素点的梯度强度与方向
- 应用非极大值抑制,消除边缘检测带来的散杂影响
- 应用双阈值检测来确认真实和潜在的边缘
- 通过抑制孤立的边缘最终完成边缘检测
5.2 函数介绍
ps: 提高效率,使用二值图像
- img = cv2.imread()
- 读取图片
- cv2.cvtColor(src, code)
- 彩色图像转灰度图-减少计算量
- src:要进行颜色空间转换的输入图像。
- code:指定颜色空间转换的类型。常用的转换类型包括:
- cv2.COLOR_BGR2GRAY:将BGR彩色图像转换为灰度图像。
- cv2.COLOR_BGR2RGB:将BGR彩色图像转换为RGB彩色图像。
- cv2.COLOR_GRAY2BGR:将灰度图像转换为BGR彩色图像。
- cv2.threshold(src, thresh, maxval, type)
- 图像阈值过滤,进行二值化
- src:输入图像,单通道灰度图像。
- thresh:阈值,用于对像素进行二值化处理。像素值大于阈值时设为maxval,小于等于阈值时设为0。
- maxval:当像素值大于阈值时,要设置的像素值。
- 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.findContours(image, mode, method)
- image:输入的单通道图像。一般情况下,这是通过阈值处理后得到的二值图像。确保图像是单通道的灰度图像。
- mode:轮廓检索模式。它指定了轮廓的检索模式。常用的模式包括:
- cv2.RETR_EXTERNAL:仅检测最外层的轮廓。
- cv2.RETR_LIST:检测所有的轮廓,不建立轮廓的父子关系。
- cv2.RETR_TREE:检测所有轮廓,并建立完整的轮廓层级结构。
- cv2.RETR_CCOMP:检测所有轮廓,并将轮廓分为两个层级,外部轮廓和内部空洞的轮廓。
- method:轮廓逼近方法。它指定了轮廓的逼近方法。常用的方法包括:
- cv2.CHAIN_APPROX_NONE:存储所有的轮廓点。
- cv2.CHAIN_APPROX_SIMPLE:仅存储水平、垂直和对角线端点。例如,一个矩形只需要四个端点来表示。
- cv2.drawContours(image, contours, contourIdx, color)
- 在图像上绘制轮廓
- image:输入图像,可以是单通道或多通道图像。
*contours:轮廓列表,每个轮廓由点集组成。
*contourIdx:轮廓索引,指定要绘制的轮廓。如果为负数,则绘制所有的轮廓。
*color:绘制轮廓的颜色,可以是一个BGR值的元组。例如,红色可以表示为(0, 0, 255)。
*thickness(可选):绘制轮廓的线条粗细,默认值为1。
*lineType(可选):绘制轮廓的线条类型,默认值为cv2.LINE_8,表示8连通线条。
*hierarchy(可选):轮廓的层级信息,用于绘制父子轮廓间的连接线。
*maxLevel(可选):指定绘制轮廓的最大层级深度。
*offset(可选):指定绘制轮廓的偏移量
5.2 代码示例
import cv2
img = cv2.imread("./yjh.jpg")
# 彩色图像转灰度图-减少计算量
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 图像阈值过滤,进行二值化
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 图像中查找轮廓
contour, hierchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 绘制轮廓
cv2.drawContours(img, contour, -1, (0, 0, 255), 5)
# 轮廓特征
cv2.namedWindow('yjh', cv2.WINDOW_NORMAL)
cv2.resizeWindow('yjh', 300, 400)
cv2.imshow("yjh", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
5.2 边缘检测
5.2.1 关于边缘的一些相关方法
PS: contour是图像的轮廓信息
- 获取图像面积
- 关键函数
- cv2.contourArea(contour)
- 这个函数用于计算轮廓的面积,接受一个轮廓作为参数,并返回其面积值
- 获取图形周长
- 关键函数
- C = cv2.arcLength(contour, True)
- 函数用于计算封闭轮廓的周长,第二个参数表示轮廓是否闭合。
- 获取图像最小边界矩阵边界
- 关键函数
- x, y, w, h = cv2.boundingRect(contour):计算最小外接矩形的坐标和尺寸
- contour= cv2.convexHull(contour) :对轮廓进行凸包处理
- 获取图像最小边界圆形边界
- 关键函数
-
( x, y), radius = cv2.minEnclosingCircle(contour) center = (int(x), int(y)) radius = int(radius)
- 这个函数用于计算最小外接圆形的圆心坐标和半径。返回值是一个元组,包含圆心坐标和半径信息
5.2.2 完整代码示例
import cv2
# img = cv2.imread("./R-C.jpg")
img = cv2.imread("./lx_1.jpg")
# 裁剪图片
# 获取图片尺寸
height, width, _ = img.shape
# 裁剪边缘
# img = img[50:height, :, :]
# 彩色图像转灰度图-减少计算量
gray = cv2.cvtColor(src=img, code=cv2.COLOR_BGR2GRAY)
# 图像阈值过滤,进行二值化
ret, thresh = cv2.threshold(src=gray, thresh=127, maxval=255, type=cv2.THRESH_BINARY)
# 图像中查找轮廓
contours, hierchy = cv2.findContours(image=thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)
print("识别到轮廓个数:", len(contours))
# 计算周长
contour = contours[0]
C = cv2.arcLength(contour, True)
print("轮廓周长(像素点个数)", C)
# 绘制轮廓
cv2.drawContours(image=img, contours=contour, contourIdx=-1, color=(255, 0, 0), thickness=3)
# # 获取最小矩阵边框
x, y, w, h = cv2.boundingRect(contour)
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
print("最小矩阵坐标信息: x =", x, ", y =", y, ", width =", w, ", height =", h)
print("轮廓面积(像素点个数)S:", cv2.contourArea(contour))
# 获取最小外部圆轮廓
(x, y), radius = cv2.minEnclosingCircle(points=contour)
center = (int(x), int(y))
radius = int(radius)
cv2.circle(img=img, center=center, radius=radius, color=(255, 0, 0))
# 轮廓特征
cv2.namedWindow('y', cv2.WINDOW_NORMAL)
cv2.resizeWindow('y', 400, 400)
cv2.imshow("y", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
6 模板匹配
6.1 模板匹配流程
-
首先,导入了OpenCV和Numpy库。
-
读取了一张原始图像和一张模板图像,两张图像都是通过cv2.imread()函数读取的。
-
使用cv2.matchTemplate()函数对原始图像和模板图像进行匹配,返回的result是匹配结果矩阵。
-
使用cv2.minMaxLoc()函数在匹配结果矩阵中找到最大值的位置和数值。
-
设置匹配阈值threshold,如果最大值max_val大于等于阈值,则认为匹配成功。
-
如果匹配成功,获取模板图像的宽度和高度,并计算出模板图像在原始图像中的左上角和右下角坐标,然后使用cv2.rectangle()函数在原始图像上绘制矩形框。
-
最后,使用cv2.imshow()函数显示匹配结果图像,并等待用户按下任意键关闭窗口,最后释放窗口资源。
6.2 使用函数介绍
- cv2.matchTemplate()
- 它能够在一张大图中寻找特定的小图像,返回小图像在大图中的位置
- image:输入图像,即待搜索的大图像,数据类型为uint8或float32,尺寸为(宽度,高度)。
- template:模板图像,即要在输入图像中查找的小图像,数据类型同样为uint8或float32,尺寸为(宽度,高度)。
- method:匹配方法,是一个枚举类型的参数,用于指定使用哪种匹配算法,包括以下几种:
- cv2.TM_SQDIFF:平方差匹配算法
- cv2.TM_SQDIFF_NORMED:归一化平方差匹配算法
- cv2.TM_CCORR:相关性匹配算法
- cv2.TM_CCORR_NORMED:归一化相关性匹配算法
- cv2.TM_CCOEFF:相关系数匹配算法
- cv2.TM_CCOEFF_NORMED:归一化相关系数匹配算法
- mask:可选的掩膜图像,用于指定感兴趣区域,大小必须与输入图像相同。
- result:输出结果图像,表示模板与输入图像的匹配程度,数据类型为float32,尺寸为(宽度 - 模板宽度 + 1,高度 - 模板高度 + 1)。
- use_canny_pruning:可选参数,指定是否使用Canny算子对输入图像和模板图像进行预处理,提高匹配效率。
- 该函数返回值为一个包含匹配结果的Numpy数组
- cv2.minMaxLoc()
- 它可以用于获取图像中像素值的最小值、最大值以及对应的位置
- min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) # 在多维数组中找到最大和最小值
- src:输入图像,即待搜索的图像,数据类型为uint8或float32,尺寸为(宽度,高度)。
- mask:可选的掩膜图像,用于指定感兴趣区域,大小必须与输入图像相同。
- minVal:返回结果中的最小值,数据类型为float32。
- maxVal:返回结果中的最大值,数据类型为float32。
- minLoc:返回结果中最小值的位置,数据类型为元组(x,y)。
- maxLoc:返回结果中最大值的位置,数据类型为元组(x,y)。
- shape()
- 对于一个图像,shape返回一个元组,包含三个值:(高度,宽度,通道数)
- cv2.rectangle()
- 它可以在给定图像上绘制一个矩形,可以用不同的线宽和颜色进行绘制
- img:输入图像,即待绘制矩形的图像,数据类型为uint8,可以是单通道或多通道图像。
- pt1:矩形的左上角点坐标,数据类型为元组(x,y)。
- pt2:矩形的右下角点坐标,数据类型为元组(x,y)。
- color:矩形的颜色,可以是一个整数(灰度图像)或一个元组(RGB图像),例如(0, 255, 0)代表绿色。
- thickness:可选参数,指定矩形边框的线宽,默认值为1。
- lineType:可选参数,指定线条的类型,可以选择的值包括8(8-connected线条)和4(4-connected线条)。
- shift:可选参数,指定坐标中的小数位数,默认值为0。
6.3 代码示例
ps: 注意图片路径不要有中文
img = cv2.imread('../static/cat.jpg')
temp = cv2.imread('../static/split_cat.png')
result = cv2.matchTemplate(img, temp, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) # 在多维数组中找到最大和最小值
print(max_val, max_loc)
threshold = 0.85 # 设置阈值
if max_val >= threshold:
template_width, template_height = temp.shape[:2] # 获取模板的宽高
top_left = max_loc
bottom_right = (top_left[0] + template_width, top_left[1] + template_height) # 绘制轮廓
cv2.rectangle(img, top_left, bottom_right, color=(0, 255, 0), thickness=2)
cv2.imshow("Result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
7 HSV色彩空间表
ps:分享一下车牌识别的实现方法
7.1 实现逻辑
向下面这个图,图片预处理后有很多不用的轮廓,刚开始一直通过cv2.threshold方法和开运算过滤,但怎么也搞不定(有点菜),后面一直找度娘,看到了图片划分区块,然后寻找颜色占比的方法。
我这里是
- 图片预处理,二值化,过滤,开运算
- 将获取到的轮廓去除面积小于3000的
- 获取轮廓的坐标(左上角的坐标和轮廓宽高)
- 找到轮廓中蓝色占比最多的轮廓
7.2 使用函数介绍
- cv2.mean()
- 参数 src 输入数组,具有1到4个通道,结果保存在Scalar_ 。
- 参数 mask 可选参数,操作掩摸,用于标记求取哪些区域的均值和标准差。
- cv2.inRange(hsv_img, low, up)
- 三个参数全是数据,这种np.array([0, 255, 255])
- 第一个参数:hsv指的是原图
- 第二个参数:lower_red指的是图像中低于这个lower_red的值,图像值变为0
- 第三个参数:upper_red指的是图像中高于这个upper_red的值,图像值变为0
- 而在lower_red~upper_red之间的值变成255
- 返回图像数组
- cv2.cvtColor(img_lite, cv2.COLOR_BGR2HSV)
- img_lite: 图片
- cv2.COLOR_BGR2HSV:从BGR颜色空间转换为HSV颜色空间
- S = cv2.contourArea(contour)
- contour: 轮廓
- S: 轮廓的面积
- contours, hierchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
- 第一个参数:图片
- 第二个参数:
- CV_CHAIN_APPROX_NONE :存储轮廓的所有点
- CV_CHAIN_APPROX_SIMPLE :不保存轮廓中水平、垂直、对角的线段,只保存轮廓的角点
- 第三个参数
4. CV_RETR_EXTERNAL :返回最外层轮廓
5. CV_RETR_LIST :返回所有的轮廓
6. CV_RETR_CCOMP :返回所有轮廓
7. CV_RETR_TREE :返回所有轮廓
- x, y, w, h = cv2.boundingRect(contours)
2. contours: 轮廓
3. 返回轮廓的左上坐标和轮廓宽高 - cv2.rectangle(img, pt1, pt2, color, thickness, lineType, shift )
- img:图片
- pt1:长方形框左上角坐标
- pt2:长方形框右下角坐标
- color:字体颜色
- thickness:字体粗细
7.3 代码示例
import cv2
import numpy as np
"""
加载图像: 使用OpenCV加载待检测的图像。
图像预处理: 对图像进行预处理,例如灰度化、高斯平滑、边缘增强等。这有助于提升后续步骤的准确性。
车牌区域定位: 使用OpenCV中的边缘检测算法(如Canny边缘检测)或形态学操作(如开运算、闭运算)来检测图像中的边缘或轮廓。然后,根据车牌的形状和尺寸特征,使用一些启发式规则(如长宽比、面积等)来筛选出可能是车牌的区域。
车牌字符分割: 在定位到的车牌区域上,使用OpenCV的图像处理技术(如阈值化、连通组件分析等)将字符分割为单独的图像块。
字符识别: 对分割得到的字符图像块进行字符识别。这可以使用基于机器学习的方法,如支持向量机(SVM)或深度学习方法(如卷积神经网络)进行训练和识别。
"""
img = cv2.imread('./static/img_1.png')
# img = cv2.imread('./static/img_2.png')
# 转灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY)
# 过滤,颜色大于100的转为55
res, gray = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
# 腐蚀-膨胀核
kernel = np.ones((3, 3), np.uint8)
# 开运算
cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
# 膨胀操作-加粗轮廓
gray = cv2.dilate(gray, kernel, 18)
# 腐蚀-去除细小轮廓
gray = cv2.erode(gray, np.ones((2, 2), np.uint8), iterations=1)
# 获取图片中所有的轮廓
contours, hierchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
print(f"识别到的轮廓个数: {len(contours)}")
# 计算轮廓的面积与颜色占比
new_contours = []
max_mean = 0
for index, contour in enumerate(contours):
# 获取每个轮廓的面积,过滤
S = cv2.contourArea(contour)
if S < 3000:
continue
x, y, w, h = cv2.boundingRect(contour) # 获取每个轮廓的左上角坐标和宽高
top_x, top_y = x, y
down_x, down_y = x + w, y + h
# 根据轮廓坐标切割图片
img_lite = img[y: h + y, x: x + w]
# 定义颜色范围
low = np.array([100, 43, 46])
up = np.array([124, 255, 255])
# 从BGR颜色空间转换为HSV颜色空间
hsv_img = cv2.cvtColor(img_lite, cv2.COLOR_BGR2HSV)
# 将蓝色部分转为255(蓝色转白色,其他全黑色)
mask = cv2.inRange(hsv_img, low, up)
# 计算每个轮廓的平均值(越大的蓝色越多)
mean = cv2.mean(mask)
if mean[0] > max_mean:
max_mean = mean[0]
# 替换轮廓
new_contours = [contour]
print(f"过滤后轮廓个数: {len(new_contours)}")
x, y, w, h = cv2.boundingRect(new_contours[0])
cv2.rectangle(img, (x, y), (x+w, h+y), color=(0, 255, 0), thickness=2) # 根据轮廓坐标框
# cv2.drawContours(img, new_contours, -1, (0, 255, 0)) # 绘画出轮廓
cv2.namedWindow("车", cv2.WINDOW_NORMAL)
cv2.imshow("车", img)
cv2.waitKey(0)
cv2.destroyAllWindows()