You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

623 lines
26 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import cv2
import os
import time
import mediapipe as mp
from ultralytics import YOLO
import queue
import threading
from config import Q_SZ
from personDet import analysis_yolov8
import tools_function
from holisticDet import MediapipeProcess
import mediapipe_detection_image
from PP_TSMv2_infer import PP_TSMv2_predict
import shutil
import json
class DealVideo():
def __init__(self,video_file,video_save_file,person_model,mediapipe_model,pptsmv2_model):
'''
加载数据
'''
self.video_file = video_file
self.video_save_file = video_save_file
# 初始化模型
self.person_model = person_model
self.mediapipe_model = mediapipe_model
self.predictor = pptsmv2_model[1]
self.infer = pptsmv2_model[0]
self.batch_size = 1
# 队列
self.videoQueue = queue.Queue(maxsize=Q_SZ)
self.videoQueue2 = queue.Queue(maxsize=Q_SZ)
self.cutbboxQueue = queue.Queue(maxsize=0)
self.videodetQueue = queue.Queue(maxsize=0)
self.videoQueue3 = queue.Queue(maxsize=0)
self.videoreturnQueue = queue.Queue(maxsize=0)
#线程
self.get_video_listThread = threading.Thread(target=self.get_video_list)
self.get_video_frameThread = threading.Thread(target=self.get_video_frame)
self.write_videoThread = threading.Thread(target=self.write_video)
self.head_hands_detThread = threading.Thread(target=self.head_hands_det)
self.video_select_dectThread = threading.Thread(target=self.video_select_dect)
self.select_video_pathThread = threading.Thread(target=self.select_video_path)
self.analysis_return_meassageThread = threading.Thread(target=self.analysis_return_meassage)
def get_video_list(self):
'''
获取数据文件
'''
if os.path.isdir(self.video_file):
video_ext = [".mp4", ".avi",".MP4"]
for maindir, subdir, file_name_list in os.walk(self.video_file):
for filename in file_name_list:
apath = os.path.join(maindir, filename)
ext = os.path.splitext(apath)[1]
if ext in video_ext:
self.videoQueue.put(apath)
else:
self.videoQueue.put(self.video_file)
def get_video_frame(self):
'''
对视频进行分帧、每一帧都保存队列
'''
while True:
if self.videoQueue.empty():
time.sleep(1)
else:
video_path = self.videoQueue.get()
# video_basename = os.path.basename(video_path).split('.')[0]
# print('video_path:',video_path)
cap = cv2.VideoCapture(video_path)
video_fps = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# frame_list = []
count_fps = 0
frame_result_contact = []
count_fps_del = 0
while cap.isOpened():
success, frame = cap.read()
if not success:
print(video_path,"Ignoring empty camera frame.")
# print('video_fps:',video_fps,'count_fps:',count_fps)
break
# print('count_fps_read_video=',count_fps)
imgsize = frame.shape
person_det = analysis_yolov8(frame=frame,
model_coco=self.person_model,
confidence_set=0.5)
person_list = tools_function.get_dict_values(person_det)
if frame_result_contact:
start_fps = frame_result_contact[0]['fps']
else:
start_fps = count_fps
if count_fps == (video_fps - 1):
video_end = True
else:
video_end = False
if person_list:
count_fps_del_re,updata_result_contact = self.analysis_by_bbox(imgsize=imgsize,
detect_result=person_list,
dertpara=4,
start_fps=start_fps,
now_fps=count_fps,
label_name='person',
video_path=video_path,
frame_result_contact=frame_result_contact,
parameter_fps=150,
count_fps_del=count_fps_del,
video_end=video_end
)
count_fps_del = count_fps_del_re
frame_result_contact = updata_result_contact
count_fps += 1
def head_hands_det(self):
# print('head_hands_detaohgaogh')
while True:
if self.videoQueue3.empty():
time.sleep(1)
else:
t0 = time.time()
video_path = self.videoQueue3.get()
# print('video_path_head_hands_det:',video_path)
cap = cv2.VideoCapture(video_path)
video_fps = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# frame_list = []
count_fps = 0
head_result_contact = []
hands_result_contact = []
count_fps_del_head = 0
count_fps_del_hand = 0
while cap.isOpened():
success, frame = cap.read()
if not success:
print(video_path,"Ignoring empty camera frame.")
# print('count_fps:',count_fps,'video_fps:',video_fps)
break
# print('count_fps_read_video=',count_fps)
imgsize = frame.shape
# 模型推理
hh_result = MediapipeProcess.mediapipe_det(image=frame,
holistic=self.mediapipe_model)
hh_result_dict = MediapipeProcess.get_analysis_result(image=frame,results=hh_result)
# # 获得当前坐标列表
head_result = hh_result_dict['face_bbox']
head_result_1 = tools_function.select_list(head_result)
hands_result = hh_result_dict['hand_bbox']
hands_result_1 = tools_function.select_list(hands_result)
if count_fps == (video_fps - 1):
# print('count_fps:',count_fps,'video_fps:',video_fps)
video_end = True
else:
video_end = False
# 统一修正坐标,分别对头和手进行分析
if head_result_1:
if head_result_contact:
start_fps = head_result_contact[0]['fps']
else:
start_fps = count_fps
count_fps_del_re,updata_result_contact = self.analysis_by_bbox(imgsize=imgsize,
detect_result=head_result_1,
dertpara=1,
start_fps=start_fps,
now_fps=count_fps,
label_name='head',
video_path=video_path,
frame_result_contact=head_result_contact,
parameter_fps=80,
count_fps_del=count_fps_del_head,
video_end=video_end
)
count_fps_del_head = count_fps_del_re
head_result_contact = updata_result_contact
if hands_result_1:
if hands_result_contact:
start_fps = hands_result_contact[0]['fps']
else:
start_fps = count_fps
count_fps_del_re,updata_result_contact = self.analysis_by_bbox(imgsize=imgsize,
detect_result=hands_result_1,
dertpara=2,
start_fps=start_fps,
now_fps=count_fps,
label_name='hands',
video_path=video_path,
frame_result_contact=hands_result_contact,
parameter_fps=80,
count_fps_del=count_fps_del_hand,
video_end=video_end
)
count_fps_del_hand = count_fps_del_re
hands_result_contact = updata_result_contact
# print(count_fps,'----------------hands_result_1-------------------------------',hands_result_1)
# print(count_fps,"-------------------------updata_result_contact----------------------:",updata_result_contact)
count_fps += 1
def video_select_dect(self):
while True:
if self.videodetQueue.empty():
time.sleep(5)
else:
video_path = self.videodetQueue.get()
try:
result_list = PP_TSMv2_predict().predict(input_f=video_path,
batch_size=self.batch_size,
predictor=self.predictor,
InferenceHelper=self.infer)
if result_list['topk_scores'] > 0.9:
video_base_name = os.path.basename(video_path)
video_save_select_path = self.video_save_file + '/' + 'video_select_dect/'+ str(result_list['topk_class'])
os.makedirs(video_save_select_path, exist_ok=True)
video_save = os.path.join(video_save_select_path, video_base_name)
os.rename(video_path, video_save)
self.videoreturnQueue.put(video_save)
print("result_list_video_select_dect:",result_list)
except Exception as e:
print(e)
def analysis_by_bbox(self,imgsize,detect_result,dertpara,start_fps,now_fps,label_name,video_path,frame_result_contact,parameter_fps,count_fps_del,video_end):
'''
imgsize:图片的尺寸,
detect_result:检测到的图像的结果,bboxlist
dertpara:scale_factor缩放因子大于 1 表示放大,小于 1 表示缩小
start_fps: 对比列表中的起始帧
now_fpsl:当前帧率
label_name:用于分析的检测类别
video_path:视频路径
frame_result_contact:对比列表
parameter_fps:统计截止时间
count_fps_del:统计前后帧未出现次数
'''
bbox_list = tools_function.para_list_correction(images_size=imgsize,bbox_list=detect_result,dertpara=dertpara)
count_fps_del_re,update_frame_result_contact = self.get_cut_message(fps1=now_fps,
label_name = label_name,
re_list=bbox_list,
video_path=video_path,
frame_result_contact=frame_result_contact,
parameter_fps=parameter_fps,
count_fps_del=count_fps_del,
video_end=video_end)
# count_fps_del_re,updata_result_contact = self.get_continue_keys(count_fps_del=count_fps_del,
# continue_para=continue_para,
# start_fps=start_fps,
# now_fps=now_fps,
# frame_result_contact=frame_result_contact,
# update_frame_result_contact=update_frame_result_contact)\
return count_fps_del_re,update_frame_result_contact
def get_cut_message(self,fps1,label_name,re_list,video_path,frame_result_contact,parameter_fps,count_fps_del,video_end):
# continue_para = False
if not frame_result_contact:
bbox_list_all = tools_function.change_list_dict(fps1=fps1,re_list=re_list)
frame_result_contact = bbox_list_all
# print("frame_result_contact:",frame_result_contact)
else:
example_dict_list = frame_result_contact
cut_list,example_lst,re_dict_lst = tools_function.analysis_re01_list(example_list=example_dict_list,
result_list=re_list)
# 有目标减少情况
if example_lst:
# 截图保存视频
# continue_para = True
# cut_dict = {'video_path':video_path,'label_name':label_name,"stop_fps":fps1,'bbox_list':example_lst}
start_fps = example_lst[0]['fps']
if count_fps_del <= 5:
frame_result_contact = frame_result_contact
count_fps_del = count_fps_del + 1
# else:
if (fps1 - start_fps) < 15:
frame_result_contact = frame_result_contact
else:
cut_dict = {'video_path':video_path,'label_name':label_name,"stop_fps":fps1,'bbox_list':example_lst}
frame_result_contact = [item for item in frame_result_contact if item not in example_lst]
self.cutbboxQueue.put(cut_dict)
# 有新添加目标情况
if re_dict_lst:
# 对比示例列表更新
update_list = tools_function.change_list_dict(fps1=fps1,re_list=re_dict_lst)
frame_result_contact = frame_result_contact + update_list
# 统计截止时间
time_out_list = tools_function.statistics_fps(fps_now=fps1,re_list=frame_result_contact,parameter=parameter_fps)
if time_out_list:
# 裁剪保存视频
# bbox_list = Process_tools.change_dict_list(time_out_list)
cut_dict = {'video_path':video_path,'label_name':label_name,"stop_fps":fps1,'bbox_list':time_out_list}
# 添加到新的队列
self.cutbboxQueue.put(cut_dict)
# 对比示例列表更新
frame_result_contact = [item for item in frame_result_contact if item not in time_out_list]
if video_end:
cut_dict = {'video_path':video_path,'label_name':label_name,"stop_fps":fps1,'bbox_list':frame_result_contact}
self.cutbboxQueue.put(cut_dict)
frame_result_contact.clear()
# print('frame_result_contact:',frame_result_contact)
return count_fps_del,frame_result_contact
def analysis_return_meassage(self):
# big_add_list = []
# big_list = []
while True:
if self.videoreturnQueue.empty():
time.sleep(5)
else:
video_message_path = self.videoreturnQueue.get()
directory = os.path.dirname(video_message_path)
labels_pptsm = directory.split('/')[-1]
video_basename = os.path.basename(video_message_path).split('.')[0]
small_anno_infor = video_basename.split('__')[-1]
big_anno_infor = video_basename.split('__')[-2]
video_base_name = video_basename.split('__')[0]
#保存的json文件格式
file_path = self.video_save_file + '/' + video_base_name + '.json'
# 对小图上的坐标和帧率进行分析
small_startfps,small_stopfps,small_fps = small_anno_infor.split('_')[0].split('-')
small_bbox_0,small_bbox_1,small_bbox_2,small_bbox_3 = small_anno_infor.split('_')[1].split('-')
big_startfps,big_stopfps,big_fps = big_anno_infor.split('_')[0].split('-')
big_bbox_0,big_bbox_1,big_bbox_2,big_bbox_3 = big_anno_infor.split('_')[1].split('-')
big_add_startfps = int(big_startfps) + int(small_startfps)
big_add_stopfps = int(big_startfps) + int(small_stopfps)
big_add_bbox_0 = int(big_bbox_0) + int(small_bbox_0)
big_add_bbox_1 = int(big_bbox_1) + int(small_bbox_1)
big_add_bbox_2 = int(big_bbox_0) + int(small_bbox_2)
big_add_bbox_3 = int(big_bbox_1) + int(small_bbox_3)
big_add_dict = {'labels':labels_pptsm,'startfps':big_add_startfps,'stopfps':big_add_stopfps,'bbox':[big_add_bbox_0,big_add_bbox_1,big_add_bbox_2,big_add_bbox_3]}
big_person_dict = {'labels':'person','startfps':big_startfps,'stopfps':big_stopfps,'bbox':[big_bbox_0,big_bbox_1,big_bbox_2,big_bbox_3]}
if os.path.isfile(file_path):
# 如果文件已存在,读取其中的字典数据
with open(file_path, "r") as json_file:
data = json.load(json_file)
data['big_dict'].append(big_add_dict)
if tools_function.compare_dicts(data['big_dict'], big_person_dict):
data['big_dict'].append(big_person_dict)
with open(file_path, "w") as json_file:
json.dump(data, json_file)
# # 访问和处理字典数据
# print(data)
else:
# 如果文件不存在,创建一个新的字典并保存到文件中
bbox_dict = {'big_dict':[big_add_dict,big_person_dict]}
with open(file_path, "w") as json_file:
json.dump(bbox_dict, json_file)
def write_video(self):
# print('write_videoafagragr')
'''
保存成视频
'''
while True:
if self.cutbboxQueue.empty():
time.sleep(2)
else:
video_frame_dict = self.cutbboxQueue.get()
# 视频路径
video_path = video_frame_dict['video_path']
video_basename = os.path.basename(video_path).split('.')[0]
file_name = video_frame_dict['label_name']
# 原视频帧率和尺寸
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
video_fps = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# print(video_path,'fps:',fps,'video_fps:',video_fps)
# 获得起始
stop_fps = video_frame_dict['stop_fps']
# 裁剪信息
result_list = video_frame_dict['bbox_list']
if cap.isOpened():
for i,bbox_dict in enumerate(result_list):
start_fps = bbox_dict['fps']
if start_fps >= stop_fps:
# print('start_fps:',start_fps,'stop_fps:',stop_fps)
break
else:
bbox_list = bbox_dict['result']
bbox_int_list = [int(bbox_list[0]),int(bbox_list[1]),int(bbox_list[2]),int(bbox_list[3])]
w = bbox_int_list[2] - bbox_int_list[0]
h = bbox_int_list[3] - bbox_int_list[1]
size = [w,h]
if tools_function.determine_zero(size):
size = (w,h)
# 根据标签保存不同视频分类
# bbox_name = '{}-{}-{}_{}'.format(int(bbox_list[0]), int(bbox_list[1]), int(bbox_list[2]), int(bbox_list[3]))
video_name_save = '{}__{}-{}-{}_{}-{}-{}-{}.avi'.format(video_basename, start_fps, stop_fps, video_fps,int(bbox_list[0]), int(bbox_list[1]), int(bbox_list[2]), int(bbox_list[3]))
video_save_file = self.video_save_file + '/' + file_name
os.makedirs(video_save_file, exist_ok=True)
video_save_path = os.path.join(video_save_file, video_name_save)
videoWriter =cv2.VideoWriter(video_save_path,cv2.VideoWriter_fourcc('X','V','I','D'),fps,size)
tools_function.save_seg_video(video_name=video_path,
frameToStart=start_fps,
frametoStop=stop_fps,
videoWriter=videoWriter,
bbox=bbox_int_list,
size=size)
videoWriter.release()
self.videoQueue2.put(video_save_path)
else:
print('-----------------agrag-----------------',size,'-----------------agag-----------------')
cap.release()
else:
print(video_path)
break
def select_video_path(self):
while True:
if self.videoQueue2.empty():
time.sleep(5)
else:
video_path = self.videoQueue2.get()
directory = os.path.dirname(video_path)
labels = directory.split('/')[-1]
# print('video_pathagfg:',video_path)
# print(labels)
if labels == 'person':
self.videoQueue3.put(video_path)
# if labels == 'head' or labels == 'hands':
if labels == 'hands':
self.videodetQueue.put(video_path)
else:
pass
def run(self):
self.get_video_listThread.start()
self.get_video_frameThread.start()
self.write_videoThread.start()
self.head_hands_detThread.start()
self.video_select_dectThread.start()
self.select_video_pathThread.start()
self.analysis_return_meassageThread.start()
if __name__ == '__main__':
t1 = time.time()
video = "E:/Bank_files/Bank_02/dataset/video_kf/02.mp4"
video_save = 'test_video'
# 初始化目标检测
person_model = YOLO("model_file/yolov8x.pt")
# 初始化pptsmv2
config = 'model_file/inference/pptsm_lcnet_k400_16frames_uniform.yaml' # 配置文件地址
model_file = 'model_file/inference_hands_2/ppTSMv2.pdmodel' # 推理模型存放地址
params_file = 'model_file/inference_hands_2/ppTSMv2.pdiparams'
# batch_size= 1
infer,predictor = PP_TSMv2_predict().create_inference_model(config,model_file,params_file)
# PP_TSMv2_predict().predict(config,input_file,batch_size,predictor,infer)
# 初始化mediapipe
mp_holistic = mp.solutions.holistic
holistic = mp_holistic.Holistic(
min_detection_confidence=0.5,
min_tracking_confidence=0.5)
# get_seg_video(video_file=video,video_save_path=video_save,dertTime=dertTime)
deal = DealVideo(video_file=video,video_save_file=video_save,person_model=person_model,mediapipe_model=holistic,pptsmv2_model=[infer,predictor])
deal.run()
t2 = time.time()
# print('总时间:',t2-t1)