前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python: 屏幕取色器(识别屏幕上不同位置的颜色)

Python: 屏幕取色器(识别屏幕上不同位置的颜色)

作者头像
Exploring
发布2022-09-20 14:04:23
4.7K0
发布2022-09-20 14:04:23
举报
文章被收录于专栏:数据处理与编程实践

文章背景:工作中,有时候需要判断图片中不同位置的颜色。有些颜色不太容易区分,所以想通过Python编写代码,通过屏幕取点,获取某个位置的颜色值。

代码逻辑:

(1)文末参考资料[2]的csv文件(记为颜色表)中给出了865种颜色的英文名称和对应的RGB数值,在此基础上,笔者添加了相应的中文名称,如下表所示。

(2)通过鼠标在屏幕上取点,获取指定位置的RGB数值,然后与颜色表中各行的RGB数值进行匹配,返回RGB数值最接近的颜色信息。

Python代码:

代码语言:javascript
复制
# Python实现屏幕取色器功能
# adapted form https://mp.weixin.qq.com/s/S_FNIqtqdvlEgplM7UuvNg

import os
import pandas as pd
from time import sleep
from PIL import ImageGrab, Image

import uuid
import pyperclip

import tkinter
import tkinter.messagebox

def get_color_name(r, g, b, csv_df):
    # 基于给定的R,G,B和颜色表,匹配与所取点RGB数值最接近的颜色。
    
    min_diff = 10000
    color = ["" for i in range(6)]

    for i in range(len(csv_df)):
        d = abs(r - int(csv_df.loc[i, "R"])) + abs(g - int(csv_df.loc[i, "G"]))+ abs(b - int(csv_df.loc[i, "B"]))
        
        if d <= min_diff:
            min_diff = d
            color[0] = csv_df.loc[i,"color_name"]
            color[1] = csv_df.loc[i,"color_Chi"]
            color[2] = str(int(csv_df.loc[i, "R"]))
            color[3] = str(int(csv_df.loc[i, "G"]))
            color[4] = str(int(csv_df.loc[i, "B"]))
            color[5] = csv_df.loc[i, "hex"]
            
    return color

class MyCapture(object):
    # 处理全屏截图

    def __init__(self, png,root,csv_df):

        # 获取屏幕尺寸
        screenWidth = root.winfo_screenwidth()
        screenHeight = root.winfo_screenheight()

        # 创建顶级组件容器,与屏幕尺寸一样大
        self.top = tkinter.Toplevel(root, width=screenWidth, height=screenHeight)

        # 不显示最大化、最小化按钮
        self.top.overrideredirect(True)
        
        # create a new PhotoImage object
        self.image = tkinter.PhotoImage(file=png)

        # 创建画布
        self.canvas = tkinter.Canvas(self.top,bg='white', width=screenWidth, height=screenHeight)

        # 显示全屏截图
        self.canvas.create_image(screenWidth//2, screenHeight//2, anchor = tkinter.CENTER, image=self.image)

        # 获取鼠标左键抬起的位置,取色
        def onLeftButtonUp(event):

            im = Image.open(png)
            
            # retrieves the red, green, blue (RGB) color value of the pixel at the specified coordinates
            color = im.getpixel((event.x, event.y))
            
            temp = [str(item) for item in color]
            RGB = "取点的RGB数值:" + ", ".join(temp) + "\n\n"
            
            R,G,B = color
            
            color = get_color_name(R,G,B,csv_df)
            
            color_RGB = "RGB数值:" + ", ".join(color[2:5]) + "\n"
            color_hex = "十六进制值:" + color[5] + "\n"
            color_Eng = "英文名称:" + color[0] + "\n"
            color_Chi = "中文名称:" + color[1] + "\n\n"
            
            msg = "中文名称已复制到剪切板!"
            
            tkinter.messagebox.showinfo('结果展示', RGB + color_RGB + color_hex + color_Eng + color_Chi + msg)
            
            pyperclip.copy(color[1])

            # 关闭Toplevel窗口对象
            self.top.destroy()

        self.canvas.bind('<ButtonRelease-1>', onLeftButtonUp)
        self.canvas.pack(fill=tkinter.BOTH, expand=True)


def buttonCaptureClick(root,buttonCapture,csv_df):
    # 截图

    # 最小化主窗口
    root.state('icon')

    sleep(0.2)
    
    # 获取临时文件名        
    filename = uuid.uuid4().hex + ".png"
    
    # 拍摄屏幕全屏,Windows上以RGB图像的形式返回。
    im = ImageGrab.grab()
    
    im.save(filename)
    im.close()

    # 显示全屏幕截图
    w = MyCapture(filename,root,csv_df)
    
    # wait_window seems to not return until the given widget passed as parameter is not destroyed.
    buttonCapture.wait_window(w.top)

    # 截图结束,恢复主窗口,并删除临时的全屏幕截图文件
    root.state('normal')
    os.remove(filename)

def main():
    
    # 获取颜色数据表
    index = ["color", "color_name","hex", "color_Chi","R", "G", "B"]
    csv_df = pd.read_csv('colors.csv', names=index, header=None, encoding='chinese')
    
    # 窗口
    root = tkinter.Tk()
    root.title("颜色识别器v2")
    
    # 窗口宽250,高60; 左上角坐标:(400,300)
    root.geometry('250x60+400+300')
    
    #不可更改窗口大小
    # root.resizable(False, False)
    
    buttonCapture = tkinter.Button(root, text='取色',width=6,command=lambda:buttonCaptureClick(root,buttonCapture,csv_df))
    buttonExit = tkinter.Button(root, text='退出',width=6,command=root.destroy)
    
    buttonCapture.grid(row=0,column=0,padx = 40,pady =10)
    buttonExit.grid(row=0,column=1,padx = 40,pady =10)

    #启动消息主循环
    root.mainloop()

if __name__ == '__main__':
    main()

效果演示:

http://mpvideo.qpic.cn/0bc3taaakaaazyaaitishjrfbggdawmaabia.f10002.mp4?dis_k=80bd5645282a6971b746f16b2da516eb&dis_t=1663653830&vid=wxv_2277589062624641024&format_id=10002&support_redirect=0&mmversion=false

参考资料:

[1] Python实现屏幕取色器功能

[2] color-names(https://github.com/codebrainz/color-names/blob/master/output/colors.csv)

[3] 基于Python的颜色识别器(https://zhuanlan.zhihu.com/p/342372391)

[4] Python PIL ImageGrab.grab()用法及代码示例(https://vimsky.com/examples/usage/pyhton-pil-imagegrab-grab-method.html)

[5] 如何让tkinter窗口最小化(https://www.pynote.net/archives/1352)

[6] What does the"wait_window" method do(https://stackoverflow.com/questions/28388346/what-does-thewait-window-method-do)

[7] Tkinter PhotoImage(https://www.pythontutorial.net/tkinter/tkinter-photoimage/)

[8] Canvas image objects(https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/create_image.html)

[9] Python PIL | getpixel() Method(https://www.geeksforgeeks.org/python-pil-getpixel-method/)

[10] Python GUI设计:tkinter菜鸟编程(https://item.jd.com/12667860.html)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据处理与编程实践 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档