AI 社交距离检测器:处理 OpenCV 中的图像






4.58/5 (7投票s)
在本系列文章中,我们将探讨如何利用人工智能和深度学习对视频帧进行处理,以确保人们在人群中保持足够的社交距离。
2020年,随着COVID-19危机席卷全球,社交距离突然变得至关重要。社交距离措施对公共卫生至关重要,但同时在所有地方强制执行也是不可能的。
在本系列文章中,我们将探讨如何利用人工智能和深度学习对视频帧进行处理,以确保人们在人群中保持足够的社交距离。在本系列结束时,您将了解如何使用人工智能来判断人们是否没有遵守社交距离协议。
社交距离检测器,与其他任何检测器一样,通常应用于图像或视频序列。本系列文章将从解释如何使用Python 3和OpenCV捕获摄像头图像、读取和写入图像以及视频序列开始。下一步,我们将学习如何使用OpenCV为检测到的对象添加标注。
OpenCV是流行的开源、跨平台计算机视觉库,适用于实时计算机视觉应用。它为图像处理、对象检测、机器学习、深度学习、计算摄影等提供了便捷的API。要开始在您的Python 3应用程序中使用OpenCV,只需安装opencv-python
包。
pip3 install opencv-python
然后,像这样导入cv2
模块:
import cv2 as opencv
这样,您就准备好使用OpenCV了。在接下来的部分中,我们将使用OpenCV API读取、显示和写入图像。然后,我们将学习如何处理视频流,以及如何从网络摄像头捕获视频。您可以在此处找到配套代码:此处。
读取和显示静态图像
我们首先从Lena.png文件读取图像。我从维基百科下载了此文件。以下是加载和显示图像的完整Python脚本:
import cv2 as opencv
# Load image
file_path = 'Lena.png'
lena_img = opencv.imread(file_path)
# Display image
opencv.imshow('Lena', lena_img)
opencv.waitKey(0)
首先,我使用imread
函数从文件读取图像。我将此操作的结果存储在lena_img
变量中。然后,我使用imshow
方法显示此图像。此方法接受两个参数:将显示图像的窗口的标题,以及要显示的图像。请注意最后的waitKey
函数调用。它将阻塞脚本执行,直到用户按下任意键才显示图像。waitKey
函数的参数是超时时间。我传递0,表示无限超时。
运行上述脚本后,您将看到Lena图像。
请注意,imread
函数除了图像文件路径外,还接受一个可选参数,用于指示图像的颜色比例。您可以使用以下三个值中的一个:
IMREAD_GRAYSCALE
或1 – 图像将以灰度模式加载。IMREAD_COLOR
或0 – 图像将以彩色模式加载,忽略透明通道。IMREAD_UNCHANGED
或-1 – 图像将以原始颜色比例加载,并包含透明度。
IMREAD_COLOR
选项是默认选项。这就是为什么我们看到Lena图像的彩色版本。让我们看看如何以灰度模式加载图像。为此,请按如下方式修改imread
:
lena_img = opencv.imread(file_path, opencv.IMREAD_GRAYSCALE)
重新运行脚本后,您将看到以下输出:
写入图像
现在我们知道了如何读取和显示图像,让我们看看如何将图像写入磁盘。为此,我们将用以下语句扩展我们的脚本:
# Process image (Gaussian blur)
kernel_size = (11,11)
sigma_X = 0
lena_img_processed = opencv.GaussianBlur(lena_img, kernel_size, sigma_X)
# Save image
output_file_path = 'Lena-processed.jpg'
opencv.imwrite(output_file_path, lena_img_processed)
上述脚本首先使用OpenCV的GaussianBlur
方法,基于预定义的11x11像素内核大小模糊图像。模糊后的图像存储在lena_img_processed
变量中,然后使用imwrite
方法将其保存到Lena-processed.png文件中。如上所示,imwrite
接受两个参数。第一个是文件路径,第二个是要写入的图像。可选地,imwrite
接受一个压缩参数数组。您可以按以下方式传递它们:
opencv.imwrite(output_file_path, lena_img_processed, [int(opencv.IMWRITE_JPEG_QUALITY), 100])
修改脚本后的结果将是Lena-processed.jpg,看起来如下:
视频捕获
要从网络摄像头捕获帧,您可以使用OpenCV的VideoCapture
对象。其构造函数接受一个整数,表示摄像头的索引,或视频文件的路径。我从摄像头索引开始,传递0。
import cv2 as opencv
# Create video capture
video_capture = opencv.VideoCapture(0)
然后,要从网络摄像头捕获帧,您可以使用VideoCapture
类实例的read
函数。此方法返回捕获状态(一个布尔值)和捕获的帧。因此,下一步是使用imshow
函数检查状态并显示帧。
quit_key = ord('q')
# Display images in a loop until user presses 'q' key
while(True):
(status, camera_frame) = video_capture.read()
if(status):
opencv.imshow('Camera preview', camera_frame)
key = opencv.waitKey(10)
if(key == quit_key):
break
上述过程将一直持续到用户在键盘上按下“Q”为止。运行此脚本时,您将看到从默认网络摄像头捕获的视频序列。
将摄像头帧写入视频文件
您也可以将捕获的帧写入文件。为此,您可以使用VideoWriter
。创建此类型的对象时,您需要提供视频文件的路径、视频编解码器、帧率和帧大小。OpenCV使用fourCC编解码器,您可以使用VideoWriter_fourcc
对象创建它。您传递一系列字母,代表编解码器。例如,要使用MJPG编解码器,请按以下方式将每个字母作为参数传递:
codec = opencv.VideoWriter_fourcc('M','J','P','G')
这是一个完整的示例,演示如何将来自网络摄像头的视频序列写入视频文件(请参阅配套代码中的video_capture.py)。
import cv2 as opencv
quit_key = ord('q')
# Create video capture
video_capture = opencv.VideoCapture(0)
# Video writer
video_file_name = 'camera_capture.avi'
codec = opencv.VideoWriter_fourcc('M','J','P','G')
frame_rate = 25
video_writer = None
# Display images in a loop until user presses 'q' key
while(True):
(status, camera_frame) = video_capture.read()
if(status):
opencv.imshow('Camera preview', camera_frame)
if(video_writer == None):
frame_size = camera_frame.shape[-2::-1]
video_writer = opencv.VideoWriter(video_file_name,
codec, frame_rate, frame_size)
video_writer.write(camera_frame)
key = opencv.waitKey(10)
if(key == quit_key):
break
video_writer.release()
上述脚本扩展了从网络摄像头捕获帧的脚本,使用了VideoWriter
。请注意,我只在成功捕获第一帧后初始化一次VideoWriter
。我这样做是为了能够访问摄像头的帧大小。我从camera_frame
的shape
属性中解包帧大小。然后,我调用write
方法将新帧添加到视频文件中。写入完成后,我调用release
方法关闭VideoWriter
。
读取视频文件
在最后一步,我将向您展示如何使用OpenCV读取视频序列。再次使用VideoCapture
对象,但这次您需要传递视频文件名。
video_capture = opencv.VideoCapture(video_file_name)
然后,以与从网络摄像头捕获视频相同的方式读取连续帧。
video_capture.read()
您可以使用imshow
方法显示加载的帧。以下是实现此类功能的完整脚本(请参阅配套代码中的video_preview.py)。
import cv2 as opencv
video_file_name = 'camera_capture.avi'
frame_rate = 25
video_capture = opencv.VideoCapture(video_file_name)
while(True):
(status, camera_frame) = video_capture.read()
if(status):
opencv.imshow('Video file', camera_frame)
opencv.waitKey(int(1000/frame_rate))
else:
break
总结
我们学习了如何使用OpenCV对图像(加载、写入和显示)和视频流(读取和写入)执行基本操作。这与图像标注一起,将为构建我们的AI对象检测器奠定基础。在下一篇文章中,我们将学习如何为图像添加标注。这些标注将指示检测到的对象。