批量 roi 目录 roi

roi_dir.py
import glob import cv2 import numpy as np import json import os class ROIDrawer: def __init__(self, image_o, label="tiaosheng"): self.drawing = False self.ix, self.iy = -1, -1 self.rois = [] # 存储多个ROI self.image_o = image_o self.image = self.image_o.copy() self.temp_image = self.image.copy() self.ok = False self.label = label # 目标标签 def draw_crosshair(self, event, x, y, flags, param): self.temp_image = self.image.copy() # 每次更新临时图像 # 关键修改:无论是否有已框选的ROI,只要不在绘制中就显示十字星 if not self.drawing: # 只有当不处于拖拽框选状态时,才显示十字星 cv2.line(self.temp_image, (x, 0), (x, self.temp_image.shape[0]), (0, 255, 0), 1) cv2.line(self.temp_image, (0, y), (self.temp_image.shape[1], y), (0, 255, 0), 1) # 鼠标按下:开始框选 if event == cv2.EVENT_LBUTTONDOWN: self.drawing = True self.ix, self.iy = x, y # 鼠标移动:实时绘制矩形(此时不显示十字星,因为drawing=True) elif event == cv2.EVENT_MOUSEMOVE: if self.drawing: # 绘制当前正在拖拽的矩形 cv2.rectangle(self.temp_image, (self.ix, self.iy), (x, y), (255, 0, 0), 2) # 鼠标左键释放:确认当前ROI(继续框选) elif event == cv2.EVENT_LBUTTONUP: self.drawing = False # 结束绘制,恢复十字星显示 # 计算规范的坐标(确保x1 < x2, y1 < y2) x1, y1 = min(self.ix, x), min(self.iy, y) x2, y2 = max(self.ix, x), max(self.iy, y) # 绘制最终矩形到原始图像 cv2.rectangle(self.image, (x1, y1), (x2, y2), (255, 0, 0), 2) # 保存ROI坐标 self.rois.append([[x1, y1], [x2, y2]]) # 鼠标右键释放:完成框选 elif event == cv2.EVENT_RBUTTONUP: self.drawing = False # 结束绘制,恢复十字星显示 x1, y1 = min(self.ix, x), min(self.iy, y) x2, y2 = max(self.ix, x), max(self.iy, y) cv2.rectangle(self.image, (x1, y1), (x2, y2), (255, 0, 0), 2) self.rois.append([[x1, y1], [x2, y2]]) print(f"已添加ROI: {[x1, y1]} - {[x2, y2]} (共{len(self.rois)}个)") self.ok = True def save_json(self, image_path, output_json_path=None): if not self.rois: print("没有框选任何目标,不保存JSON") return if not output_json_path: img_dir, img_name = os.path.split(image_path) img_base = os.path.splitext(img_name)[0] output_json_path = os.path.join(img_dir, f"{img_base}.json") # 构建JSON结构 json_data = {"version": "1.0.0", "flags": {}, "shapes": [], "imagePath": image_path, "imageHeight": self.image_o.shape[0], "imageWidth": self.image_o.shape[1]} for points in self.rois: (x1, y1), (x2, y2) = points bbox = [x1, y1, x2, y2] shape = {"label": self.label, "shape_type": "rectangle", "points": points, # 仍然保留原来的 [[x1,y1],[x2,y2]] "bbox": bbox, "description": "", "flags": {}} json_data["shapes"].append(shape) with open(output_json_path, 'w', encoding='utf-8') as f: json.dump(json_data, f, ensure_ascii=False, indent=4) def run(self, image_path, output_json=None): cv2.namedWindow('Draw ROI') cv2.setMouseCallback('Draw ROI', self.draw_crosshair) while True: cv2.imshow('Draw ROI', self.temp_image) key = cv2.waitKey(1) & 0xFF if key == 27: # Esc键:取消操作 print("已取消操作") self.rois = [] break elif key == 13: # Enter键:保存并退出 break elif self.ok: # 右键结束框选 break cv2.destroyAllWindows() if output_json: self.save_json(image_path, output_json) return self.rois def roi_video(video_path, output_json_path=None): json_path = os.path.splitext(video_path)[0] + ".json" cap = cv2.VideoCapture(video_path) frame_rate = cap.get(cv2.CAP_PROP_FPS) loaded_frames = [] prompts = {} roi_box = True image_path = "roi_box.jpg" video_result = {} video_name = os.path.basename(video_path) while True: ret, frame = cap.read() if not ret: break h, w = frame.shape[:2] target_area = 1000 * 1500 orig_area = h * w if orig_area > target_area: scale = np.sqrt(target_area / orig_area) new_w = int(w * scale) new_h = int(h * scale) new_w -= new_w % 2 new_h -= new_h % 2 frame = cv2.resize(frame, (new_w, new_h), interpolation=cv2.INTER_LINEAR) if len(prompts) < 1: if roi_box: print(f"正在处理视频: {video_name}") roi_drawer = ROIDrawer(frame) selected_rois = roi_drawer.run(image_path, output_json=json_path) if len(selected_rois) > 0: boxes = [] for p_i, points in enumerate(selected_rois): (x1, y1), (x2, y2) = points bbox = [x1, y1, x2, y2, p_i] boxes.append(bbox) # 构建返回结果 video_result = {'video_name': video_name, 'boxes': boxes, 'frame_resolution': f"{new_w}x{new_h}" if orig_area > target_area else f"{w}x{h}"} break # 获取到boxes后退出循环 else: break cap.release() return video_name, video_result def roi_video_directory(directory_path, video_extensions=None): print("1. 左键拖拽框选目标(松开后继续框选下一个,十字星始终显示)") print("2. 右键拖拽框选最后一个目标(松开后结束框选)") print("3. 按Esc键取消操作,按Enter键保存并退出") video_files=glob.glob(directory_path+"/*.mp4") if not video_files: print(f"警告: 在目录 '{directory_path}' 中未找到视频文件") return {} print(f"找到 {len(video_files)} 个视频文件:") for i, video_file in enumerate(video_files, 1): print(f"{i}. {video_file}") results = {} for video_file in video_files: try: video_name, video_result = roi_video(str(video_file)) if video_result: # 只有当有结果时才添加 results[video_name] = video_result print(results) else: results[video_name] = {'video_name': video_name, 'video_path': str(video_file), 'boxes': [],'frame_resolution': 'unknown'} except Exception as e: print(f"处理视频 '{video_file.name}' 时出错: {e}") results[video_file.name] = {'video_name': video_file.name, 'video_path': str(video_file), 'boxes': [], 'frame_resolution': 'error', 'error': str(e)} return results def print_results_summary(results_dict): print("处理结果摘要:") print("=" * 60) total_videos = len(results_dict) print(f"总视频数: {total_videos}") print("-" * 60) # 详细输出每个视频的boxes print("\n详细boxes信息:") print("=" * 60) for video_name, result in results_dict.items(): boxes = result.get('boxes', []) if boxes: print(f"\n{video_name}:") for i, box in enumerate(boxes, 1): print(f" ROI{i - 1}: {box}") else: print(f"\n{video_name}: 无ROI") print("=" * 60) def save_results_to_json(results_dict, output_path="video_rois_results.json"): # 简化结果以便保存(移除可能包含非JSON序列化的对象) simplified_results = {} for video_name, result in results_dict.items(): simplified_results[video_name] = {'video_name': result.get('video_name', video_name), 'boxes': result.get('boxes', []), 'frame_resolution': result.get('frame_resolution', 'unknown')} if 'error' in result: simplified_results[video_name]['error'] = result['error'] with open(output_path, 'w', encoding='utf-8') as f: json.dump(simplified_results, f, ensure_ascii=False, indent=4) print(f"\n结果已保存到: {output_path}") if __name__ == '__main__': directory_path = r"B:\data\tiaosheng\20260112" results = roi_video_directory(directory_path) print_results_summary(results) save_results_to_json(results, "video_rois_results.json") # 也可以直接打印原始字典 print("\n原始结果字典:") print(json.dumps(results, ensure_ascii=False, indent=2))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1156012.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三种神经网络BP-PID、RBF-PID、单神经元自适应优化PID算法对比仿真(程序+参考资料)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

零基础入门:理解AUTOSAR中DIO驱动配置

零基础也能懂&#xff1a;AUTOSAR中DIO驱动配置的“人话”指南你有没有遇到过这样的情况&#xff1f;换了个MCU芯片&#xff0c;原本好好的LED控制代码突然不亮了——不是灯坏了&#xff0c;而是GPIO引脚变了。于是你只能翻数据手册、查寄存器、改代码……一通操作下来&#xf…

LVGL移植实战案例:配合DMA2D加速GUI绘制

让LVGL在STM32上“飞”起来&#xff1a;DMA2D加速GUI绘制实战详解你有没有遇到过这样的场景&#xff1f;辛辛苦苦用LVGL搭好了界面&#xff0c;按钮、滑动条、图表一应俱全&#xff0c;结果一滑动就卡顿&#xff0c;动画像幻灯片一样一帧一卡。打开调试器一看&#xff0c;CPU占…

Cortex-M浮点单元(FPU)使用指南:新手必看示例

掌握Cortex-M的浮点加速引擎&#xff1a;FPU实战全解析你有没有遇到过这种情况&#xff1f;在STM32上跑一个FFT&#xff0c;采样率刚到48kHz&#xff0c;处理器就满负荷运转&#xff1b;或者写了个PID控制器&#xff0c;参数一调精&#xff0c;系统就开始抖动——不是算法有问题…

模糊PID与PID控制simulink仿真比较(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

ST7789V硬件时序详解:系统学习初始化流程

深入ST7789V&#xff1a;从硬件时序到初始化流程的系统性解析在嵌入式显示开发中&#xff0c;点亮一块屏幕看似简单——接上电源、写几条命令、刷点颜色。但当你真正动手时&#xff0c;却常常遇到花屏、黑屏、白屏、颜色错乱等问题。这些问题的背后&#xff0c;往往不是代码写错…

Proteus8.9下载安装教程:小白指南(含资源获取渠道)

从零开始安装 Proteus 8.9&#xff1a;工程师亲测的实战避坑指南你是不是也曾在深夜对着“License Not Found”弹窗抓耳挠腮&#xff1f;是不是下载了十几个G的安装包&#xff0c;点开却提示“缺少 VDM 引擎”&#xff1f;又或者&#xff0c;好不容易装上了&#xff0c;仿真时单…

Keil芯片包管理详解:如何为STM32选择正确版本

Keil芯片包管理实战&#xff1a;如何为STM32选对版本&#xff0c;避开90%工程师踩过的坑你有没有遇到过这样的场景&#xff1f;刚从CubeMX导出一个Keil工程&#xff0c;编译时却报错&#xff1a;“TIM8未定义”&#xff1f;或者调试时发现寄存器窗口一片空白&#xff0c;SVD视图…

基于STM32的多点温度采集系统构建

打造工业级多点温度监控系统&#xff1a;STM32实战全解析你有没有遇到过这样的场景&#xff1f;一台设备里几十个关键部件在发热&#xff0c;却只能靠一个温度探头“猜”整体状态&#xff1b;或者冷链运输途中&#xff0c;货品因局部高温变质&#xff0c;而监测系统毫无察觉。问…

利用ARM架构特性优化STM32代码效率:实战技巧

深入ARM内核&#xff1a;用架构思维优化STM32代码性能你有没有遇到过这样的情况&#xff1f;电机控制算法明明写对了&#xff0c;但就是跑不进100μs的周期&#xff1b;ADC采样频率上不去&#xff0c;DMA总在丢包&#xff1b;或者Flash空间快爆了&#xff0c;却找不到哪里能再压…

Day 33:【99天精通Python】日志记录 (Logging) - 告别 Print 调试

Day 33&#xff1a;【99天精通Python】日志记录 (Logging) - 告别 Print 调试 前言 欢迎来到第33天&#xff01; 在之前的编程练习中&#xff0c;当我们需要调试代码或者查看程序运行状态时&#xff0c;最常用的办法就是 print()。 但是在真正的项目开发&#xff08;尤其是服务…

Linux驱动开发八股文:工作队列(Workqueue)

&#x1f4da; Linux 驱动开发笔记&#xff1a;工作队列 (Workqueue) 一、 核心定义 工作队列是 Linux 内核中断下半部&#xff08;Bottom Half&#xff09;的一种重要机制。它允许你将耗时的、需要等待资源或可能导致休眠的任务&#xff0c;从中断处理函数&#xff08;ISR&…

Linux应用与驱动开发:mmap和内存映射

学习笔记&#xff1a;Linux 驱动开发之 mmap 与内存映射 1. 核心概念&#xff1a;什么是 mmap&#xff1f; mmap (Memory Map) 是一种内存映射文件的方法。在嵌入式 Linux 驱动开发中&#xff0c;它主要用于将外设的物理地址&#xff08;如 GPIO 寄存器&#xff09;映射到用户进…

Day 34:【99天精通Python】单元测试 (Unittest) - 给代码上个保险

Day 34&#xff1a;【99天精通Python】单元测试 (Unittest) - 给代码上个保险 前言 欢迎来到第34天&#xff01; 在之前的开发中&#xff0c;我们通常是怎么验证代码对不对的&#xff1f; —— 写完代码&#xff0c;手动运行一下&#xff0c;输入几个参数&#xff0c;看看打印结…

Day 35:【99天精通Python】综合实战 - 爬虫与数据分析可视化(上) - 数据采集与入库

Day 35&#xff1a;【99天精通Python】综合实战 - 爬虫与数据分析可视化(上) - 数据采集与入库 前言 欢迎来到第35天&#xff01; 经过前两周的学习&#xff0c;我们已经掌握了网络请求&#xff08;Requests&#xff09;、网页解析&#xff08;BeautifulSoup&#xff09;、数…

多FDCAN接口同步配置实战:双通道并行通信实现

多FDCAN接口实战&#xff1a;双通道并行通信如何突破带宽瓶颈你有没有遇到过这样的情况&#xff1f;在开发一个高实时性的车载控制模块时&#xff0c;CAN总线突然“卡顿”——数据延迟飙升、报文丢失频发。排查一圈后发现&#xff0c;并不是硬件故障&#xff0c;而是单条CAN通道…

强烈安利10个AI论文软件,MBA毕业论文轻松搞定!

强烈安利10个AI论文软件&#xff0c;MBA毕业论文轻松搞定&#xff01; AI 工具如何让论文写作更高效&#xff1f; 在当前的学术环境中&#xff0c;MBA 学生和研究者们正面临越来越多的挑战。从选题到撰写&#xff0c;再到查重与修改&#xff0c;每一个环节都可能成为耗时费力的…

Figma中文界面本地化:设计师专属的语言解决方案

Figma中文界面本地化&#xff1a;设计师专属的语言解决方案 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 语言障碍的痛点与解决方案 对于国内设计从业者而言&#xff0c;Figma作为专…

Day 36:【99天精通Python】综合实战 - 爬虫与数据分析可视化(下) - 让数据“说话“

Day 36&#xff1a;【99天精通Python】综合实战 - 爬虫与数据分析可视化(下) - 让数据"说话" 前言 欢迎来到第36天&#xff01; 在昨天&#xff08;Day 35&#xff09;的课程中&#xff0c;我们化身为"数据采集员"&#xff0c;成功编写爬虫抓取了豆瓣 Top2…

导师推荐!8个AI论文平台测评:研究生开题报告全攻略

导师推荐&#xff01;8个AI论文平台测评&#xff1a;研究生开题报告全攻略 学术写作工具测评&#xff1a;为什么需要一份精准的AI论文平台榜单 在研究生阶段&#xff0c;开题报告和论文撰写是科研工作的核心环节&#xff0c;而高效、专业的写作工具能显著提升研究效率与成果质…