Python图像处理:OpenCV入门教程
- 一、Python图像处理概述
- 1 图像处理的基本概念
- 2 Python在图像处理中的优势
- 二、OpenCV简介
- 1 OpenCV的概述
- 2 OpenCV的特点
- 3 OpenCV的应用领域
- 三、OpenCV安装与环境配置
- 1 OpenCV的安装方法
- 2 OpenCV的环境配置
- 四、图像处理的基础知识
- 1 读取 显示 保存图像
- 2 进行图像尺寸大小的调整
- 3 修改图像的颜色空间
- 4 对图像进行几何变换
- 5 对图像进行阈值操作
- 6 图像卷积和滤波操作
- 五、图像处理的进阶技巧
- 1 图像的边缘检测
- 2 图像的特征提取
- 3 对图像进行轮廓提取
- 4 对图像进行分割和分离
- 5 对图像进行形态学操作
- 六、实际案例:基于OpenCV的图像处理项目演示
- 1 人脸识别示例
- 算法概述
- 代码实现
- 实现说明
- 2 动态手势识别示例
- 算法概述
- 代码实现
- 实现说明
- 3 视频监控和分析示例
- 算法概述
- 代码实现
- 实现说明
一、Python图像处理概述
1 图像处理的基本概念
所谓图像处理指利用计算机技术对图像进行处理和增强的过程。它是计算机视觉的组成部分,可应用于多个领域。
2 Python在图像处理中的优势
Python是一门高级编程语言其在数据分析、机器学习和人工智能等领域都有广泛的应用。在图像处理领域中,Python与OpenCV相关联, OpenCV是一种开源计算机视觉库,由Intel公司研发,可用于图像处理、视频处理和机器视觉等领域。
Python在图像处理领域中有多种优势包括:
- 代码简洁易懂、使用方便、不需要太多的编程经验
- 有强大的图像处理库(如OpenCV),可支持多种图像格式
- 能够与其他Python库(如NumPy、SciPy)进行无缝集成
二、OpenCV简介
1 OpenCV的概述
OpenCV是一种计算机视觉开源库。它由英特尔公司研发,可支持多种编程语言,如C++、Python 和 Java 等。 主要用于开发实时的计算机视觉应用程序。它具有强大的图像处理功能,支持多种图像格式和数学运算,使开发人员可以很容易地使用和定制这个库。 另外,它还具有良好的跨平台性能,能够在Windows、Linux 和 macOS 等多个操作系统上运行。
2 OpenCV的特点
OpenCV主要有以下特点:
- 能够处理图像和视频,支持多种图像格式
- 提供了基本的图像处理函数(如滤波、形态学操作、边缘检测等)
- 支持人脸识别、目标追踪、运动分析等高级功能
- 对于计算效率有所优化,提供C++和Python两种编程方式
- 具有良好的跨平台性能,可以在Windows、Linux和macOS等多个操作系统上运行
- 可以进行图像/视频的导入和导出
3 OpenCV的应用领域
OpenCV广泛应用于计算机视觉和机器视觉领域,包括:
- 人脸识别
- 目标检测和跟踪
- 动作捕捉
- 视频分析和处理
- 无人驾驶汽车
- 增强现实技术等
三、OpenCV安装与环境配置
1 OpenCV的安装方法
在Python中安装OpenCV的最简单方法是使用pip命令命令如下:
pip install opencv-python
这个命令将会自动下载和安装OpenCV最新稳定版本。
2 OpenCV的环境配置
要使用OpenCV进行图像处理需要对环境进行配置。首先,需要在Python中导入OpenCV库。在Python中,可以使用以下代码:
import cv2
如果没有出现错误提示则说明OpenCV库已成功导入。接下来,我们就可以使用OpenCV库中的函数来进行图像处理啦!
四、图像处理的基础知识
在进行图像处理前首先要了解一些基础的知识。这些知识包括如何读取、显示、保存图片;如何调整图像的大小和颜色空间。如何对图像进行几何变换、阈值操作和卷积滤波等操作。
1 读取 显示 保存图像
在Python中可以使用OpenCV库中的函数来读取、显示和保存图像。具体代码如下所示:
import cv2# 读取图像
img = cv2.imread('image.jpg')# 显示图像
cv2.imshow('Image', img)
cv2.waitKey(0)# 保存图像
cv2.imwrite('new_image.jpg', img)
其中cv2.imread()
函数用于读取一张图像,cv2.imshow()
函数用于显示图像,cv2.waitKey()
函数用于等待键盘输入,cv2.imwrite()
函数用于将图像保存为指定文件。在运行程序时,按下任意键即可关闭图像窗口。
2 进行图像尺寸大小的调整
在实际应用中可能需要调整图像的大小。我们可以使用cv2.resize()
函数对图像的尺寸进行调整。具体代码如下:
import cv2# 读取图像
img = cv2.imread('image.jpg')# 调整图像大小
resized_img = cv2.resize(img, (600, 600))# 显示原图和调整后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Resized Image', resized_img)
cv2.waitKey(0)# 保存调整后的图像
cv2.imwrite('resized_image.jpg', resized_img)
其中cv2.resize()
函数的第二个参数为元组型式的新图像大小,即新的图像宽和高。调整大小后,可以通过与原始图像进行比较来观察结果。
3 修改图像的颜色空间
图像的颜色空间包括灰度空间和彩色空间。我们可以使用cv2.cvtColor()
函数对图像的颜色空间进行转换。具体代码如下:
import cv2# 读取图像
img = cv2.imread('image.jpg')# 将图像转换为灰度空间
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 显示原图和灰度图
cv2.imshow('Original Image', img)
cv2.imshow('Gray Image', gray_img)
cv2.waitKey(0)# 保存灰度图
cv2.imwrite('gray_image.jpg', gray_img)
其中cv2.cvtColor()
函数的第一个参数为原始图像,第二个参数指定了转换后的颜色空间。在本例中我们将原始图像转换为灰度空间(GRAY),并将其保存为灰度图像。
4 对图像进行几何变换
通过对图像进行几何变换可以实现图像的旋转、平移、缩放等操作。下面以旋转为例介绍如何对图像进行几何变换。具体代码如下:
import cv2
import numpy as np# 读取图像
img = cv2.imread('image.jpg')# 获取图像的旋转矩阵
rows, cols = img.shape[:2]
M = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 1)# 进行图像旋转
rotated_img = cv2.warpAffine(img, M, (cols, rows))# 显示原图和旋转后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Rotated Image', rotated_img)
cv2.waitKey(0)# 保存旋转后的图像
cv2.imwrite('rotated_image.jpg', rotated_img)
其中cv2.getRotationMatrix2D()
函数用于获取旋转变换矩阵,指定旋转中心和旋转角度(45度),cv2.warpAffine()
函数用于进行旋转操作。
5 对图像进行阈值操作
在进行阈值操作时可以将图像像素的灰度值(或者RGB值)与指定阈值进行比较,将大于(或小于)阈值的像素值设为一个特定的值,将小于(或大于)阈值的像素值设为另一个特定的值。下面以将图像灰度值二值化为例,介绍如何进行阈值操作。具体代码如下:
import cv2# 读取图像并转换为灰度图
img = cv2.imread('image.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 进行阈值操作
_, threshold_img = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)# 显示原图和阈值化后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Threshold Image', threshold_img)
cv2.waitKey(0)# 保存阈值化后的图像
cv2.imwrite('threshold_image.jpg', threshold_img)
其中cv2.threshold()
函数用于进行阈值操作。该函数的第二个参数为指定的阈值,第三个参数为大于阈值的像素值,第四个参数为小于阈值的像素值。
6 图像卷积和滤波操作
图像卷积和滤波操作是对图像进行平滑和增强的一种基本方法。我们可以使用cv2.filter2D()
函数来进行卷积和滤波操作。具体代码如下:
import cv2
import numpy as np# 读取图像
img = cv2.imread('image.jpg')# 定义滤波器
kernel = np.ones((5, 5), np.float32) / 25# 进行滤波操作
filtered_img = cv2.filter2D(img, -1, kernel)# 显示原图和滤波后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Filtered Image', filtered_img)
cv2.waitKey(0)# 保存滤波后的图像
cv2.imwrite('filtered_image.jpg', filtered_img)
其中cv2.filter2D()
函数用于执行卷积和滤波操作。本例中采用的是平均滤波器,其每个像素值都等于周围 5x5 区域像素值的平均值
五、图像处理的进阶技巧
在掌握了基本的图像处理知识后,我们可以继续学习一些进阶的技巧,如图像的边缘检测、特征提取、轮廓提取、分割和分离、形态学操作等。本节将为大家介绍这些技巧的基础概念和实现方法。
1 图像的边缘检测
边缘检测是图像处理中的一项常见任务。其目的是找到图像中明显的边缘、轮廓或线条。可以使用一些特定的算法来实现图像的边缘检测如Sobel算子、Laplacian算子和Canny算子。下面以Canny算子为例,介绍如何对图像进行边缘检测。具体代码如下:
import cv2# 读取图像并转换为灰度图
img = cv2.imread('image.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 进行边缘检测
edges = cv2.Canny(gray_img, 100, 200)# 显示原图和边缘检测后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Edges', edges)
cv2.waitKey(0)# 保存边缘检测后的图像
cv2.imwrite('edges.jpg', edges)
其中cv2.Canny()
函数用于进行边缘检测。该函数的第二个和第三个参数为指定的阈值,用于控制边缘检测的敏感度。
2 图像的特征提取
图像的特征提取是将图像中的信息转换成数值特征的一种处理方法。在图像识别、目标检测等领域中广泛应用。我们可以使用一些常用的算法对图像进行特征提取,如SIFT、SURF、ORB等。下面以SIFT算法为例,介绍如何对图像进行特征提取。具体代码如下:
import cv2# 读取图像并转换为灰度图
img = cv2.imread('image.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 初始化SIFT算法对象并提取图像的关键点和描述符
sift = cv2.xfeatures2d.SIFT_create()
keypoints, descriptors = sift.detectAndCompute(gray_img, None)# 在图像中绘制关键点
res_img = cv2.drawKeypoints(img, keypoints, None)# 显示原图和特征点标注后的图像
cv2.imshow('Original Image', img)
cv2.imshow('SIFT Features', res_img)
cv2.waitKey(0)# 保存特征点标注后的图像
cv2.imwrite('sift_features.jpg', res_img)
其中cv2.xfeatures2d.SIFT_create()
函数用于初始化SIFT算法对象,sift.detectAndCompute()
函数用于提取图像的关键点和描述符,cv2.drawKeypoints()
函数用于在图像中绘制关键点。
3 对图像进行轮廓提取
轮廓提取是指对图像进行边界提取和连通性检查,获取图像中的轮廓形状。我们可以使用OpenCV库的cv2.findContours()
函数对图像进行轮廓提取。具体代码如下:
import cv2# 读取图像并转换为灰度图
img = cv2.imread('image.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 进行边缘检测
edges = cv2.Canny(gray_img, 100, 200)# 进行轮廓提取
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 在图像中绘制轮廓
res_img = cv2.drawContours(img, contours, -1, (0, 255, 0), 2)# 显示原图和绘制轮廓后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Contours', res_img)
cv2.waitKey(0)# 保存绘制轮廓后的图像
cv2.imwrite('contours.jpg', res_img)
其中cv2.findContours()
函数用于进行轮廓提取,该函数的第二个参数指定了轮廓的检索模式,第三个参数指定了轮廓的近似方法,cv2.drawContours()
函数用于在图像中绘制轮廓。
4 对图像进行分割和分离
图像分割和分离是将一幅复杂的图像拆分成多个独立的区域或图像的处理方法可以使用一些算法对图像进行分割和分离如GrabCut算法、K-means算法等。下面以K-means算法为例,介绍如何对图像进行分割和分离。具体代码如下:
import cv2
import numpy as np# 读取图像
img = cv2.imread('image.jpg')# 获取图像像素并进行K-means聚类
pixel_values = img.reshape((-1, 3))
pixel_values = np.float32(pixel_values)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2)
_, labels, center = cv2.kmeans(pixel_values, 5, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)# 对图像进行分割和分离
center = np.uint8(center)
res_img = center[labels.flatten()]
res_img = res_img.reshape((img.shape))# 显示原图和分割后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Segmented Image', res_img)
cv2.waitKey(0)# 保存分割后的图像
cv2.imwrite('segmented_image.jpg', res_img)
其中cv2.kmeans()
函数用于进行K-means聚类,该函数的第二个参数指定了聚类数目,第三个参数为初始化的聚类中心,np.uint8()
函数用于将聚类中心转换为无符号8位整型。
5 对图像进行形态学操作
形态学操作是一种常见的图像处理方法。其可以对图像进行膨胀、腐蚀、开运算、闭运算等处理,用于图像去噪、分割和检测等任务。我们可以使用OpenCV库的cv2.erode()
、cv2.dilate()
、cv2.morphologyEx()
函数对图像进行形态学操作。下面以开运算为例,介绍如何对图像进行形态学操作。具体代码如下:
import cv2
import numpy as np# 读取图像并转换为灰度图
img = cv2.imread('image.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 对图像进行二值化处理
_, binary_img = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)# 进行开运算操作
kernel = np.ones((5, 5), np.uint8)
opened_img = cv2.morphologyEx(binary_img, cv2.MORPH_OPEN, kernel)# 显示原图和开运算后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Opened Image', opened_img)
cv2.waitKey(0)# 保存开运算后的图像
cv2.imwrite('opened_image.jpg', opened_img)
其中cv2.threshold()
函数用于进行图像二值化处理,cv2.morphologyEx()
函数用于进行形态学操作,该函数的第二个参数指定了操作的类型,第三个参数为核函数,本例中使用了5x5的全1核函数进行开运算操作。
至此已经掌握了图像处理的进阶技巧,包括图像的边缘检测、特征提取、轮廓提取、分割和分离、形态学操作等。这些技巧可以帮助您更好地处理图像,并提供更多的图像特征信息,为后续的处理任务打下良好的基础。
六、实际案例:基于OpenCV的图像处理项目演示
1 人脸识别示例
算法概述
人脸识别是一种基于图像和视频的自动识别技术。在图像处理中,我们通常使用基于人脸特征的分类器来进行人脸检测和人脸识别。OpenCV提供了许多基于人脸识别的分类器,包括Haar分类器、LBP分类器等。我们可以使用这些分类器来构建我们自己的人脸识别系统。
代码实现
# 导入OpenCV和numpy库
import cv2
import numpy as np# 加载人脸分类器
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')# 加载图片并转化为灰度图像
img = cv2.imread('img.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 检测人脸
faces = face_cascade.detectMultiScale(gray, 1.2, 5)# 绘制矩形框
for (x,y,w,h) in faces:cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)# 显示结果
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
实现说明
首先需要导入需要的库其中cv2
模块是OpenCV在Python3.0下的接口,而numpy
是科学计算工具包,这里用于数组处理。
import cv2
import numpy as np
接着需要加载一个已经训练好的人脸分类器。这里使用的是Haar分类器,可以通过OpenCV提供的CascadeClassifier
类来加载:
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
然后需要加载要进行人脸识别的图片并转成灰度图像,因为在灰度图像下计算量更小,处理速度更快。可以使用imread()
函数来加载图片,使用cvtColor()
函数将图片转为灰度图像。
img = cv2.imread('img.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
接下来可以使用detectMultiScale()
函数来检测图片中的人脸,该函数用于检测一张图片的多个目标,因此被称为级联检测器。这个函数比较复杂,其中的参数需要认真设置常见的参数如下:
gray
:输入的灰度图像数据;1.2
:表示图像缩放比例。5
:表示目标的最小邻居数目,即至少要检测到5个才算检测到人脸。
faces = face_cascade.detectMultiScale(gray, 1.2, 5)
最后将检测到的人脸用矩形框标记出来。其中,(x,y)
表示矩形框的左上角坐标,w
和h
是矩形框的宽和高。
for (x,y,w,h) in faces:cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
最后使用imshow()
函数来显示最终的图片,waitKey()
函数等待用户在键盘上按下一个键,destroyAllWindows()
函数用于关闭所有打开的窗口。
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
2 动态手势识别示例
算法概述
手势识别是一种基于图像和视频的自动识别技术, 它将人的手部动作转化为机器能够识别的语言和动作,更加人性化亲和。手势识别技术广泛应用在智能家居、无人驾驶等领域,成为人们生活中重要的一部分。
代码实现
# 导入OpenCV和numpy库
import cv2
import numpy as np# 常量定义
camera_width = 640
camera_height = 480
camera_fps = 30# 手势分类器定义
gesture_cascade = cv2.CascadeClassifier('palm.xml')# 打开摄像头
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, camera_width)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, camera_height)
camera.set(cv2.CAP_PROP_FPS, camera_fps)# 循环检测
while True:# 读取当前帧ret, frame = camera.read()# 灰度转换gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 手势检测gestures = gesture_cascade.detectMultiScale(gray, 1.3, 5)# 绘制矩形框for (x, y, w, h) in gestures:cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)# 显示结果cv2.imshow('Gesture detection', frame)# 等待用户输入if cv2.waitKey(1) & 0xFF == ord('q'):break# 关闭摄像头,并销毁所有窗口
camera.release()
cv2.destroyAllWindows()
实现说明
首先需要导入需要的库 cv2
模块是OpenCV在Python3.0下的接口,这里用于视频流的采集和处理;numpy
是科学计算工具包,这里用于数组处理。
import cv2
import numpy as np
接着需要打开摄像头并设置其参数。读取摄像头的方法是使用VideoCapture()
函数。可以通过调用摄像头对象的set()
方法,对其参数进行配置,包括帧率、分辨率等参数。
camera_width = 640
camera_height = 480
camera_fps = 30camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, camera_width)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, camera_height)
camera.set(cv2.CAP_PROP_FPS, camera_fps)
然后需要加载一个训练好的手势分类器。这里使用的是palm.xml分类器。
gesture_cascade = cv2.CascadeClassifier('palm.xml')
接下来在while循环中能够不断读取摄像头中的视频帧。然后将当前视频帧转换为灰度图像,用于降低计算量和提高处理速度。然后使用detectMultiScale()
函数检测当前帧中的手势。该函数用于检测一张图片的多个目标,因此被称为级联检测器。常见的参数解释如下:
gray
:输入灰度图像,该参数需要在代码中设置过;1.3
:表示图像缩放比例;5
:表示目标的最小邻居数目,即至少要检测到5个才算检测到手势。
ret, frame = camera.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gestures = gesture_cascade.detectMultiScale(gray, 1.3, 5)
最后将检测到的手势用矩形框标记出来。其中,(x, y)
表示矩形框的左上角坐标,w
和h
是矩形框的宽和高。
for (x, y, w, h) in gestures:cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
最后在while循环之外关闭摄像头并销毁所有窗口
camera.release()
cv2.destroyAllWindows()
3 视频监控和分析示例
算法概述
视频监控和分析系统可以实现对场景中的人和物进行自动检测、跟踪和分析,例如运动物体检测、人脸识别、烟火检测等。
代码实现
# 导入OpenCV, numpy和datetime库
import cv2
import numpy as np
import datetime# 常量定义
camera_width = 640
camera_height = 480
camera_fps = 30# 打开摄像头
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, camera_width)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, camera_height)
camera.set(cv2.CAP_PROP_FPS, camera_fps)# 初始化运动检测器
foreground_detector = cv2.createBackgroundSubtractorMOG2(history=100, varThreshold=50)# 循环处理每一帧
while True:# 读取当前帧ret, frame = camera.read()# 转换图像为灰度图gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 移除背景并二值化fgmask = foreground_detector.apply(gray)fgmask = cv2.threshold(fgmask, 200, 255, cv2.THRESH_BINARY)[1]# 膨胀并腐蚀处理kernel = np.ones((5, 5), np.uint8)fgmask = cv2.dilate(fgmask, kernel, iterations=2)fgmask = cv2.erode(fgmask, kernel, iterations=2)# 检测并绘制运动物体的边框contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)for c in contours:if cv2.contourArea(c) < 500:continue(x, y, w, h) = cv2.boundingRect(c)cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)# 显示结果cv2.putText(frame, datetime.datetime.now().strftime('%A %d %B %Y %I:%M:%S%p'),(10, camera_height - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)cv2.imshow('Video Surveillance', frame)# 等待用户输入if cv2.waitKey(1) == ord('q'):break# 关闭摄像头,并销毁所有窗口
camera.release()
cv2.destroyAllWindows()
实现说明
首先需要导入需要的库。这里引入了 cv2
模块是OpenCV在Python3.0下的接口,这里用于视频流的采集和处理;numpy
是科学计算工具包,这里用于数组处理;datetime
是用来在视频流上支持给视频帧打日期时间标签的库。
import cv2
import numpy as np
import datetime
接着需要打开摄像头并设置其参数。读取摄像头的方法是使用 VideoCapture()
函数。可以通过调用摄像头对象的set()
方法,对其参数进行配置,包括帧率、分辨率等参数。
camera_width = 640
camera_height = 480
camera_fps = 30camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, camera_width)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, camera_height)
camera.set(cv2.CAP_PROP_FPS, camera_fps)
然后需要初始化运动检测器。在代码中使用了 createBackgroundSubtractorMOG2()
方法创建了一个基于Mixtures of Gaussians (MOG2)的背景减法器,并为其设置了100帧的历史记录和50的变化阈值。
foreground_detector = cv2.createBackgroundSubtractorMOG2(history=100, varThreshold=50)
接下来在while循环中能够不断读取摄像头中的视频帧,并进行多步处理。先将当前视频帧转换为灰度图像,用于降低计算量和提高处理速度。然后,我们使用 apply()
函数移除输入灰度图像中的背景。然后将减法后的矩阵进行二值化处理。
ret, frame = camera.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)fgmask = foreground_detector.apply(gray)
fgmask = cv2.threshold(fgmask, 200, 255, cv2.THRESH_BINARY)[1]
接下来使用开操作对二值图像进行膨胀和腐蚀处理,去除附在对象周围的杂质点。
kernel = np.ones((5, 5), np.uint8)
fgmask = cv2.dilate(fgmask, kernel, iterations=2)
fgmask = cv2.erode(fgmask, kernel, iterations=2)
接下来使用 findContours()
函数来查找二值图像中的连通域,并绘制边框。在绘制边框时,我们需要先判断面积是否满足检测的条件。
contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
if cv2.contourArea(c) < 500:continue(x, y, w, h) = cv2.boundingRect(c)cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
最后在while循环之外关闭摄像头并销毁所有窗口。
camera.release()
cv2.destroyAllWindows()
我们还在frame
中添加了日期时间标签,以显示当前视频帧被处理的时间。
cv2.putText(frame, datetime.datetime.now().strftime('%A %d %B %Y %I:%M:%S%p'),(10, camera_height - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)