点击鼠标取rgb,转为中文颜色,效果很差

本博客介绍了一个使用Python实现的颜色识别程序。通过设置鼠标监听,程序能在用户点击屏幕时读取并识别点击位置的颜色,并将其归类为预定义的颜色类别之一。涉及到的技术包括HSV颜色空间转换、OpenCV图像处理库的应用及Windows API的调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import numpy as np
import collections


# 定义字典存放颜色分量上下限
# 例如:{颜色: [min分量, max分量]}
# {'red': [array([160,  43,  46]), array([179, 255, 255])]}

def getColorList():
    dict = collections.defaultdict(list)

    # 黑色
    lower_black = np.array([0, 0, 0])
    upper_black = np.array([180, 255, 46])
    color_list = []
    color_list.append(lower_black)
    color_list.append(upper_black)
    dict['black'] = color_list

    #灰色
    lower_gray = np.array([0, 0, 46])
    upper_gray = np.array([180, 43, 220])
    color_list = []
    color_list.append(lower_gray)
    color_list.append(upper_gray)
    dict['gray']=color_list

    # 白色
    lower_white = np.array([0, 0, 221])
    upper_white = np.array([180, 30, 255])
    color_list = []
    color_list.append(lower_white)
    color_list.append(upper_white)
    dict['white'] = color_list

    # 红色
    lower_red = np.array([156, 43, 46])
    upper_red = np.array([180, 255, 255])
    color_list = []
    color_list.append(lower_red)
    color_list.append(upper_red)
    dict['red'] = color_list

    # 红色2
    lower_red = np.array([0, 43, 46])
    upper_red = np.array([10, 255, 255])
    color_list = []
    color_list.append(lower_red)
    color_list.append(upper_red)
    dict['red2'] = color_list

    # 橙色
    lower_orange = np.array([11, 43, 46])
    upper_orange = np.array([25, 255, 255])
    color_list = []
    color_list.append(lower_orange)
    color_list.append(upper_orange)
    dict['orange'] = color_list

    # 黄色
    lower_yellow = np.array([26, 43, 46])
    upper_yellow = np.array([34, 255, 255])
    color_list = []
    color_list.append(lower_yellow)
    color_list.append(upper_yellow)
    dict['yellow'] = color_list

    # 绿色
    lower_green = np.array([35, 43, 46])
    upper_green = np.array([77, 255, 255])
    color_list = []
    color_list.append(lower_green)
    color_list.append(upper_green)
    dict['green'] = color_list

    # 青色
    lower_cyan = np.array([78, 43, 46])
    upper_cyan = np.array([99, 255, 255])
    color_list = []
    color_list.append(lower_cyan)
    color_list.append(upper_cyan)
    dict['cyan'] = color_list

    # 蓝色
    lower_blue = np.array([100, 43, 46])
    upper_blue = np.array([124, 255, 255])
    color_list = []
    color_list.append(lower_blue)
    color_list.append(upper_blue)
    dict['blue'] = color_list

    # 紫色
    lower_purple = np.array([125, 43, 46])
    upper_purple = np.array([155, 255, 255])
    color_list = []
    color_list.append(lower_purple)
    color_list.append(upper_purple)
    dict['purple'] = color_list

    return dict


import cv2
import numpy as np
#
# filename = './8.png'
#
#
# # 处理图片
# def get_color(frame):
#     #print('go in get_color')
#     hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
#     maxsum = -100
#     color = None
#     color_dict = getColorList()
#     for d in color_dict:
#         #print(color_dict[d][0], color_dict[d][1], d)
#         mask = cv2.inRange(hsv, color_dict[d][0], color_dict[d][1]) # 将高于或者低于该颜色的hsv都设置成0
#
#         cv2.imwrite(d + '.jpg', mask)
#         # binary = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)[1]
#         binary = cv2.dilate(mask, None, iterations=2)
#         cnts, hiera = cv2.findContours(binary.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#         sum = 0
#         for c in cnts:
#             sum += cv2.contourArea(c) # 计算所有轮廓的面积
#         if sum > maxsum:
#             maxsum = sum
#             color = d
#
#     return color
#
#
# if __name__ == '__main__':
#     frame = cv2.imread(filename)
#     #print(get_color(frame))



def rgb2hsv(r, g, b):
    r, g, b = r/255.0, g/255.0, b/255.0
    mx = max(r, g, b)
    mn = min(r, g, b)
    m = mx-mn
    if mx == mn:
        h = 0
    elif mx == r:
        if g >= b:
            h = ((g-b)/m)*60
        else:
            h = ((g-b)/m)*60 + 360
    elif mx == g:
        h = ((b-r)/m)*60 + 120
    elif mx == b:
        h = ((r-g)/m)*60 + 240
    if mx == 0:
        s = 0
    else:
        s = m/mx
    v = mx


    H = h / 2
    S = s * 255.0
    V = v * 255.0
    return H, S, V








import ctypes
from ctypes import wintypes

WH_MOUSE_LL = 14  # 低级鼠标钩子常量
WM_LBUTTONDOWN = 0x0201  # 左键按下事件常量
WM_LBUTTONUP = 0x0202  # 左键回弹事件常量
HC_ACTION = 0

user32 = ctypes.WinDLL('user32', use_last_error=True)
gdi32 = ctypes.WinDLL('gdi32', use_last_error=True)

# 定义一些wintypes中没有的类型
ULONG_PTR = wintypes.WPARAM
LRESULT = wintypes.LPARAM
HOOKPROC = ctypes.WINFUNCTYPE(LRESULT, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)
LPMSG = ctypes.POINTER(wintypes.MSG)

class MSLLHOOKSTRUCT(ctypes.Structure):
    _fields_ = (
        ('pt',          wintypes.POINT),
        ('mouseData',   wintypes.DWORD),
        ('flags',       wintypes.DWORD),
        ('time',        wintypes.DWORD),
        ('dwExtraInfo', ULONG_PTR),
    )

'''
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644986
LowLevelMouseProc回调函数原型:
LRESULT CALLBACK LowLevelMouseProc(
  _In_ int    nCode,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);
'''
LowLevelMouseProc = ctypes.WINFUNCTYPE(LRESULT, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)

# 注册user32中的各API参数和返回值
user32.SetWindowsHookExW.restype = wintypes.HHOOK
user32.SetWindowsHookExW.argtypes = (ctypes.c_int, HOOKPROC, wintypes.HINSTANCE, wintypes.DWORD)
user32.CallNextHookEx.restype = LRESULT
user32.CallNextHookEx.argtypes = (wintypes.HHOOK, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)
user32.GetMessageW.restype = wintypes.BOOL
user32.GetMessageW.argtypes = (LPMSG, wintypes.HWND, wintypes.UINT, wintypes.UINT)
user32.TranslateMessage.restype = wintypes.BOOL
user32.TranslateMessage.argtypes = (LPMSG,)
user32.DispatchMessageW.restype = LRESULT
user32.DispatchMessageW.argtypes = (LPMSG,)
user32.GetDC.restype = wintypes.HDC
user32.GetDC.argtypes = (wintypes.HWND,)
user32.ReleaseDC.restype = ctypes.c_int
user32.ReleaseDC.argtypes = (wintypes.HWND, wintypes.HDC)
# 注册GetPixel
gdi32.GetPixel.restype = wintypes.COLORREF
gdi32.GetPixel.argtypes = (wintypes.HDC, ctypes.c_int, ctypes.c_int)

# 鼠标事件回调函数, wParam是事件类型,lParam是一个MSLLHOOKSTRUCT的结构体,其中包括鼠标坐标等信息
@LowLevelMouseProc
def callback_func(nCode, wParam, lParam):
    if nCode == HC_ACTION:
        if wParam == WM_LBUTTONDOWN:  # 左键按下
            # 解析鼠标坐标
            ms_ll_msg = ctypes.cast(lParam, ctypes.POINTER(MSLLHOOKSTRUCT))[0]
            # 获取对应点像素值
            hdc = user32.GetDC(None)
            x, y = ms_ll_msg.pt.x, ms_ll_msg.pt.y
            color = gdi32.GetPixel(hdc, x, y)
            r = color & 0xFF
            g = (color >> 2) & 0xFF
            b = (color >> 4) & 0xFF
            # #print('coord=(%d,%d), color=#%02X%02X%02X' % (x, y, r, g, b))
            # #print(rgb2hsv(195, 206, 216))
            h, s, v = rgb2hsv(r, g, b)
            color_dict = getColorList()
            for d in color_dict:
                # #print(color_dict[d][0], color_dict[d][1], d)
                if h > color_dict[d][0][0] and h < color_dict[d][1][0] and s > color_dict[d][0][1] and s < \
                        color_dict[d][1][1] and v > color_dict[d][0][2] and v < color_dict[d][1][2]:
                        print(h, s, v, d)

            user32.ReleaseDC(None, hdc)

    return user32.CallNextHookEx(None, nCode, wParam, lParam)


# Windows消息循环
def event_loop():
    msg = wintypes.MSG()
    while True:
        bRet = user32.GetMessageW(ctypes.byref(msg), None, 0, 0)
        if bRet == 0:  # WM_QUIT消息
            #print('bye')
            exit(0)
        elif bRet == -1:  # 错误
            #print('an error happened')
            exit(-1)
        else:
            user32.TranslateMessage(ctypes.byref(msg))
            user32.DispatchMessageW(ctypes.byref(msg))


if __name__ == '__main__':
    # 注册鼠标钩子
    hMouseHook = user32.SetWindowsHookExW(WH_MOUSE_LL, callback_func, None, 0)
    event_loop()




 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值