随着人工智能技术的发展,可以使用AI来帮助监控和提醒人们保持社交距离。本文将介绍如何通过图像识别技术来检测人们的位置,并计算他们之间的距离,以判断他们是否过于接近。
首先,需要创建一个方法来计算两个人之间的距离。这可以通过计算两个边界框中心点之间的欧几里得距离来实现。以下是Python代码示例:
def calculate_distance_between_rectangle_centers(rect_center_1, rect_center_2):
    # 计算x和y坐标的绝对差值
    x_abs_diff = abs(rect_center_1[0] - rect_center_2[0])
    y_abs_diff = abs(rect_center_1[1] - rect_center_2[1])
    # 计算欧几里得距离
    return math.sqrt(x_abs_diff**2 + y_abs_diff**2)
    
上述函数是distance_analyzer模块的一个静态方法(参见Part_06文件夹中的distance_analyzer.py)。
为了找到过于接近的人,需要检查每个人的距离。在虚拟环境中,需要执行一个双重循环。但是,第i个人和第j个人之间的距离与第j个人和第i个人之间的距离是相同的。因此,嵌套for循环的迭代次数可以从j=1..N减少到j=i+1..N。以下是给定检测到的人的列表,找到过于接近的人的完整实现方法(也参见distance_analyzer.py):
def find_people_that_are_too_close(detection_results, distance_threshold):
    # 准备结果列表
    results = []
    # 获取矩形中心
    rectangle_centers = DistanceAnalyzer.get_rectangle_centers(detection_results)
    # 分析每个对象之间的距离
    N = len(detection_results)
    for i in range(N):
        for j in range(i+1, N):
            rect_center_1 = rectangle_centers[i]
            rect_center_2 = rectangle_centers[j]
            distance = DistanceAnalyzer.calculate_distance_between_rectangle_centers(rect_center_1, rect_center_2)
            # 如果对象之间的距离太近
            if (distance <= distance_threshold):
                results.append((detection_results[i]['rectangle'], detection_results[j]['rectangle']))
    return results
    
该方法接受两个参数:detection_results -AI模型返回的检测到的人的列表。注意,列表中的每个元素包含一个对象,该对象持有检测分数、边界框和标签。distance_threshold - 指定图像中人们可以靠得多近(以像素为单位)。如果计算出的人之间的距离低于这个值,边界框将被添加到返回的结果列表中。
为了指示过于接近的人,可以使用OpenCV的rectangle函数,如前所述。代码可能看起来与用来绘制图像中检测到的对象的边界框和标签的代码非常相似。但是,作为输入,取find_people_that_are_too_close返回的列表。记住,该方法返回的列表中每个元素包含两个矩形。这些矩形是违反社交距离规则的人的边界框(distance_threshold)。
def indicate_people_that_are_too_close(image, people_that_are_too_close, delay=0):
    # 准备窗口
    opencv.namedWindow(common.WINDOW_NAME, opencv.WINDOW_GUI_NORMAL)
    # 遍历对象(即一对矩形点)
    for i in range(len(people_that_are_too_close)):
        # 绘制每个矩形
        for j in range(len(people_that_are_too_close[i])):
            rectangle_points = people_that_are_too_close[i][j]
            opencv.rectangle(image, rectangle_points[0], rectangle_points[1], common.RED, common.LINE_THICKNESS)
    # 显示图像
    opencv.imshow(common.WINDOW_NAME, image)
    # 等待用户按下任意键
    opencv.waitKey(delay)
    
如上所示,使用namedWindow函数创建窗口,并使用imshow显示图像。其他组件与指示检测到的对象的情况几乎相同。
有了以上所有部分,可以创建如下主脚本(参见Part_07文件夹中的main.py):
import sys
sys.path.insert(1, '../Part_03/')
sys.path.insert(1, '../Part_05/')
sys.path.insert(1, '../Part_06/')
from inference import Inference as model
from image_helper import ImageHelper as imgHelper
from video_reader import VideoReader as videoReader
from distance_analyzer import DistanceAnalyzer as analyzer
if __name__ == "__main__":
    # 加载并准备模型
    model_file_path = '../Models/01_model.tflite'
    labels_file_path = '../Models/02_labels.txt'
    # 初始化模型
    ai_model = model(model_file_path, labels_file_path)
    # 初始化视频读取器
    video_file_path = '../Videos/01.mp4'
    video_reader = videoReader(video_file_path)
    # 检测和预览参数
    score_threshold = 0.4
    delay_between_frames = 5
    # 在视频序列中执行对象检测
    while (True):
        # 从视频文件中获取帧
        frame = video_reader.read_next_frame()
        # 如果帧是None,则跳出循环
        if (frame is None):
            break
        # 执行检测
        results = ai_model.detect_people(frame, score_threshold)
        # 找到过于接近的人
        proximity_distance_threshold = 50
        people_that_are_too_close = analyzer.find_people_that_are_too_close(results, proximity_distance_threshold)
        # 在图像中指示这些对象
        imgHelper.indicate_people_that_are_too_close(frame, people_that_are_too_close, delay_between_frames)