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.

393 lines
10 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
from deepdiff import DeepDiff
# 图像文件夹
def get_video_list(path):
video_ext = [".mp4", ".avi",".MP4"]
video_names = []
for maindir, subdir, file_name_list in os.walk(path):
for filename in file_name_list:
apath = os.path.join(maindir, filename)
ext = os.path.splitext(apath)[1]
if ext in video_ext:
video_names.append(apath)
return video_names
# # 截取裁剪需要的视频帧
# def save_seg_video(video_name, frameToStart, frametoStop, videoWriter, bbox):
# cap = video_name
# cap.set(cv2.CAP_PROP_POS_FRAMES, frameToStart) # 设置初始帧数
# count = frameToStart
# while True:
# success, frame = cap.read()
# if not success or count > frametoStop:
# break
# if count >= frameToStart:
# # 裁剪视频画面
# frame_target = frame[int(bbox[1]):int(bbox[3]), int(bbox[0]):int(bbox[2])]
# videoWriter.write(frame_target)
# count += 1
# cap.release()
# 截取裁剪需要的视频帧
def save_seg_video(video_name,frameToStart,frametoStop,videoWriter,bbox,size):
cap = cv2.VideoCapture(video_name)
count = 0
while True:
success,frame = cap.read()
if success:
count += 1
if count <= frametoStop and count > frameToStart: # 选取起始帧
# print('correct= ', count)
#裁剪视频画面
frame_target = frame[bbox[1]:bbox[3], bbox[0]:bbox[2]] # (split_height, split_width)
try:
frame_target = cv2.resize(frame_target,size)
videoWriter.write(frame_target)
except Exception as e:
print('----------------------------------',size,'----------------------------------')
print(e)
if not success or count >= frametoStop:
break
videoWriter.release()
cap.release()
# 获得字典中所有values值这个值是列表
def get_dict_values(lst):
"""
获取列表中所有字典的 values 值(如果值是列表)
参数:
lst: 包含字典的列表
返回值:
values: 包含所有字典的 values 值的列表(如果值是列表)
"""
return [value for dictionary in lst for value in dictionary.values() if isinstance(value, list)]
# 解析检测后的结果,为检测后的结果排序
def analysis_sort_list(re_list):
# print('result_dict:',result_dict)
# 获得检测列表
# re_list = result_dict['start_bbox']
# print('re_list:',re_list)
# 获得列表中所有字典的values值
# re_bbox_list = Process_tools.get_dict_values(re_list)
# 为检测出来的标注框排序
sorted_lst = sorted(re_list, key=lambda x: x[0])
return sorted_lst
#对比重叠率高的两个部分,并结合标注框,保存最大的标注框
def contrast_bbox(e_bbox,r_bbox):
e_bbox_min = e_bbox[:2]
r_bbox_min = r_bbox[:2]
bbox_min = [min(x, y) for x, y in zip(e_bbox_min, r_bbox_min)]
e_bbox_max = e_bbox[-2:]
r_bbox_max = r_bbox[-2:]
bbox_max = [max(x, y) for x, y in zip(e_bbox_max, r_bbox_max)]
bbox = bbox_min + bbox_max
return bbox
# 解析result_list列表
def analysis_re01_list(example_list,result_list):
'''
example_dict:对比的参照
result_dict: 需要与参照对比的结果
example_sorted_lst返回值中原先有现在没有部分
re_dict_sorted_lst返回值中现在有原先没有部分
cut_list原先有现在也有的部分
'''
# 第一次检测到目标的帧率和信息
# example_dict_fps = list(example_dict.keys())[0]
# example_sorted_lst = Process_tools.analysis_sort_list(example_list)
# 当前帧检测结果中所有的检测结果数值
# re_dict_fps = list(result_dict.keys())[0]
# re_dict_sorted_lst = Process_tools.analysis_sort_list(result_list)
# 保存前后帧率连续的范围、筛选出相同的部分
cut_list = []
example_temp = []
re_temp = []
for i,ex_bbox_dict in enumerate(example_list):
ex_bbox = ex_bbox_dict['result']
for j,re_bbox in enumerate(result_list):
iou = calculate_iou(box1=ex_bbox, box2=re_bbox)
# print(iou)
if iou > 0.5:
# bbox = Process_tools.contrast_bbox(e_bbox=ex_bbox,r_bbox=re_bbox)
# cut_list.append({i:re_bbox})
cut_list.append(re_bbox)
example_temp.append(ex_bbox)
re_temp.append(re_bbox)
break
# print('example_temp:',example_temp)
# print('re_temp:',re_temp)
example_sorted_lst = [item for item in example_list if item['result'] not in example_temp]
re_dict_sorted_lst = [item for item in result_list if item not in re_temp]
return cut_list,example_sorted_lst,re_dict_sorted_lst
# 计算前后帧率重叠范围
def calculate_iou(box1, box2):
"""
计算两个边界框之间的IoU值
参数:
box1: 边界框1的坐标x1, y1, x2, y2
box2: 边界框2的坐标x1, y1, x2, y2
返回值:
iou: 两个边界框之间的IoU值
"""
x1 = max(box1[0], box2[0])
y1 = max(box1[1], box2[1])
x2 = min(box1[2], box2[2])
y2 = min(box1[3], box2[3])
# 计算交集区域面积
intersection_area = max(0, x2 - x1 + 1) * max(0, y2 - y1 + 1)
# 计算边界框1和边界框2的面积
box1_area = (box1[2] - box1[0] + 1) * (box1[3] - box1[1] + 1)
box2_area = (box2[2] - box2[0] + 1) * (box2[3] - box2[1] + 1)
# 计算并集区域面积
union_area = box1_area + box2_area - intersection_area
# 计算IoU值
iou = intersection_area / union_area
return iou
# 修正坐标参数
def para_correction(images_size,bbox,dertpara):
'''
修正检测后标注框过小的情况,如果有修正参数则使用修正参数,如果没有就按照坐标值扩大两倍
'''
# if dertpara:
# pass
# else:
w = (bbox[2] - bbox[0]) / int(dertpara)
h = (bbox[3] - bbox[1]) / int(dertpara)
bbox_extand_list_x = [bbox[0] - w,bbox[2] + w]
bbox_extand_list_y = [bbox[1] - h,bbox[3] + h]
bbox_list_x = contrast(size=images_size[0],bbox_extand_list=bbox_extand_list_x)
bbox_list_y = contrast(size=images_size[1],bbox_extand_list=bbox_extand_list_y)
bbox_list = [bbox_list_x[0],bbox_list_y[0],bbox_list_x[1],bbox_list_y[1]]
return bbox_list
def para_correction_back(x1, y1, x2, y2):
'''
修正检测后标注框还原
'''
# if dertpara:
# pass
# else:
# x1, y1, x2, y2 = bbox[0], bbox[1],bbox[2],bbox[3] # 原始坐标
width = x2 - x1
height = y2 - y1
scaled_width = int(width * 1.2)
scaled_height = int(height * 1.2)
restored_width = int(scaled_width / 1.2)
restored_height = int(scaled_height / 1.2)
restored_x1 = x1 + (width - restored_width) // 2
restored_y1 = y1 + (height - restored_height) // 2
restored_x2 = restored_x1 + restored_width
restored_y2 = restored_y1 + restored_height
bbox_list = [restored_x1,restored_y1,restored_x2,restored_y2]
return bbox_list
def para_list_correction(images_size,bbox_list,dertpara):
updata_result_list = []
for bbox in bbox_list:
updata_bbox = para_correction(images_size,bbox,dertpara)
updata_result_list.append(updata_bbox)
return updata_result_list
# 对比数值是否在这个范围内
def contrast(size,bbox_extand_list):
'''
对比数值是否在这个范围内
'''
# print('bbox_extand_list:',bbox_extand_list)
# print('size:',size)
bbox_list = []
for x in bbox_extand_list:
# print('size:',size)
if 0 <= int(x) <= int(size):
# print('in:',x,size)
bbox_list.append(x)
if int(x) > int(size):
# print('>:',x,size)
bbox_list.append(size)
if int(x) < 0:
# print('<:',x,size)
bbox_list.append(0)
# print('bbox_list:',bbox_list)
return bbox_list
def change_list_dict(fps1,re_list):
'''
给列表的结果设置对应帧率
'''
bbox_list_all = []
for bbox_list in re_list:
bbox_dict = {'fps':fps1,'result':bbox_list}
bbox_list_all.append(bbox_dict)
return bbox_list_all
def statistics_fps(fps_now,re_list,parameter):
'''
统计时长,返回时间满足截取要求的目标坐标
'''
time_out_list = []
for bbox_dict in re_list:
con_fps = int(fps_now) - int(bbox_dict["fps"])
if con_fps > parameter:
time_out_list.append(bbox_dict)
return time_out_list
def change_dict_list(dict_list):
'''
从字典列表得到bbox列表
'''
bbox_list = []
for dicts1 in dict_list:
bbox_list.append(dicts1['result'])
return bbox_list
def select_list(result_list):
'''
筛选列表中的空列表
'''
if result_list:
result_only = []
for result in result_list:
if result == None :
pass
else:
# result_bbox = select_bbox(result)
result_only.append(result)
return result_only
def select_bbox(bbox_list):
# bbox_list_return = []
# print('bbox:',bbox_list)
left_top = [min(bbox_list, key=lambda p: p[0])[0], min(bbox_list, key=lambda p: p[1])[1]]
right_bottom = [max(bbox_list, key=lambda p: p[0])[0], max(bbox_list, key=lambda p: p[1])[1]]
bbox_list_return = left_top + right_bottom
# print('bbox_list:',bbox_list_return)
return bbox_list_return
# 对比两字典中的值是否完全一致
def compare_dicts(dict1, list_of_dicts):
for d in list_of_dicts:
diff = DeepDiff(dict1, d)
if not diff:
return False
return True