标注工具--抹除目标

news/2025/10/24 13:33:00/文章来源:https://www.cnblogs.com/yanghailin/p/19163036

恩,chatgpt帮我写的标注抹除的工具

import cv2
import numpy as np
import argparse
import os
"""
左键拖动	框选区域
左键单击	粘贴选区
z	撤销上一次操作
c	取消当前选区
s	手动保存
n	自动保存当前 → 加载下一张(若存在 _edited.jpg 优先)
p	自动保存当前 → 加载上一张(若存在 _edited.jpg 优先)
ESC	自动保存后退出
"""class RegionMoveAnnotator:def __init__(self, img_dir):self.img_dir = img_dirself.img_paths = sorted([os.path.join(img_dir, f) for f in os.listdir(img_dir)if f.lower().endswith((".jpg", ".png"))])if not self.img_paths:raise ValueError("❌ 没有找到图片,请检查路径")# 创建同级目录保存标注结果base_dir = os.path.dirname(os.path.abspath(img_dir))folder_name = os.path.basename(img_dir.rstrip("/"))self.save_dir = os.path.join(base_dir, f"{folder_name}_edited")os.makedirs(self.save_dir, exist_ok=True)self.index = 0self.img = Noneself.clone = Noneself.start_point = Noneself.end_point = Noneself.selecting = Falseself.selected_roi = Noneself.show_preview = Falseself.undo_stack = []self.mouse_pos = (0, 0)self.load_image()def get_save_path(self, index):base_name = os.path.basename(self.img_paths[index])name, ext = os.path.splitext(base_name)return os.path.join(self.save_dir, f"{name}_edited{ext}")def load_image(self):save_path = self.get_save_path(self.index)if os.path.exists(save_path):self.img = cv2.imread(save_path)print(f"📷 Loaded edited: {save_path}")else:self.img = cv2.imread(self.img_paths[self.index])print(f"📷 Loaded original: {self.img_paths[self.index]}")self.clone = self.img.copy()self.undo_stack = []self.selected_roi = Noneself.show_preview = Falsedef save_current(self):save_path = self.get_save_path(self.index)cv2.imwrite(save_path, self.img)print(f"💾 Saved: {save_path}")def draw_preview(self, frame):if self.selected_roi is None or not self.show_preview:return frameoverlay = frame.copy()h, w = self.selected_roi.shape[:2]x, y = self.mouse_posx1, x2 = x, x + wy1, y2 = y, y + hif x1 < 0 or y1 < 0:return frameif x2 > frame.shape[1] or y2 > frame.shape[0]:return frameroi_h = min(h, frame.shape[0] - y1)roi_w = min(w, frame.shape[1] - x1)alpha = 0.5overlay[y1:y1+roi_h, x1:x1+roi_w] = (overlay[y1:y1+roi_h, x1:x1+roi_w] * (1 - alpha)+ self.selected_roi[:roi_h, :roi_w] * alpha).astype(np.uint8)return overlaydef mouse_callback(self, event, x, y, flags, param):self.mouse_pos = (x, y)if event == cv2.EVENT_LBUTTONDOWN:if self.selected_roi is not None and self.show_preview:self.undo_stack.append(self.img.copy())h, w = self.selected_roi.shape[:2]y1, y2 = y, y + hx1, x2 = x, x + wy2 = min(y2, self.img.shape[0])x2 = min(x2, self.img.shape[1])self.img[y1:y2, x1:x2] = self.selected_roi[:y2 - y1, :x2 - x1]self.selected_roi = Noneself.show_preview = Falseself.clone = self.img.copy()cv2.imshow("Annotator", self.img)print("✅ Paste done")else:self.start_point = (x, y)self.selecting = Trueelif event == cv2.EVENT_MOUSEMOVE:if self.selecting:temp = self.clone.copy()cv2.rectangle(temp, self.start_point, (x, y), (0, 255, 0), 2)cv2.imshow("Annotator", temp)elif self.selected_roi is not None and self.show_preview:cv2.imshow("Annotator", self.draw_preview(self.clone.copy()))elif event == cv2.EVENT_LBUTTONUP and self.selecting:self.end_point = (x, y)self.selecting = Falsex1, y1 = self.start_pointx2, y2 = self.end_pointx1, x2 = sorted([x1, x2])y1, y2 = sorted([y1, y2])if x2 - x1 > 0 and y2 - y1 > 0:self.selected_roi = self.clone[y1:y2, x1:x2].copy()self.show_preview = Trueprint("✅ Region selected, move mouse and click to paste.")def run(self):cv2.namedWindow("Annotator", cv2.WINDOW_NORMAL)cv2.setMouseCallback("Annotator", self.mouse_callback)cv2.imshow("Annotator", self.img)while True:if self.selected_roi is not None and self.show_preview:cv2.imshow("Annotator", self.draw_preview(self.clone.copy()))key = cv2.waitKey(10) & 0xFFif key == 27:  # ESCself.save_current()breakelif key == ord('z'):if self.undo_stack:self.img = self.undo_stack.pop()self.clone = self.img.copy()cv2.imshow("Annotator", self.img)print("↩ Undo")elif key == ord('c'):if self.selected_roi is not None:self.selected_roi = Noneself.show_preview = Falsecv2.imshow("Annotator", self.clone)print("❎ Selection canceled")elif key == ord('s'):self.save_current()elif key == ord('n'):self.save_current()self.index = (self.index + 1) % len(self.img_paths)self.load_image()cv2.imshow("Annotator", self.img)elif key == ord('p'):self.save_current()self.index = (self.index - 1) % len(self.img_paths)self.load_image()cv2.imshow("Annotator", self.img)cv2.destroyAllWindows()if __name__ == "__main__":parser = argparse.ArgumentParser(description="Label & Move Tool")parser.add_argument('--images','-i', required=True, help="Image file or folder")args = parser.parse_args()img_dir = args.images  # 原图目录annotator = RegionMoveAnnotator(img_dir)annotator.run()

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

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

相关文章

1024程序员节福利!参与互动,5分钟赢好礼!

Hi 程序员朋友们! 敲得了代码,扛得住需求,也该在 1024 这个专属节日里,给自己拆份“技术人专属福利”啦~ 作为深耕开源数据库的 IvorySQL,今年 1024 不想搞复杂玩法——2 种方式,轻松参与,即可获得 IvorySQL 周…

具身智能/智能体 定义

1. 具身智能智能并非一个孤立于身体的大脑计算过程,而是源于身体与环境的实时交互。智能、知觉和行动是一个不可分割的整体。 一个系统必须拥有“身体”(可以是实体机器人,也可以是虚拟环境中的化身),并通过这个身…

【数据挖掘】基于随机森林回归模型的二手车价格预测分析(信息集+源码)

【数据挖掘】基于随机森林回归模型的二手车价格预测分析(信息集+源码)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: …

实用指南:flink批处理-水位线

实用指南:flink批处理-水位线2025-10-24 13:24 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !importan…

字符串模式匹配算法 KMP

子串与子序列中文名称 常见英文名称 解释子串 \(\tt substring\) 连续的选择一段字符(可以全选、可以不选)组成的新字符串子序列 \(\tt subsequence\) 从左到右取出若干个字符(可以不取、可以全取、可以不连续)组成…

Z函数(扩展 KMP)

Z函数(扩展 KMP) 获取字符串 \(s\) 和 \(s[i,n-1]\) (即以 \(s[i]\) 开头的后缀)的最长公共前缀(LCP)的长度,总复杂度 \(\mathcal O(N)\)。 vector<int> zFunction(string s) {int n = s.size();vector&l…

常用例题

常用例题 题意:在一篇文章(包含大小写英文字母、数字、和空白字符(制表/空格/回车))中寻找 \({\tt helloworld}\)(任意一个字母的大小写都行)的子序列出现了多少次,输出结果对 \(10^9+7\) 的余数。 字符串 DP …

2025年环评公司权威推荐排行榜,环评手续,环评报告,环评验收,专业高效服务助力企业合规发展

2025年环评公司权威推荐排行榜,环评手续,环评报告,环评验收,专业高效服务助力企业合规发展 一、行业背景与发展趋势 随着中国生态文明建设的深入推进,环境保护法律法规体系日益完善,环境影响评价作为建设项目环境…

2025年棒球帽厂家推荐排行榜,运动棒球帽,时尚棒球帽,定制棒球帽,防晒棒球帽公司精选榜单

2025年棒球帽厂家推荐排行榜:运动、时尚、定制与防晒棒球帽公司精选榜单 行业背景与发展趋势 棒球帽作为兼具功能性与时尚性的头部配饰,近年来在全球市场持续保持增长态势。随着运动休闲风的盛行和个性化需求的提升,…

常见结论与例题

常见结论 题意:(区间移位问题)要求将整个序列左移/右移若干个位置,例如,原序列为 \(A=(a_1, a_2, \dots, a_n)\) ,右移 \(x\) 位后变为 \(A=(a_{x+1}, a_{x+2}, \dots, a_n,a_1,a_2,\dots, a_x)\) 。 区间的端点…

单芯片方案分享-CH336F-USB拓展坞+百兆网卡+读卡器+100W快充芯片

CH336F是符合USB2.0协议规范的 3端口HUB、USB高速读卡器、USB PD快充和USB转以太网四合一控制器芯片,该芯片集成 3口USB HUB、USB高速SD卡读卡器、USB PD快充和USB百兆以太网扩展功能。简介 CH336F是符合USB2.0协议规…

于状压的线性 RMQ 算法

基于状压的线性 RMQ 算法 严格 \(\mathcal O(N)\) 预处理,\(\mathcal O(1)\) 查询。 template<class T, class Cmp = less<T>> struct RMQ {const Cmp cmp = Cmp();static constexpr unsigned B = 64;usi…

Flink编程模型 - 详解

Flink编程模型 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "…

工业4.0下的边缘存储设计:材料就地处理,响应更快更安全

工业4.0下的边缘存储设计:材料就地处理,响应更快更安全pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas…

服务器关机用halt、poweroff还是shutdown -h now?一文帮你说明

我们需要对服务器进行关机的时候,选择必要的关机命令是非常重要的,本文将帮你说明linux系统中halt、poweroff及shutdown -h now 三个命令的区别并描述底层原理 一. halt功能:停止系统运行,但不一定关闭电源。行为:…

KD Tree

KD Tree 在第 \(k\) 维上的单次查询复杂度最坏为 \(\mathcal O(n^{1-k^{-1}})\)。 struct KDT {constexpr static int N = 1e5 + 10, K = 2;double alpha = 0.725;struct node {int info[K];int mn[K], mx[K];} tr[N];…

小波矩阵树:高效静态区间第 K 大查询

小波矩阵树:高效静态区间第 K 大查询 手写 bitset 压位,以 \(\mathcal O(N \log N)\) 的时间复杂度和 \(\mathcal O(N + \frac{N \log N}{64})\) 的空间建树后,实现单次 \(\mathcal O(\log N)\) 复杂度的区间第 \(k…

Seata用法

目录AT模式TCCSAGA模式参考资料 AT模式在Springboot启动程序加上,@EnableAutoDataSourceProxy 确保数据源被代理 在全局事务启动的方法上加 @GlobalTransactional 分支事务代码无需做任何处理。TCC 实现类加上 @Local…

Day3多媒体标签——视频与音频

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width= , initial-scale=1.0"><title&g…

分数运算类

分数运算类 定义了分数的四则运算,如果需要处理浮点数,那么需要将函数中的 gcd 运算替换为 fgcd 。 template<class T> struct Frac {T x, y;Frac() : Frac(0, 1) {}Frac(T x_) : Frac(x_, 1) {}Frac(T x_, T …