【数据集标注制作】视频剪切标注1——类DarkLabel软件

编程入门 行业动态 更新时间:2024-10-27 12:30:41

【<a href=https://www.elefans.com/category/jswz/34/1771445.html style=数据集标注制作】视频剪切标注1——类DarkLabel软件"/>

【数据集标注制作】视频剪切标注1——类DarkLabel软件

视频标注

用于从视频中标注数据,用于YOLO网络的目标检测。旨在实现单次鼠标标注能生成多张被标注图像,实现数据集快速制作!

  1. 从视频中,通过鼠标框选指定区域,形成掩码box
  2. 鼠标选定区域后,根据设定的成像尺寸,在选定区域周围随机实施多个角度的剪切,制作数据集。(重在减少鼠标标注操作,丰富数据集图片数量)
  3. 剪切出的图片,每张都带掩码box、原图和效果图。
  4. 标注过程视频可暂停,生成图像文件自动命名。(鼠标单击过后,或者键盘按键,都可控制视频暂停和继续)
  5. 不足之处:不可控制视频帧移动

import threading
import queueclass Mask_video:def __init__(self, urls, label, images_save_path):self.urls = urlsself.video_idx = 0self.lock = threading.Lock()self.drawing = Falseself.start_point = (-1, -1)self.end_point = (-1, -1)self.cropped_image = Noneself.paused = False  # 是否暂停视频播放self.expanded_cropped_image = Noneself.expanded_cropped_image_mask_pts = [0,0,0,0]self.images_save_root = images_save_pathself.images_data_save_path = os.path.join(self.images_save_root, 'images')self.images_label_save_path = os.path.join(self.images_save_root, 'labels')self.images_label_mask_path = os.path.join(self.images_save_root, 'mask')os.makedirs(self.images_data_save_path, exist_ok=True)os.makedirs(self.images_label_save_path, exist_ok=True)os.makedirs(self.images_label_mask_path, exist_ok=True)self.images_idx = 0self.label = label# 创建一个窗口并设置鼠标事件回调函数cv.namedWindow('Video')cv.setMouseCallback('Video', self.draw_rectangle)passdef draw_rectangle(self, event, x, y, flags, param):if event == cv.EVENT_LBUTTONDOWN:with self.lock:self.drawing = Trueself.start_point = (x, y)self.pause_video()elif event == cv.EVENT_MOUSEMOVE:if self.drawing:with self.lock:self.end_point = (x, y)if event == cv.EVENT_LBUTTONUP:with self.lock:self.drawing = Falseself.end_point = (x, y)# print('=== 1 ===',  self.start_point, self.end_point)# 归一化坐标,确保 start_point 包含左上角坐标,end_point 包含右下角坐标start_point = (min(self.start_point[0], self.end_point[0]), min(self.start_point[1], self.end_point[1]))end_point = (max(self.start_point[0], self.end_point[0]), max(self.start_point[1], self.end_point[1]))self.start_point, self.end_point = start_point, end_point# print('=== 2 ===', self.start_point, self.end_point)if (self.start_point[0]-self.end_point[0])==0 or (self.start_point[1]-self.end_point[1])==0:self.cropped_image = Nonereturnelse:# 裁剪图像并显示self.cropped_image = self.frame[self.start_point[1]:self.end_point[1],self.start_point[0]:self.end_point[0]]# cv.imshow('Cropped Image', self.cropped_image)for i in range(4): self.crop_and_random_expand()self.cropped_image = Noneself.resume_video()def pause_video(self):with self.lock:self.paused = Truedef resume_video(self):with self.lock:self.paused = Falsedef crop_and_random_expand(self):""" 在指定区域的附近,实施随机剪裁,生成图像 """# with self.lock:if self.cropped_image is not None:# 定义扩展的像素范围expand_range1 = np.random.randint(0, self.start_point[0])  # 您可以根据需要调整这个值expanded_x1 = max(self.start_point[0] - expand_range1, 0)expand_range2 = np.random.randint(0, self.frame.shape[1]-self.end_point[0])  # 您可以根据需要调整这个值expanded_x2 = min(self.end_point[0] + expand_range2, self.frame.shape[1])expand_range3 = np.random.randint(0, self.start_point[1])  # 您可以根据需要调整这个值expanded_y1 = max(self.start_point[1] - expand_range3, 0)expand_range4 = np.random.randint(0, self.frame.shape[0] - self.end_point[1])  # 您可以根据需要调整这个值expanded_y2 = min(self.end_point[1] + expand_range4, self.frame.shape[0])expanded_cropped_image = self.frame[expanded_y1:expanded_y2, expanded_x1:expanded_x2]yh1, xw1 = expanded_cropped_image.shape[:2]expanded_cropped_image = cv.resize(expanded_cropped_image, (640, 640))yh2, xw2 = expanded_cropped_image.shape[:2]self.expanded_cropped_image = expanded_cropped_image.copy()new_pts = [expand_range1, expand_range3, self.end_point[0]-self.start_point[0], self.end_point[1]-self.start_point[1]]new_pts = [new_pts[0]*xw2/xw1, new_pts[1]*yh2/yh1, new_pts[2]*xw2/xw1, new_pts[3]*yh2/yh1]new_pts = np.array(new_pts, dtype=np.int32)self.expanded_cropped_image_mask_pts = new_ptscv.rectangle(expanded_cropped_image, (new_pts[0],new_pts[1]), (new_pts[0]+new_pts[2], new_pts[1]+new_pts[3]), (0, 255, 0), 2)cv.imshow('expanded_cropped_image', expanded_cropped_image)self.save_image(self.expanded_cropped_image, expanded_cropped_image)return expanded_cropped_imageelse:return Nonedef run_video_crop(self):while True:if not self.paused:ret, self.frame = self.cap.read()if not ret:print("无法读取视频帧")breakimg = self.frame.copy()if self.start_point != (-1, -1) and self.end_point != (-1, -1):# 在帧上绘制方框with self.lock:cv.rectangle(img, self.start_point, self.end_point, (0, 255, 0), 2)cv.imshow('Video', img)key = cv.waitKey(20)if key & 0xFF == ord('q'):  # 退出剪裁软件breakelif key & 0xFF == ord('s'):   # 暂停视频self.pause_video()elif key & 0xFF == ord('d'):  # 继续播放视频self.resume_video()# cv.waitKey(20)self.cap.release()# cv.destroyAllWindows()def run(self):for i in range(len(self.urls)):url = self.urls[i]self.video_idx = itry:cap = cv.VideoCapture(url)ret, frame = cap.read()if ret:self.cap = cap# breakself.lock = threading.Lock()self.drawing = Falseself.start_point = (-1, -1)self.end_point = (-1, -1)self.cropped_image = Noneself.paused = False  # 是否暂停视频播放self.run_video_crop()except: passcv.destroyAllWindows()def save_image(self, imgdata, maskdata):self.images_idx += 1imgfile = os.path.join(self.images_data_save_path, f"{str(self.video_idx)}_{self.images_idx}.jpg")labelfile = os.path.join(self.images_label_save_path, f"{str(self.video_idx)}_{self.images_idx}.txt")maskfile = os.path.join(self.images_label_mask_path, f"{str(self.video_idx)}_{self.images_idx}.jpg")print('\timages data jpg save in:', imgfile)cv.imwrite(imgfile, imgdata)print('\timages label txt save in:', labelfile)hy, wx = imgdata.shape[:2]x,y,w,h = self.expanded_cropped_image_mask_ptswith open(labelfile, 'w') as f:data = f"{str(self.label)}\t{x / wx}\t{y / hy}\t{w / wx}\t{h / hy}" + "\n"f.write(data)print('\timages mask save in:', maskfile)cv.imwrite(maskfile, maskdata)def run():print('==========   start system  ==============')import pandas as pd# 读取Excel文件excel_file = r'I:\python\02-job\h03090 data-output\video.xlsx'  # 将文件名替换为实际的Excel文件名df = pd.read_excel(io=excel_file)# 提取某一行的数据,例如第3行(索引为2)row_index = 3selected_row = df.iloc[row_index]# 打印提取的行数据print("提取的行数据:")print(selected_row)videos = str(selected_row['topVideo']).split(',')print(videos)data = {'id': selected_row['goods_id'], 'videos': videos}images_save_path = r'I:\python\02-job\h03090 data-output\new_images-labeled'mask = Mask_video(urls=videos, label=row_index, images_save_path=images_save_path)mask.run()pass

更多推荐

【数据集标注制作】视频剪切标注1——类DarkLabel软件

本文发布于:2023-11-16 00:36:59,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1610817.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数据   视频   软件   DarkLabel

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!