相信很多人在使用labelme标注数据的时候都曾有过吐槽,或者觉得点击鼠标的操作很累,对!!那么他来了,便捷小工具!!
目前只测试过ubuntu上的使用,据反馈和本人亲自测试,windows下使用好像有些问题,异常卡顿,暂时没有精力去优化,先等等。
一
能够代替手动点击,根据鼠标移动距离,自动进行点击,通过键盘控制点击开关,可完美契合labelme快捷键。
注:labelme快捷键
ctrl+J=对polygons进行移动编辑
ctrl+N=创建新的polygons
Python代码
# linux 版本的
from pynput import mouse, keyboard
# 瘟dow好像是pyautogui还是叫什么来着忘了
import random
click_enabled = False
mouse_position = None
mouse_controller = mouse.Controller()
# 键盘按键事件处理函数
def on_key_press(key):
global click_enabled
if key == keyboard.Key.space: # 绑定开按键
click_enabled = True
# print("开")
elif key == keyboard.Key.down: # 绑定关按键
click_enabled = False
# print("关")
elif key == keyboard.Key.enter: # 绑定关按键
click_enabled = False
# print("关")
elif key == keyboard.Key.up: # 绑定关按键
click_enabled = False
# print("关")
# 这边我绑定了三个暂停按键,看个人需求
elif key == keyboard.Key.right: # 绑定强制结束程序按键
stop_listeners()
# 鼠标移动事件处理
def on_move(x, y):
global click_enabled, mouse_position
if not click_enabled:
return
# 初始位置记录
if mouse_position is None:
mouse_position = (x, y)
return
# 计算鼠标移动距离
distance = ((x - mouse_position[0]) ** 2 + (y - mouse_position[1]) ** 2) ** 0.5
DISTANCE_THRESHOLD = 14 # 是否随机随机随机,10适合雨滴,20适合云彩
# DISTANCE_THRESHOLD = random.uniform(10, 50)
if distance >= DISTANCE_THRESHOLD:
# 模拟鼠标左键点击
mouse_controller.click(mouse.Button.left)
# mouse_controller.click(mouse.Button.right)
# 更新鼠标位置
mouse_position = (x, y)
mouse_position = (x, y)
# 直接用像素会出问题,移动多少像素都不行。bug
# 停止监听
def stop_listeners():
mouse_listener.stop()
keyboard_listener.stop()
# 创建
mouse_listener = mouse.Listener(on_move=on_move)
keyboard_listener = keyboard.Listener(on_press=on_key_press)
# 启动
mouse_listener.start()
keyboard_listener.start()
# 额额
keyboard_listener.join()
mouse_listener.join()
这边注释写的很清楚,大家应该都能看懂,大家直接自行运行吧,代码没有怎么进行优化,本人能力有限,能用就行能用就行哦~(目前流畅使用)
效果展示:

这样就可以只需要专注于轮廓框选,省去大量点击步骤
二
图片快捷删除工具
有时候大家要先对原数据进行一遍筛选,可以通过这个,可以直接删除png和json文件,这个代码比较烂,就不介绍了,用的不多,随便弄弄的。
大家直接看吧
Python代码
import os
import tkinter as tk
from tkinter import filedialog, messagebox
def delete_files(folder_path, number):
if '-' in number:
start, end = map(int, number.split('-'))
deleted_files = []
for i in range(start, end+1):
json_file = f"{i}.json"
png_file = f"{i}.png"
json_path = os.path.join(folder_path, json_file)
png_path = os.path.join(folder_path, png_file)
if os.path.exists(json_path):
os.remove(json_path)
deleted_files.append(json_file)
if os.path.exists(png_path):
os.remove(png_path)
deleted_files.append(png_file)
return tuple(deleted_files)
else:
json_file = f"{number}.json"
png_file = f"{number}.png"
json_path = os.path.join(folder_path, json_file)
png_path = os.path.join(folder_path, png_file)
if os.path.exists(json_path):
os.remove(json_path)
if os.path.exists(png_path):
os.remove(png_path)
return json_file, png_file
def on_enter_pressed(event=None):
folder_path = folder_var.get()
number = number_var.get()
if os.path.exists(folder_path) and (number.isdigit() or '-' in number):
deleted_files = delete_files(folder_path, number)
if deleted_files:
result_var.set(f"已删除文件: {', '.join(deleted_files)}")
else:
result_var.set("未找到匹配文件")
# 清空输入框
number_var.set("")
else:
result_var.set("无效的文件夹路径或数字")
def select_folder():
folder_selected = filedialog.askdirectory()
folder_var.set(folder_selected)
# 创建主窗口
root = tk.Tk()
root.title("文件删除工具")
# 文件夹路径输入
tk.Label(root, text="文件夹路径:").pack()
folder_var = tk.StringVar()
folder_entry = tk.Entry(root, textvariable=folder_var, width=30)
folder_entry.pack()
# 文件夹选择按钮
select_button = tk.Button(root, text="选择文件夹", command=select_folder)
select_button.pack()
# 数字输入
tk.Label(root, text="输入数字:").pack()
number_var = tk.StringVar()
number_entry = tk.Entry(root, textvariable=number_var, width=10)
number_entry.pack()
# 绑定<Return>事件
number_entry.bind("<Return>", on_enter_pressed)
# 结果展示
result_var = tk.StringVar()
result_label = tk.Label(root, textvariable=result_var, fg="red")
result_label.pack()
# 删除按钮
delete_button = tk.Button(root, text="删除文件", command=on_enter_pressed)
delete_button.pack()
# 运行主循环
root.mainloop()
如有优化或者其他相关问题欢迎大家进行反馈,本人能力有限,只是浅浅分享一下。

