当前位置:   article > 正文

OpenCV入门(基于python)——笔记_python opencv bgr2rgb

python opencv bgr2rgb

目录

1.安装CV2 (确保已经安装Anconde并配置环境)

2.读取图片,并显示和保存

3.图片基本处理

4.画框、画线、画圆

5.插入文字

6.平滑处理

7.图形轮廓

 8.几何变形

9.加载摄像或视频文件


1.安装CV2 (确保已经安装Anconde并配置环境)

pip install opencv-python

最好确保numpy也正常安装

pip install numpy

2.读取图片,并显示和保存

在Python的OpenCV库中,读取图片的常用方法有以下几种:

  • 使用imread()函数读取图片。
  • 使用imshow()函数显示图片。
  • 使用waitKey()函数等待用户按下键盘上的任意键后关闭窗口(不加上窗口会一闪而过)waitKey 是 OpenCV 的一个函数,用于等待并获取键盘输入的事件。这个函数的参数是一个整数,表示等待的最长时间(以毫秒为单位)。如果在这段时间内用户按下了键盘上的任意键,函数会立即返回按下的键的 ASCII 值。如果超过指定的时间,函数仍然没有收到键盘输入,那么它将返回 -1。
  • 使用destroyAllWindows()函数关闭所有窗口。
  • 使用imwrite('fileName.jpg', img)该函数用于将图像数据保存为名为“saved_example.jpg”的图像文件。第一个参数是文件名,第二个参数是要保存的图像数据

       注意:路径不能有中文

  1. import cv2
  2. # 使用imread()函数读取图片,参数是图片文件的路径
  3. image = cv2.imread('path_to_your_image.jpg')
  4. # 使用imshow()函数显示图片,第一个参数是窗口的名称,第二个参数是要显示的图像
  5. cv2.imshow('image', image)
  6. # 使用waitKey()函数等待用户按下键盘上的任意键后关闭窗口,参数是等待的毫秒数
  7. cv2.waitKey(0)
  8. # 使用destroyAllWindows()函数关闭所有窗口
  9. cv2.destroyAllWindows()
  10. cv2.imwrite('saved_example.jpg', image)

c26e4b4eb3f746b8a8468c068e7747fa.png

积累:

代码使用cv2.imdecode()函数读取文件,如下

  1. import cv2
  2. import numpy as np
  3. filename = "path_to_your_image_file" # 替换为你的图像文件路径
  4. decoded_image = cv2.imdecode(np.fromfile(filename, dtype=np.uint8), cv2.IMREAD_COLOR)
  5. cv2.imshow("Decoded Image", decoded_image)
  6. cv2.waitKey(0)
  7. cv2.destroyAllWindows()

展示结果

c26e4b4eb3f746b8a8468c068e7747fa.png

imdecode()imread()都是用于读取图像文件的函数,但它们在某些方面存在一些差异。

imread()是OpenCV库中用于读取图像文件的函数,它能够读取各种格式的图像文件,并将其转换为OpenCV的Mat对象。该函数通常用于简单的图像读取任务,并且可以直接在Python中使用。

imdecode()函数则是在读取图像文件后将其解码为图像矩阵,它接受一个包含图像数据的字节流作为输入,并返回解码后的图像矩阵。这个函数通常用于处理从网络传输或文件流中读取的图像数据,因为它可以解码图像而不需要先将其写入磁盘

总结来说,imread()imdecode()的主要区别在于:

  • imread()用于直接读取图像文件,而imdecode()用于解码图像数据流。
  • imread()返回一个OpenCV的Mat对象,而imdecode()返回解码后的图像矩阵。
  • imread()通常用于简单的图像读取任务,而imdecode()适用于处理从网络或文件流中读取的图像数据。

3.图片基本处理

BGR模式转换为RGB模式       

在Python的OpenCV库中将图像从BGR模式转换为RGB模式。这是一个常见的操作,因为在许多图像处理和计算机视觉任务中,我们通常使用RGB模式来表示图像

img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

  提取图片的BGR部分

  1. import cv2
  2. # 读取图像
  3. img = cv2.imread('image.jpg')
  4. # OpenCV默认以BGR(Blue, Green, Red)方式读取图像
  5. # 所以我们需要把BGR转成RGB来处理
  6. img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  7. # 分离出RGB三个通道,顺序是B、G、R,即蓝绿红与红绿蓝正好相反。
  8. b, g, r = cv2.split(img_rgb)

灰度化处理

将彩色图像转换为灰度图像的过程称为灰度化处理。灰度化处理将彩色图像的每个像素转换为一个灰度值,表示像素的亮度。灰度化处理可以减少图像的数据量,并简化图像的分析和处理过程。

  1. # 将彩色图像转换为灰度图像
  2. gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

二值化处理

二值化处理,顾名思义就是只留下黑与白,即每个元素不是为0黑,就是最大阈值。是一种常见的图像处理技术,它可以将灰度图像转化为二值图像,使得图像数据量减少,同时凸显出目标的轮廓,更有利于图像的进一步处理。

  1. # 对图像进行二值化处理
  2. ret, thresh = cv2.threshold(src, 阈值, 最大值, type)

参数说明:

  • src:源图像,通常为灰度图像。
  • thresh:阈值,用于确定图像的黑白分界。
  • maxval:当源图像的灰度值高于(或低于)阈值时的最大值。如果是大于阈值的像素,则将其设置为maxval;如果是小于阈值的像素,则将其设置为0
  • type:二值化类型。这是一个可选参数,默认为cv2.THRESH_BINARY。以下是一些常见的类型:
    • cv2.THRESH_BINARY:这是默认类型,大于阈值的像素被赋值为maxval,否则被赋值为0
    • cv2.THRESH_BINARY_INV:与cv2.THRESH_BINARY相反,小于阈值的像素被赋值为maxval,否则被赋值为0
    • cv2.THRESH_TRUNC:大于阈值的像素被赋值为maxval,小于阈值的像素被赋值为0,阈值处的像素被赋值为阈值。
    • cv2.THRESH_TOZERO:大于阈值的像素被赋值为maxval,小于阈值的像素被赋值为0
    • cv2.THRESH_TOZERO_INV:大于阈值的像素被赋值为0,小于阈值的像素被赋值为maxval
  • dst:输出图像,与输入图像大小相同,类型为8位无符号的二进制图像。

   

shape与reshape的使用

shape使用

在python的OpenCV中图片是使用numpy存储的,是以多维数据矩阵的方式存在,一般维度为height*width*3(height*width代表图片的高和宽,3代表蓝绿红3底色,每个元素取值0-255)。

shape函数如果是彩色图像,则返回(行数,列数,通道数)的数组;如果是灰度图像,则返回(行数,列数)的数组。

  1. # 读取图像
  2. img = cv2.imread('image.jpg')
  3. # 获取图像的形状信息
  4. shape = img.shape
  5. print('Height:', shape[0])
  6. print('Width:', shape[1])
  7. print('Channels:', shape[2])

结果:

68f9996e9975454396093c232ee5121c.png

reshape函数通常是指改变数据结构或矩阵的形状或布局的操作

  1. import numpy as np
  2. # 创建一个一维数组
  3. arr = np.array([1, 2, 3, 4])
  4. print("原始数组:")
  5. print(arr)
  6. # 将一维数组重塑为二维数组
  7. reshaped_arr = arr.reshape(2, 2)
  8. print("重塑后的二维数组:")
  9. print(reshaped_arr)
'
运行
  1. 原始数组:
  2. [1 2 3 4]
  3. 重塑后的二维数组:
  4. [[1 2]
  5. [3 4]]

图片截取和resize操作

图片裁剪:

  1. # 定义裁剪区域 (x, y, width, height)
  2. crop_img = image[y:y+h, x:x+w]

cv2.resize的使用方法

resize函数用于调整图像的尺寸。它接受以下参数:

  • src:输入图像。这可以是一个彩色或灰度图像。
  • dst:输出图像。这是调整尺寸后的图像大小,一般设置为(height,width)。
  • fx:沿着水平轴的比例因子。如果为负数,则函数会将图像翻转。
  • fy:沿着垂直轴的比例因子。如果为负数,则函数会将图像翻转。如果fx和fy都是0,函数会根据新的图像大小自动计算它们。
  • interpolation:插值方法。这是决定如何调整图像尺寸的方法。常见的选项包括cv2.INTER_LINEAR(线性插值,这是默认值),cv2.INTER_NEAREST(最近邻插值),cv2.INTER_AREA(像素区域相关插值,适合用于缩小图像)等。
  1. import cv2
  2. # 加载图像
  3. image = cv2.imread('01.jpg')
  4. cv2.imshow("image",image)
  5. print("shape:",image.shape)
  6. h,w,_=image.shape
  7. # 定义裁剪区域 (x, y, width, height)
  8. crop_img = image[200:520, 100:520]
  9. cv2.imshow('Cropped Image', crop_img)
  10. #调整图片大小
  11. # 重塑图像为一个高度和宽度都为原来一半的新图像
  12. new_shape = cv2.resize(crop_img,(int(h / 2), int(w / 2)))
  13. cv2.imshow("new_img",new_shape)
  14. cv2.waitKey(0)
  15. cv2.destroyAllWindows()

874c6583ec8749d5b54204e1586273d3.png

4.画框、画线、画圆

  1. import cv2
  2. import numpy as np
  3. # 创建一个空白的图像
  4. image = np.zeros((512, 512, 3), dtype="uint8")
  5. # 定义矩形的左上角和右下角坐标和颜色蓝,线段粗细2像素点
  6. # 在图像上画一个矩形
  7. cv2.rectangle(image, (10, 10), (40, 40), (255, 0, 0), thickness=2)
  8. # 定义直线的起点坐标和终点坐标,以及颜色绿,线段粗细2像素点
  9. # 在图像上画一条直线
  10. cv2.line(image,(10, 10), (40, 40), (0, 255, 0), thickness=2)
  11. # 定义圆的中心坐标和半径,以及颜色红,线段粗细2像素点
  12. # 在图像上画一个圆
  13. cv2.circle(image, (384, 384), 100, (0, 0, 255),thickness=2)
  14. cv2.imshow("img", image)
  15. cv2.waitKey(0)
  16. cv2.destroyAllWindows()

结果演示:

9b2034149aa7466290eb0ece77fee95e.png

5.插入文字

可以使用Python的内置功能来在图像上绘制文本。

cv2.putText() 函数的参数如下:

  • image:你想要在其上绘制文本的图像。
  • text:你想要绘制的文本。
  • org:文本的左下角坐标(即文本开始的位置)。
  • font:字体类型。例如,cv2.FONT_HERSHEY_SIMPLEXcv2.FONT_HERSHEY_PLAIN等。
  • fontScale:字体大小。你可以通过这个参数来缩放字体。
  • color:文本颜色。这个参数是一个BGR元组,例如 (255, 255, 255) 表示白色。
  • thickness:文本线宽。如果你将这个值设为1,那么文本就会有一条黑色的边框。如果你将这个值设为2,那么文本就会有两条黑色的边框,以此类推。
  1. import cv2
  2. import numpy as np
  3. # 创建一个空白的图像
  4. image = np.zeros((512, 512, 3), dtype="uint8")
  5. # 定义你想要插入的文本
  6. text = "OpenCV"
  7. # 使用OpenCV的putText函数在图像上绘制文本
  8. cv2.putText(image, text, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
  9. # 显示图像
  10. cv2.imshow("Image with Text", image)
  11. cv2.waitKey(0)
  12. cv2.destroyAllWindows()

结果演示:

aa7620f5d31f47c688d67d22cf93d17c.png

解决在python中Opencv不给图片中文的问题

  •        下载Pillow
pip install Pillow
  •         使用如下代码
  1. # 创建一个空白的图像
  2. image = np.zeros((512, 512, 3), dtype="uint8")
  3. import cv2
  4. import numpy as np
  5. from PIL import ImageFont, Image, ImageDraw
  6. # 创建一个空白的图像
  7. image = np.zeros((512, 512, 3), dtype="uint8")
  8. def show_chinese(img,text,pos):
  9. img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
  10. font = ImageFont.truetype(font='msyh.ttc', size=36)
  11. draw = ImageDraw.Draw(img_pil)
  12. draw.text(pos, text, font=font, fill=(255, 0, 0)) # PIL中RGB=(255,0,0)表示红色
  13. img_cv = np.array(img_pil) # PIL图片转换为numpy
  14. img = cv2.cvtColor(img_cv, cv2.COLOR_RGB2BGR) # PIL格式转换为OpenCV的BGR格式
  15. return img
  16. img = show_chinese(image,"你好",(0,0))
  17. cv2.imshow('p', img)
  18. cv2.waitKey(0)
  19. cv2.destroyAllWindows()

结果演示

70c5213b4e7243ceaebabee8ab2eec21.png

6.平滑处理

在OpenCV中,可以使用多种方法进行噪点过滤。以下是几种常见的方法:

这里只做平滑处理简单介绍,详细原理和具体目的可参考其他博主的文章,推荐如下:

文章1

  • 均值滤波器:

        均值滤波器是一种常见的图像处理技术,可以用于降低图像的噪声。均值滤波器是一种线性滤波器,它对图像进行平滑处理,去除噪声,同时也能去除图像的细节部分,代码示例如下

  1. import cv2
  2. # 加载图像
  3. img = cv2.imread('image.jpg')
  4. # 使用cv2.blur()进行均值滤波,这里使用大小为9*9的滤波核进行均值滤波
  5. dst1 = cv2.blur(img, (9, 9))
  6. # 使用cv2.boxFilter()进行均值滤波
  7. blur = cv2.boxFilter(img, -1, (5, 5), normalize=True)
  8. # 显示原图和处理后的图像
  9. cv2.imshow('Original Image', img)
  10. cv2.imshow('Blur Image', blur)
  11. cv2.waitKey(0)
  12. cv2.destroyAllWindows()

参数说明:

dst = cv2.blur(src,ksize,anchor,borderType)
参数说明:

  • src:被处理的图像
  • ksize:滤波核大小,其格式为(高度,宽度),建议使用如(3,3)、(5,5)等宽高相等的奇数边长。滤波核越大,处理之后的图像就越模糊。
  • anchor:可选参数,滤波核的锚点,建议采用默认值,方法可以自动计算锚点。
  • boderType:可选参数,边界样式,建议采用默认值。


cv2.boxFilter(src, ddepth, ksize, dst , anchor , normalize , borderType)

参数说明(方括号内表示可加可不加):

  • src:输入图像对象矩阵。
  • ddepth:数据格式,位深度。通常为 CV_32F 或 CV_64F。参数为-1时,表示输出图像的深度将与输入图像相同。也就是说,如果输入图像是8位无符号整型的图像,则输出图像也将是8位无符号整型的图像。
  • ksize:高斯卷积核的大小,格式为(宽,高)。
  • dst:输出图像矩阵,大小和数据类型都与src相同。
  • anchor:卷积核锚点,默认-1-1表示卷积核的中心位置。
  • normalize:是否归一化(若卷积核3*5,归一化卷积核需要除以15)。
  • borderType:填充边界类型。

        盒形滤波器是一个领域滤波器,对于领域内像素的平均值进行计算,然后将该值分配给中心像素。盒形滤波器对图像进行滤波处理,与高斯滤波器类似,但是它不需要指定sigmaX和sigmaY参数,因此更加简单和直接。盒形滤波器的卷积核是一个正方形,对应于每个像素的窗口大小可以自由调整。

        

  • 中值滤波:

        中值滤波是一种非线性信号处理技术,它对像素值进行排序,并将中间值作为输出。这种方法对于消除随机出现的噪点非常有效。可以使用OpenCV的cv2.medianBlur()函数实现中值滤波,如下所示:

  1. import cv2
  2. # 读取图像
  3. img = cv2.imread('image.jpg')
  4. # 进行中值滤波
  5. filtered_img = cv2.medianBlur(img, 5)
  6. # 显示原图和滤波后的图像
  7. cv2.imshow('Original Image', img)
  8. cv2.imshow('Filtered Image', filtered_img)
  9. cv2.waitKey(0)
  10. cv2.destroyAllWindows()

参数说明:

cv2.medianBlur(src,ksize)

函数的具体参数如下1:

  • src:源图像,可以是彩色图像或灰度图像。
  • ksize:滤波核的边长,必须是正数大于1,且为奇数。

  • 高斯滤波:

        高斯滤波是一种线性滤波技术,它使用正态分布函数对像素值进行加权平均。这种方法对于消除高斯噪声非常有效。可以使用OpenCV的cv2.GaussianBlur()函数实现高斯滤波,如下所示:

  1. import cv2
  2. # 读取图像
  3. img = cv2.imread('image.jpg')
  4. # 进行高斯滤波
  5. filtered_img = cv2.GaussianBlur(img, (5, 5), 0)
  6. # 显示原图和滤波后的图像
  7. cv2.imshow('Original Image', img)
  8. cv2.imshow('Filtered Image', filtered_img)
  9. cv2.waitKey(0)
  10. cv2.destroyAllWindows()

参数说明:

blurred = cv2.GaussianBlur(src,ksize, sigmaX=1.0, sigmaY=1.0, borderType=cv2.BORDER_CONSTANT)

函数的具体参数如下:

  • src:源图像,输入图像。
  • ksize:高斯核大小。这个参数是一个包含两个整数的元组,表示高斯核的宽和高。例如,(3, 3)表示使用3x3的高斯核。
  • sigmaX:X方向上的高斯核标准偏差。这个参数决定了高斯核在X方向上的平滑程度。sigmaX的值越大,图像在X方向上的模糊程度越强。
  • sigmaY:Y方向上的高斯核标准偏差。这个参数决定了高斯核在Y方向上的平滑程度。sigmaY的值越大,图像在Y方向上的模糊程度越强。如果不知道如何设计这两个参数值,就直接把这两个参数的值写成0,方法就会根据滤波核的大小自动计算出合适的权重比例。
  • borderType:像素外插法。这个参数指定了在进行高斯模糊时,如何处理图像边缘的像素。常见的值有cv2.BORDER_CONSTANT(常数填充)、cv2.BORDER_REPLICATE(复制边缘像素)、cv2.BORDER_REFLECT(镜像反射)等。

  • 双边滤波:

         双边滤波是一种非线性滤波技术,它考虑了像素的空间信息和灰度信息。这种方法对于保留边缘信息的同时去除噪点非常有效。可以使用OpenCV的cv2.bilateralFilter()函数实现双边滤波,如下所示:

  1. import cv2
  2. # 读取图像
  3. img = cv2.imread('image.jpg')
  4. # 进行双边滤波
  5. filtered_img = cv2.bilateralFilter(img, 9, 75, 75)
  6. # 显示原图和滤波后的图像
  7. cv2.imshow('Original Image', img)
  8. cv2.imshow('Filtered Image', filtered_img)
  9. cv2.waitKey(0)
  10. cv2.destroyAllWindows()
参数说明:

filtered = cv2.bilateralFilter(img, 9, sigmaColor=75, sigmaSpace=75)

函数的具体参数如下:

  • src:源图像,输入图像。
  • d:每个像素的直径,定义了像素的邻域大小。
  • sigmaColor:颜色空间的标准偏差。这个参数决定了在颜色空间中的平滑程度。sigmaColor的值越大,颜色平滑程度越强。
  • sigmaSpace:空间空间的标准偏差。这个参数决定了在空间域中的平滑程度。sigmaSpace的值越大,空间平滑程度越强。

7.图形轮廓

边缘检测--Canny函数

该函数通过计算图像中每个像素点的梯度值来检测边缘。其基本原理是:先对输入图像进行灰度化处理,然后进行高斯滤波以平滑图像并去除噪声,再使用Sobel算子计算梯度幅值和方向,对梯度幅值进行非极大值抑制以压缩边缘带宽,最后使用滞后阈值进行二值化得到二值化图像,再对二值化图像进行连接操作,将断开的边缘进行连接,得到最终的边缘图像

v2.Canny是OpenCV库中的一个函数,用于在图像中进行边缘检测。其函数语法如下:

cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])

参数说明:

  • image: 输入图像,可以是灰度图像或彩色图像。
  • threshold1: 第一个阈值,用于边缘检测中的滞后阈值,通常建议取值为100。
  • threshold2: 第二个阈值,用于边缘检测中的滞后阈值,通常建议取值为200。
  • edges:可选参数,用于存储边缘检测的结果。
  • apertureSize:可选参数,用于指定Sobel算子的大小,通常建议取值为3。
  • L2gradient:可选参数,用于指定是否使用L2 L2梯度计算方式,默认为False。

使用举例:

  1. import cv2
  2. # 读取图像
  3. image = cv2.imread('06.jpg')
  4. h,w,_=image.shape
  5. img=cv2.resize(image,(int(w/2),int(w/2)))
  6. # 将图像转换为灰度图像
  7. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  8. # 使用Canny边缘检测算法
  9. edges = cv2.Canny(gray, 100, 200)
  10. # 显示结果图像
  11. cv2.imshow('img', img)
  12. cv2.imshow('Edges', edges)
  13. cv2.waitKey(0)
  14. cv2.destroyAllWindows()
图片素材

结果展示

72af05dd6af649e49257d634a180c5c8.png

查询轮廓--findContours 函数

cv2.findContours 是 OpenCV 库中的一个函数,用于找到图像中的轮廓。

其基本语法如下(方括号内表示可选):
cv2.findContours(image, mode, method[, contours[, hierarchy]])

参数解释如下:

  • image:源图像,应该是灰度图。
  • mode:轮廓检索模式,常用的有 cv2.RETR_EXTERNAL(只检索最外面的轮廓)和 cv2.RETR_LIST(检索所有轮廓并将其保存到列表中)。
  • method:轮廓近似方法,常用的有 cv2.CHAIN_APPROX_SIMPLE(存储轮廓的终点)和 cv2.CHAIN_APPROX_TC89_L1(使用Ramer-Douglas-Peucker算法进行近似)。
  • contours:轮廓的输出参数。如果这个参数不为空,那么函数会直接在这个参数中填充找到的轮廓。否则,函数会创建一个新的列表来保存轮廓。
  • hierarchy:这个参数是用来描述轮廓的层次结构的。如果这个参数不为空,那么函数会在这个参数中填充轮廓的层次信息。否则,函数会忽略这个参数。

绘制轮廓--drawContours函数

cv2.drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point())

参数如下:

  • image:要绘制轮廓的输入图像。可以是彩色图像或灰度图像。
  • contours:输入轮廓的数组。轮廓是以向量形式存储的点集。每个轮廓可以由多个连续的点组成。
  • contourIdx:要绘制的轮廓的索引值。如果要绘制多个轮廓,则该参数用于指定绘制哪个轮廓。例如,如果要绘制第一个轮廓,可以将contourIdx设置为0,而-1表示绘制所有轮廓。
  • color:轮廓的颜色。可以使用RGB或灰度颜色空间表示颜色。
  • thickness:轮廓线条的粗细。可以是正整数或负整数。正整数表示使用填充轮廓,负整数表示使用空心轮廓。例如,thickness=2表示绘制填充轮廓,thickness=-1表示绘制空心轮廓。
  • lineType:轮廓线条的类型。可以是以下值之一:cv2.LINE_AA(抗锯齿线型)、cv2.LINE_4(4像素线型)、cv2.LINE_8(8像素线型)等。
  • hierarchy:轮廓的层次信息。如果不需要层次信息,可以使用默认值noArray()。
  • maxLevel:最大轮廓等级。如果需要绘制嵌套的轮廓,可以设置maxLevel的值来控制最大嵌套层级。
  • offset:偏移量。可以在绘制轮廓时设置偏移量来调整轮廓的位置。
  1. import numpy as np
  2. # 读取图像
  3. image = cv2.imread('image.png')
  4. # 转换为灰度图像
  5. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  6. # 使用Canny边缘检测
  7. edges = cv2.Canny(gray, 50, 150, apertureSize=3)
  8. # 查找轮廓
  9. contours, hierarchy = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  10. # 创建一个空白图像,用于绘制轮廓
  11. draw_image = np.zeros(image.shape, dtype="uint8")
  12. # 绘制轮廓
  13. cv2.drawContours(draw_image, contours, -1, (0,255,0), 3)
  14. # 显示原始图像和轮廓图像
  15. cv2.imshow("Original Image", image)
  16. cv2.imshow("Contours", draw_image)
  17. cv2.waitKey(0)
  18. cv2.destroyAllWindows()

37f23c62ba7b4bfbb7f9bd638efec5e9.png

计算轮廓的近似多边形--approxPolyDP函数

cv2.approxPolyDP() 是一个用于在 OpenCV 中近似多边形的函数。这个函数使用 Ramer-Douglas-Peucker 算法来减少多边形顶点的数量,同时尽可能保持多边形的形状。

cv.approxPolyDP(curve, epsilon, closed[, approxCurve=None])

参数说明:

  • curve:输入点集,二维点向量的集合
  • epsilon:近似精度,原始曲线与近似曲线之间的最大距离。如果epsilon为0,那么函数会返回原始轮廓的顶点集。随着epsilon值的增加,函数返回的近似多边形的顶点数会减少,但与原始轮廓的形状也会越偏离。
  • close: 闭合标志,True 表示闭合多边形,False 表示多边形不闭合
  • approxCurve:输出点集,表示拟合曲线或多边形,数据与输入参数 curve 一致

cv2.approxPolyDP()函数返回一个列表,其中包含近似多边形的顶点坐标。每个顶点的坐标是一个元组,包含x和y坐标。列表中的顶点按顺序排列,以绘制近似多边形。

近似多边形来寻找图形各个顶点坐标

  1. import numpy as np
  2. import cv2
  3. # 读取图像
  4. image = cv2.imread('06.jpg')
  5. h,w,_=image.shape
  6. image=cv2.resize(image,(int(w/2),int(w/2)))
  7. # 转换为灰度图像
  8. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  9. # 使用Canny边缘检测
  10. edges = cv2.Canny(gray, 50, 150, apertureSize=3)
  11. # 查找轮廓
  12. contours, hierarchy = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  13. # 创建一个空白图像,用于绘制轮廓
  14. draw_image = np.zeros(image.shape, dtype="uint8")
  15. # 绘制轮廓
  16. cv2.drawContours(draw_image, contours, -1, (0,255,0), 3)
  17. # 显示原始图像和轮廓图像
  18. cv2.imshow("Original Image", draw_image)
  19. cv2.waitKey()
  20. for contour in contours:
  21. peri=cv2.arcLength(contour,True)
  22. approx=cv2.approxPolyDP(contour,0.02*peri,True)
  23. if len(approx)==4:
  24. screenCnt=approx
  25. break
  26. cv2.drawContours(image,[screenCnt],-1,(0,255,0),2)
  27. screenCnt=screenCnt.reshape(4,2)
  28. for i in screenCnt:
  29. print("--------")
  30. cv2.circle(image,(i[0],i[1]), 3, (0,0,255), -1)
  31. cv2.putText(image,str(i[0])+","+str(i[1]) ,(i[0],i[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 1)
  32. # 显示原始图像和轮廓图像
  33. cv2.imshow("Original Image", image)
  34. cv2.imshow("Contours", draw_image)
  35. cv2.waitKey(0)
  36. cv2.destroyAllWindows()

96a3bc718fa048c58344666a0408745d.png

 检测车牌

看看就行

该代码出自github项目,这里只有利用轮廓和颜色检测车牌的代码。详细地址如下:

https://github.com/wzh191920/License-Plate-Recognition/tree/master

  1. import cv2
  2. import numpy as np
  3. from numpy.linalg import norm
  4. import sys
  5. import os
  6. import json
  7. SZ = 20 #训练图片长宽
  8. MAX_WIDTH = 1000 #原始图片最大宽度
  9. Min_Area = 2000 #车牌区域允许最大面积
  10. PROVINCE_START = 1000
  11. #读取图片文件
  12. def imreadex(filename):
  13. return cv2.imdecode(np.fromfile(filename, dtype=np.uint8), cv2.IMREAD_COLOR)
  14. def point_limit(point):
  15. if point[0] < 0:
  16. point[0] = 0
  17. if point[1] < 0:
  18. point[1] = 0
  19. #根据找出的波峰,分隔图片,从而得到逐个字符图片
  20. def seperate_card(img, waves):
  21. part_cards = []
  22. for wave in waves:
  23. part_cards.append(img[:, wave[0]:wave[1]])
  24. return part_cards
  25. class CardPredictor:
  26. def __init__(self):
  27. #车牌识别的部分参数保存在js中,便于根据图片分辨率做调整
  28. f = open('config.js')
  29. j = json.load(f)
  30. for c in j["config"]:
  31. if c["open"]:
  32. self.cfg = c.copy()
  33. break
  34. else:
  35. raise RuntimeError('没有设置有效配置参数')
  36. def __del__(self):
  37. self.save_traindata()
  38. def save_traindata(self):
  39. if not os.path.exists("svm.dat"):
  40. self.model.save("svm.dat")
  41. if not os.path.exists("svmchinese.dat"):
  42. self.modelchinese.save("svmchinese.dat")
  43. def accurate_place(self, card_img_hsv, limit1, limit2, color):
  44. row_num, col_num = card_img_hsv.shape[:2]
  45. xl = col_num
  46. xr = 0
  47. yh = 0
  48. yl = row_num
  49. #col_num_limit = self.cfg["col_num_limit"]
  50. row_num_limit = self.cfg["row_num_limit"]
  51. col_num_limit = col_num * 0.8 if color != "green" else col_num * 0.5#绿色有渐变
  52. for i in range(row_num):
  53. count = 0
  54. for j in range(col_num):
  55. H = card_img_hsv.item(i, j, 0)
  56. S = card_img_hsv.item(i, j, 1)
  57. V = card_img_hsv.item(i, j, 2)
  58. if limit1 < H <= limit2 and 34 < S and 46 < V:
  59. count += 1
  60. if count > col_num_limit:
  61. if yl > i:
  62. yl = i
  63. if yh < i:
  64. yh = i
  65. for j in range(col_num):
  66. count = 0
  67. for i in range(row_num):
  68. H = card_img_hsv.item(i, j, 0)
  69. S = card_img_hsv.item(i, j, 1)
  70. V = card_img_hsv.item(i, j, 2)
  71. if limit1 < H <= limit2 and 34 < S and 46 < V:
  72. count += 1
  73. if count > row_num - row_num_limit:
  74. if xl > j:
  75. xl = j
  76. if xr < j:
  77. xr = j
  78. return xl, xr, yh, yl
  79. def predict(self, car_pic, resize_rate=1):
  80. if type(car_pic) == type(""):
  81. img = imreadex(car_pic)
  82. else:
  83. img = car_pic
  84. pic_hight, pic_width = img.shape[:2]
  85. if pic_width > MAX_WIDTH:
  86. pic_rate = MAX_WIDTH / pic_width
  87. img = cv2.resize(img, (MAX_WIDTH, int(pic_hight*pic_rate)), interpolation=cv2.INTER_LANCZOS4)
  88. if resize_rate != 1:
  89. img = cv2.resize(img, (int(pic_width*resize_rate), int(pic_hight*resize_rate)), interpolation=cv2.INTER_LANCZOS4)
  90. pic_hight, pic_width = img.shape[:2]
  91. print("h,w:", pic_hight, pic_width)
  92. blur = self.cfg["blur"]
  93. #高斯去噪
  94. if blur > 0:
  95. img = cv2.GaussianBlur(img, (blur, blur), 0)#图片分辨率调整
  96. oldimg = img
  97. img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  98. #equ = cv2.equalizeHist(img)
  99. #img = np.hstack((img, equ))
  100. #去掉图像中不会是车牌的区域
  101. kernel = np.ones((20, 20), np.uint8)
  102. img_opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
  103. img_opening = cv2.addWeighted(img, 1, img_opening, -1, 0);
  104. #找到图像边缘
  105. ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
  106. img_edge = cv2.Canny(img_thresh, 100, 200)
  107. #使用开运算和闭运算让图像边缘成为一个整体
  108. kernel = np.ones((self.cfg["morphologyr"], self.cfg["morphologyc"]), np.uint8)
  109. img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel)
  110. img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel)
  111. #查找图像边缘整体形成的矩形区域,可能有很多,车牌就在其中一个矩形区域中
  112. try:
  113. contours, hierarchy = cv2.findContours(img_edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
  114. except ValueError:
  115. image, contours, hierarchy = cv2.findContours(img_edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
  116. contours = [cnt for cnt in contours if cv2.contourArea(cnt) > Min_Area]
  117. print('len(contours)', len(contours))
  118. #一一排除不是车牌的矩形区域
  119. car_contours = []
  120. for cnt in contours:
  121. rect = cv2.minAreaRect(cnt)
  122. area_width, area_height = rect[1]
  123. if area_width < area_height:
  124. area_width, area_height = area_height, area_width
  125. wh_ratio = area_width / area_height
  126. #print(wh_ratio)
  127. #要求矩形区域长宽比在2到5.5之间,2到5.5是车牌的长宽比,其余的矩形排除
  128. if wh_ratio > 2 and wh_ratio < 5.5:
  129. car_contours.append(rect)
  130. box = cv2.boxPoints(rect)
  131. box = np.int0(box)
  132. #oldimg = cv2.drawContours(oldimg, [box], 0, (0, 0, 255), 2)
  133. #cv2.imshow("edge4", oldimg)
  134. #cv2.waitKey(0)
  135. print(len(car_contours))
  136. print("精确定位")
  137. card_imgs = []
  138. #矩形区域可能是倾斜的矩形,需要矫正,以便使用颜色定位
  139. for rect in car_contours:
  140. if rect[2] > -1 and rect[2] < 1:#创造角度,使得左、高、右、低拿到正确的值
  141. angle = 1
  142. else:
  143. angle = rect[2]
  144. rect = (rect[0], (rect[1][0]+5, rect[1][1]+5), angle)#扩大范围,避免车牌边缘被排除
  145. box = cv2.boxPoints(rect)
  146. heigth_point = right_point = [0, 0]
  147. left_point = low_point = [pic_width, pic_hight]
  148. for point in box:
  149. if left_point[0] > point[0]:
  150. left_point = point
  151. if low_point[1] > point[1]:
  152. low_point = point
  153. if heigth_point[1] < point[1]:
  154. heigth_point = point
  155. if right_point[0] < point[0]:
  156. right_point = point
  157. if left_point[1] <= right_point[1]:#正角度
  158. new_right_point = [right_point[0], heigth_point[1]]
  159. pts2 = np.float32([left_point, heigth_point, new_right_point])#字符只是高度需要改变
  160. pts1 = np.float32([left_point, heigth_point, right_point])
  161. M = cv2.getAffineTransform(pts1, pts2)
  162. dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))
  163. point_limit(new_right_point)
  164. point_limit(heigth_point)
  165. point_limit(left_point)
  166. card_img = dst[int(left_point[1]):int(heigth_point[1]), int(left_point[0]):int(new_right_point[0])]
  167. card_imgs.append(card_img)
  168. #cv2.imshow("card", card_img)
  169. #cv2.waitKey(0)
  170. elif left_point[1] > right_point[1]:#负角度
  171. new_left_point = [left_point[0], heigth_point[1]]
  172. pts2 = np.float32([new_left_point, heigth_point, right_point])#字符只是高度需要改变
  173. pts1 = np.float32([left_point, heigth_point, right_point])
  174. M = cv2.getAffineTransform(pts1, pts2)
  175. dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))
  176. point_limit(right_point)
  177. point_limit(heigth_point)
  178. point_limit(new_left_point)
  179. card_img = dst[int(right_point[1]):int(heigth_point[1]), int(new_left_point[0]):int(right_point[0])]
  180. card_imgs.append(card_img)
  181. #cv2.imshow("card", card_img)
  182. #cv2.waitKey(0)
  183. #开始使用颜色定位,排除不是车牌的矩形,目前只识别蓝、绿、黄车牌
  184. colors = []
  185. for card_index,card_img in enumerate(card_imgs):
  186. green = yello = blue = black = white = 0
  187. card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
  188. #有转换失败的可能,原因来自于上面矫正矩形出错
  189. if card_img_hsv is None:
  190. continue
  191. row_num, col_num= card_img_hsv.shape[:2]
  192. card_img_count = row_num * col_num
  193. for i in range(row_num):
  194. for j in range(col_num):
  195. H = card_img_hsv.item(i, j, 0)
  196. S = card_img_hsv.item(i, j, 1)
  197. V = card_img_hsv.item(i, j, 2)
  198. if 11 < H <= 34 and S > 34:#图片分辨率调整
  199. yello += 1
  200. elif 35 < H <= 99 and S > 34:#图片分辨率调整
  201. green += 1
  202. elif 99 < H <= 124 and S > 34:#图片分辨率调整
  203. blue += 1
  204. if 0 < H <180 and 0 < S < 255 and 0 < V < 46:
  205. black += 1
  206. elif 0 < H <180 and 0 < S < 43 and 221 < V < 225:
  207. white += 1
  208. color = "no"
  209. limit1 = limit2 = 0
  210. if yello*2 >= card_img_count:
  211. color = "yello"
  212. limit1 = 11
  213. limit2 = 34#有的图片有色偏偏绿
  214. elif green*2 >= card_img_count:
  215. color = "green"
  216. limit1 = 35
  217. limit2 = 99
  218. elif blue*2 >= card_img_count:
  219. color = "blue"
  220. limit1 = 100
  221. limit2 = 124#有的图片有色偏偏紫
  222. elif black + white >= card_img_count*0.7:#TODO
  223. color = "bw"
  224. print(color)
  225. colors.append(color)
  226. print(blue, green, yello, black, white, card_img_count)
  227. #cv2.imshow("color", card_img)
  228. #cv2.waitKey(0)
  229. if limit1 == 0:
  230. continue
  231. #以上为确定车牌颜色
  232. #以下为根据车牌颜色再定位,缩小边缘非车牌边界
  233. xl, xr, yh, yl = self.accurate_place(card_img_hsv, limit1, limit2, color)
  234. if yl == yh and xl == xr:
  235. continue
  236. need_accurate = False
  237. if yl >= yh:
  238. yl = 0
  239. yh = row_num
  240. need_accurate = True
  241. if xl >= xr:
  242. xl = 0
  243. xr = col_num
  244. need_accurate = True
  245. card_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh-yl)//4 else card_img[yl-(yh-yl)//4:yh, xl:xr]
  246. if need_accurate:#可能x或y方向未缩小,需要再试一次
  247. card_img = card_imgs[card_index]
  248. card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
  249. xl, xr, yh, yl = self.accurate_place(card_img_hsv, limit1, limit2, color)
  250. if yl == yh and xl == xr:
  251. continue
  252. if yl >= yh:
  253. yl = 0
  254. yh = row_num
  255. if xl >= xr:
  256. xl = 0
  257. xr = col_num
  258. card_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh-yl)//4 else card_img[yl-(yh-yl)//4:yh, xl:xr]
  259. return card_imgs
  260. if __name__ == '__main__':
  261. c = CardPredictor()
  262. roi= c.predict("Screenshots\\6.jpeg")
  263. for i in roi:
  264. cv2.imshow("img",i)
  265. cv2.waitKey(0)

检测车牌:

ad907f50992a4bf4b48fd3571dc62189.png

展示结果:

e1c0af4991344b389d774f6bc666f4f0.png

有时候你会发现效果并不是很好,利用轮廓检测目标,过于落后,目前目标检测一般会运用深度学习,利用大量的数据来训练模型,目前比较好算法是YOLO,推荐如下文章

文章1 YOLOv5使用​​​​​  

文章2 YOLOV8使用(官网)推荐

 8.几何变形

视变换矩阵

cv2.getPerspectiveTransform(srcPoints,dstPoints)

是OpenCV库中的一个函数,用于获取透视变换矩阵。透视变换是一种几何变换,可以模拟图像通过透镜或经过其他透镜形状的物体时的视角效果。

具体参数包括:

  • srcPoints:输入的源点,它是一个4x2的矩阵,其中4是点的数量。每一行代表一个点的坐标,第一列是x坐标,第二列是y坐标。
  • dstPoints:目标的点,与源点类似,也是一个4x2的矩阵。

这个函数返回一个3x3的变换矩阵,可以用作cv2.warpPerspective函数的变换矩阵M。

M=cv2.getPerspectiveTransform(srcPoints,dstPoints)

cv2.warpPerspective(src, M, (src.shape[1], src.shape[0]))

函数来获取透视变换矩阵。最后,使用cv2.warpPerspective函数来应用这个透视变换到源图像上,并显示原图和转换后的图像。

下面是一个示例代码:

  1. import cv2
  2. import numpy as np
  3. # 源图像
  4. src = cv2.imread('src.jpg')
  5. # 源图像上的四个点(对应于透视变换的四个对应点)
  6. src_pts = np.float32([[10, 10], [100, 10], [10, 100], [100, 100]])
  7. # 目标图像上的对应点
  8. dst_pts = np.float32([[20, 20], [120, 20], [20, 120], [120, 120]])
  9. # 获取透视变换矩阵
  10. M = cv2.getPerspectiveTransform(src_pts, dst_pts)
  11. # 应用透视变换,注意,第二个参数是转换的源图像,第三个参数是输出图像的大小
  12. dst = cv2.warpPerspective(src, M, (src.shape[1], src.shape[0]))
  13. # 显示原图和转换后的图像
  14. cv2.imshow('src', src)
  15. cv2.imshow('dst', dst)
  16. cv2.waitKey(0)
  17. cv2.destroyAllWindows()

这段代码首先定义了源图像上的四个点和目标图像上对应的四个点。然后使用

图片矫正

使用举例:

测试使用图片

4bf861d66e3b44228fb8fe97d775e0cb.jpeg

代码部分

  1. import numpy as np
  2. import cv2
  3. def four_point_transform(img,rect):
  4. # 创建一个NumPy数组
  5. rect = np.array(rect, dtype=np.float32)
  6. (tl,tr,br,bl)=rect
  7. print(tl,tr,br,bl)
  8. #两点距离公式计算最大的高和宽
  9. heightA=np.sqrt(((br[0]-bl[0])**2)+(br[1]-bl[1])**2)
  10. heightB=np.sqrt(((tr[0]-tl[0])**2)+(tr[1]-tl[1])**2)
  11. maxHeight=max(int(heightA),int(heightB))
  12. widthA=np.sqrt((tr[0]-br[0])**2+(tr[1]-br[1])**2)
  13. widthB=np.sqrt((tl[0]-bl[0])**2+(tl[1]-bl[1])**2)
  14. maxWidth=max(int(widthA),int(widthB))
  15. #distinctive point
  16. dst=np.array([[0,0],[0,maxHeight-1],[maxWidth-1,maxHeight-1],[maxWidth-1,0]],dtype="float32")
  17. M=cv2.getPerspectiveTransform(rect,dst)
  18. warped=cv2.warpPerspective(img,M,(maxWidth,maxHeight))
  19. return warped
  20. # 读取图像
  21. image = cv2.imread('06.jpg')
  22. h,w,_=image.shape
  23. image=cv2.resize(image,(int(w/2),int(w/2)))
  24. # 转换为灰度图像
  25. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  26. # 使用Canny边缘检测
  27. edges = cv2.Canny(gray, 50, 150, apertureSize=3)
  28. # 查找轮廓
  29. contours, hierarchy = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  30. # 创建一个空白图像,用于绘制轮廓
  31. draw_image = np.zeros(image.shape, dtype="uint8")
  32. # 绘制轮廓
  33. cv2.drawContours(draw_image, contours, -1, (0,255,0), 3)
  34. # 显示原始图像和轮廓图像
  35. cv2.imshow("Original Image", draw_image)
  36. cv2.waitKey()
  37. for contour in contours:
  38. peri=cv2.arcLength(contour,True)
  39. approx=cv2.approxPolyDP(contour,0.02*peri,True)
  40. if len(approx)==4:
  41. screenCnt=approx
  42. break
  43. cv2.drawContours(image,[screenCnt],-1,(0,255,0),2)
  44. screenCnt=screenCnt.reshape(4,2)
  45. for i in screenCnt:
  46. cv2.circle(image,(i[0],i[1]), 3, (0,0,255), -1)
  47. cv2.putText(image,str(i[0])+","+str(i[1]) ,(i[0],i[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255), 1)
  48. # 显示原始图像和轮廓图像
  49. cv2.imshow("Original Image", image)
  50. cv2.imshow("Contours", draw_image)
  51. warped=four_point_transform(image,screenCnt)
  52. cv2.imshow("warped",warped)
  53. cv2.waitKey(0)
  54. cv2.destroyAllWindows()

结果演示:代码

befa9777bb9c42c99aba01f217382d26.png

仿射变换矩阵

cv2.getAffineTransform(srcPoints,dstPoints)

是OpenCV库中的一个函数,用于获取仿射变换矩阵。仿射变换是在几何中常用的一种变换,它保持了图像的“平行性”和“面积不变性”,也就是说,变换后的图像与原图像的平行线段和面积比都是相同的。

具体参数包括:

  • srcPoints:输入的源点,它是一个3 x 2的矩阵,其中3是点的数量。
  • dstPoints:目标的点,与源点类似,也是一个3 x 2的矩阵,这些点定义了源点对应目标图像上的点。

函数返回一个2x3的变换矩阵,可以用作cv2.warpAffine函数的变换矩阵M。
dst = cv2.warpAffine(src, M, (src.shape[1], src.shape[0]))

下面是一个示例代码:

  1. import cv2
  2. import numpy as np
  3. # 源图像
  4. src = cv2.imread('src.jpg')
  5. # 源图像上的三个点(对应于仿射变换的三个对应点)
  6. src_pts = np.float32([[10, 10], [100, 10], [10, 100]])
  7. # 目标图像上的对应点
  8. dst_pts = np.float32([[20, 20], [120, 20], [20, 120]])
  9. # 获取仿射变换矩阵
  10. M = cv2.getAffineTransform(src_pts, dst_pts)
  11. # 应用仿射变换,注意,第二个参数是转换的源图像,第三个参数是输出图像的大小
  12. dst = cv2.warpAffine(src, M, (src.shape[1], src.shape[0]))
  13. # 显示原图和转换后的图像
  14. cv2.imshow('src', src)
  15. cv2.imshow('dst', dst)
  16. cv2.waitKey(0)
  17. cv2.destroyAllWindows()

这段代码首先定义了源图像上的三个点和目标图像上对应的三个点。然后使用cv2.getAffineTransform函数来获取仿射变换矩阵。最后,使用cv2.warpAffine函数来应用这个仿射变换到源图像上,并显示原图和转换后的图像

仿射变换矩阵getAffineTransform和透视变换矩阵getPerspectiveTransform区别

区别如下:

  • 应用场景不同:仿射变换通常用于旋转、缩放、倾斜等变换,而透视变换通常用于模拟人眼视角的视觉效果。
  • 变换矩阵不同:仿射变换矩阵是一个2x3的矩阵,而透视变换矩阵是一个3x3的矩阵。
  • 保持特性不同:仿射变换保持了平行性、共线性和发生率,而透视变换不保持平行性、长度以及角度。

9.加载摄像或视频文件

cv2.VideoCapture()

 VideoCapture() 函数是OpenCV库中的一个类,用于捕获视频。它可以放两种参数,分别是视频文件路径或摄像头编号。

参数说明:

  • filename: 视频文件路径。例如:"test.mp4"。如果这个参数为空,函数会创建一个VideoCapture对象,但不会打开任何文件或设备。
  • camId: 摄像头编号,从0开始。如果这个参数为-1,函数会创建一个VideoCapture对象,但不会打开任何文件或设备。camId可以是一个整数(0表示默认摄像头)或一个文件名(以打开视频文件)

使用说明:

  • cv2.VideoCapture() 创建一个VideoCapture对象。
  • cap.read() 从视频中读取一帧。如果帧存在,则返回True。否则返回False。
  • cap.get(propId) 返回指定的帧的属性。propId可以是0到18之间的任何整数(取决于所支持的属性)。例如,帧的宽度和高度可以通过 cap.get(3) 和 cap.get(4) 获得。
  • cap.set(propId, value) 设置帧的属性。propId可以是0到18之间的任何整数(取决于所支持的属性)。例如,可以设置帧的宽度和高度为640x480。
  • cap.release() 释放VideoCapture对象并关闭视频文件或摄像头。

获取摄像头画面并保存为视频文件

  1. import cv2
  2. # 创建VideoCapture对象并打开视频文件
  3. cap = cv2.VideoCapture(0)
  4. # 获取视频的当前帧率
  5. fps = cap.get(cv2.CAP_PROP_FPS)
  6. # 创建VideoWriter对象,指定输出视频路径、帧率、分辨率等参数
  7. fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 选择视频编码器
  8. out = cv2.VideoWriter('output.mp4', fourcc, 30.0, (640, 480)) # 30帧每秒,640x480分辨率
  9. while cap.isOpened():
  10. ret, frame = cap.read() # 读取一帧
  11. if not ret:
  12. break
  13. #显示
  14. cv2.imshow("Frame", frame)
  15. # 将处理后的帧写入输出视频文件
  16. out.write(frame)
  17. # 等待按键按下,控制帧率
  18. if cv2.waitKey(1) & 0xFF == ord('q'):
  19. break
  20. # 释放VideoCapture对象和VideoWriter对象,并关闭窗口
  21. cap.release()
  22. out.release()
  23. cv2.destroyAllWindows()

效果展示

49b6d87d8dc645d590d8383a86dda4ee.png

读取视频文件,并显示

  1. import cv2
  2. # 创建VideoCapture对象并打开视频文件
  3. cap = cv2.VideoCapture('D:\\file\\ocr\\OCR\\test\\label\\04.mp4')
  4. fps=cap.get(cv2.CAP_PROP_FPS)
  5. frame_rate=int(fps)
  6. print(frame_rate)
  7. # 循环读取视频帧并显示
  8. while cap.isOpened():
  9. ret, frame = cap.read()
  10. frame=cv2.resize(frame,(640,480))
  11. cv2.imshow('Video', frame)
  12. if cv2.waitKey(frame_rate) == ord('q'): # 按q键退出播放
  13. break
  14. # 释放资源并关闭窗口
  15. cap.release()
  16. cv2.destroyAllWindows()

  

        

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号