AI | 重明

第一个AI?

“这次任务繁重,诸君共勉!”

1300多个视频,每一个都有六个小时的时长,反复观看,持续三天

要在浩如烟海的视频画面中识别出携带有效信息的三个人,尤其是对于刚刚接触业务工作的我们来说,更是堪比青天揽星

第一次听到这个任务的我,也是沉默了一会儿,唉,是个体力活啊

“大家不用有很大的压力,我们也向很多公司寻求了技术支持,比如某华、某康威视,他们的图像识别技术在国内也是领先水平,有他们的协助,再加上大家的共同努力,相信我们一定可以取得非常不错的成绩。”

嗯?技术支持?图像识别?脑袋轰的一下炸开,我知道python有一个开源库opencv​,但是我平时只是拿来提取简单的色素块进行比较排序,还没试过对复杂图像和长时间视频进行一个深度学习、识别、提取的过程,但这次时间跨度有点长,那为什么我不自己去写一个AI帮我去看呢?🤔

OpenCV

假设,我们有一个西瓜🍉那我们如何判断这是一个西瓜的呢?比如说,我们可以从通过分析它的颜色、形状和质地,都可以说它是西瓜🍉。

下一个问题,计算机怎么知道这是西瓜🍉呢?计算机是没有生活经验的,但是计算机视觉的功能可以通过识别图像的线索来进行判断。而这些线索称为图像的特征,而我们要做的就是帮助计算机检测图像中的各种特征。

听上去是不是简单?但写起来还是挺麻烦的,尤其是对我这种基本没接触过深度学习与神经网络的初学者来讲。。。

但可以先确定一下具体步骤,首先要根据照片生成人体检测模型:

  1. 收集和准备训练数据集:获取包含人体的照片,并为每个人体标注边界框或关键点。可以使用公开的人体检测数据集,如COCO​、MPII​等,或者自己手动标注数据集。
  2. 数据预处理:对收集到的数据集进行预处理,包括图像的调整大小、裁剪、归一化等操作,以便于模型的训练和输入。
  3. 构建模型:选择适合人体检测任务的模型架构,如Faster R-CNN​、YOLO​、SSD​等。可以使用现有的模型架构,并根据需要进行修改或微调。
  4. 训练模型:使用准备好的数据集对模型进行训练。在训练过程中,你需要定义损失函数、选择优化算法,并设置训练的超参数。
  5. 模型评估和调优:在训练完成后,使用验证集或测试集对模型进行评估,了解模型的性能。根据评估结果,可以进行模型的调优,如调整网络结构、调整超参数等。
  6. 导出和使用模型:训练完成后,将模型导出为可用的格式,比如caffemodel​、prototx​,然后再用该模型进行人体检测。

上面这些数据处理、模型训练,我相信公司已经在做了,所以我打算直接嫖他们的训练模型(嘿嘿嘿)

目标识别

然后麻烦的就是目标的判断算法,这几天看大家的照片,都是在以胸前图案为主,我一开始也是这样想的,但是在写代码的时候就发现了问题:

  1. 监控的画质并不是很清晰。
  2. 中午阳光强烈,衣服上的图案可能与衣服本身颜色对比不明显,很难提取。

似乎停滞了?

“目标必须要共同行走一段距离,两者之间相距不得超过1.5米。”
所以我果断换了思路——距离计算

虽然这样也会有一定的问题,比如拍摄角度问题,可能就要根据透视原理之类的适当缩放那个距离数值,但是比起图案识别那个思路来讲,难度小,误差也小,实现起来也简单。

我们可以先对两人添加矩形框,然后取矩形框对角线的交点作为两人的中心点,任意连接两个中心点形成线段,判断线段长度是否持续四秒钟小于1.5米,符合条件的话便对此时画面进行捕捉提取。

而距离度量的话,我选择了欧几里得距离公式(欧氏距离)进行计算:

​​image​​

代码编写

第一次自己操刀写的一个AI,说实话写的不行,不美观,思路还有点杂乱。。。

(这是思路的初稿,二代修正在写了)

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import cv2
import time
import math
import numpy as np
import torch
import torchvision.transforms as transforms
import tensorflow as tf
import tf2caffe
import caffe
import random
import os

# 自定义数据路径
data_dir = 'path1'
train_txt = 'path2'
val_txt = 'path3'

# 定义模型结构
model_template = '''
name: "PersonDetection"
layer {{
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {{
    phase: TRAIN
  }}
  transform_param {{
    mirror: true
    crop_size: 227
    mean_value: 104
    mean_value: 117
    mean_value: 123
  }}
  data_param {{
    source: "{TRAIN_TXT}"
    batch_size: 32
    backend: LMDB
  }}
}}
layer {{
  name: "data"
  type: "Data"
  top: "data"
  top: "label"
  include {{
    phase: TEST
  }}
  transform_param {{
    mirror: false
    crop_size: 227
    mean_value: 104
    mean_value: 117
    mean_value: 123
  }}
  data_param {{
    source: "{VAL_TXT}"
    batch_size: 32
    backend: LMDB
  }}
}}
layer {{
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  convolution_param {{
    num_output: 96
    kernel_size: 11
    stride: 4
  }}
}}
layer {{
  name: "relu1"
  type: "ReLU"
  bottom: "conv1"
  top: "conv1"
}}
# 其他层定义...
'''

# 生成prototxt文件
train_prototxt = 'train.prototxt'
val_prototxt = 'val.prototxt'

with open(train_prototxt, 'w') as f:
    f.write(model_template.format(TRAIN_TXT=train_txt))

with open(val_prototxt, 'w') as f:
    f.write(model_template.format(VAL_TXT=val_txt))

# 训练模型
caffe.set_mode_gpu()
solver = caffe.SGDSolver('solver.prototxt')
solver.solve()

# 保存模型权重
trained_caffemodel = 'trained.caffemodel'
solver.net.save(trained_caffemodel)

# 加载模型文件
net = cv2.dnn.readNetFromCaffe('deploy.prototxt', 'model.caffemodel')
# 加载目标视频
video = cv2.VideoCapture("video.mp4")
# 获取视频帧率
fps = video.get(cv2.CAP_PROP_FPS)
# 定义输出图片路径
output_path = 'output_path'
# 初始化变量
start_frame = 0
end_frame = 0
# 定义距离计算:欧几里得距离公式
def calculate_distance(point1, point2):
    x1, y1 = point1
    x2, y2 = point2
    distance = np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
    return distance
# 取中心点
def calculate_center(box):
    x1, y1, x2, y2 = box
    center_x = int((x1 + x2) // 2)
    center_y = int((y1 + y2) // 2)
    centers.append(center_x, center_y)

# 记录每个人物的最近一次检测时间
person_last_detected = {}

# 定义变量和列表
threshold_distance = 100  # 这里我们假设1.5米对应的像素距离是100
duration_threshold = 3  # 持续时间阈值(单位:秒)
start_time = None  # 记录开始时间
center_points = []  # 存储中心点坐标的列表

while video.isOpened():
    ret, frame = video.read()

    if not ret:
        break
    # 随机选择两个人
    random_indices = random.sample(range(len(centers)), 2)
    selected_centers = [centers[i] for i in random_indices]
    # 进行人体检测并获取人的矩形框
    blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), (104.0, 177.0, 123.0))
    net.setInput(blob)
    detections = net.forward()
    centers = []

    for i in range(detections.shape[2]):
        confidence = detections[0, 0, i, 2]
        if confidence > 0.5:  # 设置置信度阈值
            center = detections[0, 0, i, 3:7] * np.array([frame.shape[1], frame.shape[0], frame.shape[1], frame.shape[0]])
            center = center.astype(int)
            centers.append(center)

            x1, y1, x2, y2 = center
            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)

    # 对每个人的矩形框进行处理
    for center in centers:
        # 计算中心点坐标
        center = calculate_center(center)
        # 将中心点坐标添加到列表中
        center_points.append(center)
        # 更新人物中心点和最近一次检测时间
        person_last_detected[center] = time.time()

    # 如果中心点坐标列表长度大于等于2
    if len(center_points) >= 2:
        last_three_points = center_points[-2:]  # 获取最后2个中心点坐标

        # 判断距离是否小于1.5米
        distances = [calculate_distance(point1, point2) for point1, point2 in zip(last_three_points[:-1], last_three_points[1:])]
        if all(distance < threshold_distance for distance in distances):
            if start_time is None:
                start_time = time.time()
            elif time.time() - start_time >= duration_threshold:
                cv2.imwrite("captured.jpg", frame)
                print("Hunt!")
        else:
            # 重置起始时间和中心点坐标列表
            start_time = time.time()
            # 清空人物中心点列表
            center_points = []
    # 移除超过持续时间阈值的检测记录
    current_time = time.time()
    person_centers = [center for center in person_centers
            if current_time - person_last_detected[center] <= duration_threshold]

    # 保存当前帧图片
    cv2.imwrite(output_path, frame)

    #  'q' 键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# 释放资源
video.release()
cv2.destroyAllWindows()

上面说的其实都不是问题,重要的是我还没有模型。。。没有实际测量,后面我打算弄一个模型简单测测再说吧。

起名?

“嘿,Siri!记录,凌晨零点三十二分,AI主要代码编写完成。”
“好的,我已为您创建好备忘录,请设置一个标题。”
我端起茶杯,浅尝一口,望向窗外,外面早已一片漆黑,仿佛被夜冲刷了所有的痕迹,透着它独有的深邃。
“嗯,就叫重明吧。”

这就是我的第一个AI,一个还不完善的AI🙂