下载数据
import argparse
import pandas as pd
import cv2
import numpy as np
from typing import Tuple, Dict, Optional
from datetime import datetime
import osclass ColorDetector:def __init__(self, color_db_path: str = 'colors.csv'):"""初始化颜色检测器:param color_db_path: 颜色数据库CSV文件路径"""# 初始化状态self.clicked = False # 初始化鼠标点击标识self.bgr_values = (0, 0, 0) # 初始化rgb值self.position = (0, 0) # 初始化鼠标点击位置self.img: Optional[np.ndarray] = None # 初始化图片# 加载颜色数据库(带缓存)self.color_db = self._load_color_db(color_db_path)self._precompute_colors()def _load_color_db(self, path: str) -> pd.DataFrame:"""加载并验证颜色数据库"""try:df = pd.read_csv(path, names=['color', 'color_name', 'hex', 'R', 'G', 'B'], header=None)# 数据验证if df.empty:raise ValueError("颜色数据库为空")if not all(col in df.columns for col in ['R', 'G', 'B', 'color_name']):raise ValueError("颜色数据库缺少必要列")# 转换颜色值为整数df[['R', 'G', 'B']] = df[['R', 'G', 'B']].astype(int)return dfexcept Exception as e:raise RuntimeError(f"加载颜色数据库失败: {str(e)}")def _precompute_colors(self) -> None:"""预计算颜色数据加速查找"""self.color_array = self.color_db[['R', 'G', 'B']].valuesdef _mouse_callback(self, event: int, x: int, y: int, *_) -> None:"""鼠标回调函数(优化性能)"""if event == cv2.EVENT_LBUTTONDBLCLK and self.img is not None: # 是否双击鼠标,点击图片是否存在self.clicked = True # 将鼠标点击设为Trueself.position = (x, y) # 获取当前点击图片的xy坐标值print("已经双击了")self.bgr_values = tuple(map(int, self.img[y, x])) # 获取当前的RGB值def _get_closest_color(self, bgr: Tuple[int, int, int]) -> Dict[str, str]:"""查找最接近的颜色(使用向量化计算优化性能):param bgr: (B, G, R) 格式的颜色值,opencv中使用的是BGR,其他的使用的是RGB:return: 包含颜色信息的字典"""b, g, r = bgr# 使用numpy向量化计算曼哈顿距离distances = np.sum(np.abs(self.color_array - [r, g, b]), axis=1) # 计算加载出来的数据与当前点击位置的RGB的距离closest_idx = np.argmin(distances) # 返回距离最小的颜色下标return {'name': self.color_db.loc[closest_idx, 'color_name'], # 获取当前颜色的名字'hex': self.color_db.loc[closest_idx, 'hex'], # 获取当前颜色的hex'rgb': (r, g, b),'bgr': (b, g, r)}def _draw_info_panel(self) -> None:"""绘制信息面板(修复vconcat错误)"""if self.img is None:returncolor_info = self._get_closest_color(self.bgr_values)b, g, r = self.bgr_values# 计算亮度决定文字颜色brightness = 0.299 * r + 0.587 * g + 0.114 * btext_color = (0, 0, 0) if brightness > 150 else (255, 255, 255)# 确保面板宽度与原图一致panel_width = self.img.shape[1]panel = np.zeros((100, panel_width, 3), dtype=np.uint8)cv2.rectangle(panel, (0, 0), (panel_width, 100), (b, g, r), -1)# 添加文字信息info_lines = [f"Color: {color_info['name']}",f"HEX: #{color_info['hex']}",f"RGB: ({r}, {g}, {b})",f"Position: {self.position}"]for i, line in enumerate(info_lines):cv2.putText(panel, line, (20, 30 + i * 20),cv2.FONT_HERSHEY_SIMPLEX, 0.6,text_color, 1, cv2.LINE_AA)# 修复合并条件:确保图像尺寸和类型匹配if panel.shape[1] == self.img.shape[1] and panel.dtype == self.img.dtype:self.img = cv2.vconcat([panel, self.img])else:# 应急处理:仅显示面板self.img = paneldef run(self, image_path: str) -> None:# 加载图片(支持中文路径)self.img = cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), cv2.IMREAD_COLOR)if self.img is None:print("错误:图片加载失败,请检查路径和文件格式")return# 创建窗口并绑定回调cv2.namedWindow('Color Detector', cv2.WINDOW_NORMAL)cv2.setMouseCallback('Color Detector', self._mouse_callback)print("提示:请先点击窗口标题栏获得焦点,然后双击图片")while True:display_img = self.img.copy()if self.clicked:self._draw_info_panel()self.clicked = Falsecv2.imshow('Color Detector', display_img)key = cv2.waitKey(20)if key == 27:breakcv2.destroyAllWindows()def _save_screenshot(self) -> None:"""保存截图功能"""if self.img is not None:timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')filename = f'color_detection_{timestamp}.png'try:cv2.imwrite(filename, self.img)print(f"截图已保存为 {filename}")except Exception as e:print(f"保存截图失败: {str(e)}")def main():parser = argparse.ArgumentParser(description="高级颜色检测工具 v2.0",formatter_class=argparse.RawTextHelpFormatter,epilog="""使用示例:python color_detector.py -i test.jpgpython color_detector.py -i test.jpg -c custom_colors.csv快捷键:ESC 退出程序S 保存当前截图H 显示帮助信息""")parser.add_argument('-i', '--image',required=True,help="要分析的图片路径(支持中文路径)")parser.add_argument('-c', '--color_db',default='colors.csv',help="自定义颜色数据库路径 (默认: colors.csv)")args = parser.parse_args()try:print("启动颜色检测器...")detector = ColorDetector(args.color_db)print("操作提示: 双击图片选取颜色,按S保存截图,ESC退出")detector.run(args.image)except Exception as e:print(f"初始化失败: {str(e)}")exit(1)if __name__ == "__main__":main()
启动方式:命令:python 你脚本路径 -i 要提取颜色的图片位置 -c 颜色数据库
python color_detection.py -i "D:\python_project\color.jpg.jpg" -c color.csv