第一个AI?
“这次任务繁重,诸君共勉!”
1300多个视频,每一个都有六个小时的时长,反复观看,持续三天
要在浩如烟海的视频画面中识别出携带有效信息的三个人,尤其是对于刚刚接触业务工作的我们来说,更是堪比青天揽星
第一次听到这个任务的我,也是沉默了一会儿,唉,是个体力活啊
“大家不用有很大的压力,我们也向很多公司寻求了技术支持,比如某华、某康威视,他们的图像识别技术在国内也是领先水平,有他们的协助,再加上大家的共同努力,相信我们一定可以取得非常不错的成绩。”
嗯?技术支持?图像识别?脑袋轰的一下炸开,我知道python有一个开源库opencv
,但是我平时只是拿来提取简单的色素块进行比较排序,还没试过对复杂图像和长时间视频进行一个深度学习、识别、提取的过程,但这次时间跨度有点长,那为什么我不自己去写一个AI帮我去看呢?🤔
OpenCV
假设,我们有一个西瓜🍉那我们如何判断这是一个西瓜的呢?比如说,我们可以从通过分析它的颜色、形状和质地,都可以说它是西瓜🍉。
下一个问题,计算机怎么知道这是西瓜🍉呢?计算机是没有生活经验的,但是计算机视觉的功能可以通过识别图像的线索来进行判断。而这些线索称为图像的特征,而我们要做的就是帮助计算机检测图像中的各种特征。
听上去是不是简单?但写起来还是挺麻烦的,尤其是对我这种基本没接触过深度学习与神经网络的初学者来讲。。。
但可以先确定一下具体步骤,首先要根据照片生成人体检测模型:
- 收集和准备训练数据集:获取包含人体的照片,并为每个人体标注边界框或关键点。可以使用公开的人体检测数据集,如
COCO
、MPII
等,或者自己手动标注数据集。 - 数据预处理:对收集到的数据集进行预处理,包括图像的调整大小、裁剪、归一化等操作,以便于模型的训练和输入。
- 构建模型:选择适合人体检测任务的模型架构,如
Faster R-CNN
、YOLO
、SSD
等。可以使用现有的模型架构,并根据需要进行修改或微调。 - 训练模型:使用准备好的数据集对模型进行训练。在训练过程中,你需要定义损失函数、选择优化算法,并设置训练的超参数。
- 模型评估和调优:在训练完成后,使用验证集或测试集对模型进行评估,了解模型的性能。根据评估结果,可以进行模型的调优,如调整网络结构、调整超参数等。
- 导出和使用模型:训练完成后,将模型导出为可用的格式,比如
caffemodel
、prototx
,然后再用该模型进行人体检测。
上面这些数据处理、模型训练,我相信公司已经在做了,所以我打算直接嫖他们的训练模型(嘿嘿嘿)
目标识别
然后麻烦的就是目标的判断算法,这几天看大家的照片,都是在以胸前图案为主,我一开始也是这样想的,但是在写代码的时候就发现了问题:
- 监控的画质并不是很清晰。
- 中午阳光强烈,衣服上的图案可能与衣服本身颜色对比不明显,很难提取。
似乎停滞了?
“目标必须要共同行走一段距离,两者之间相距不得超过1.5米。”
所以我果断换了思路——距离计算
虽然这样也会有一定的问题,比如拍摄角度问题,可能就要根据透视原理之类的适当缩放那个距离数值,但是比起图案识别那个思路来讲,难度小,误差也小,实现起来也简单。
我们可以先对两人添加矩形框,然后取矩形框对角线的交点作为两人的中心点,任意连接两个中心点形成线段,判断线段长度是否持续四秒钟小于1.5米,符合条件的话便对此时画面进行捕捉提取。
而距离度量的话,我选择了欧几里得距离公式(欧氏距离)进行计算:
代码编写
第一次自己操刀写的一个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🙂