Python中如何识别一张图片上文字的颜色

各位好,最近小弟遇到一个问题,就是怎么识别一张图片上文字的颜色,我目前的解决方法如下:

首先使用 ocr 工具先在图片上找出一行文本,然后把这一行文本中的每个文字都切片,然后对每个切片抽取 5 个颜色,选择占面积最大的颜色作为该切片上的文字颜色,但是因为一张图片上文字的颜色可能不一样,我这里只是想抽取一种颜色,所以我就把所有切片的文字颜色综合起来,找出其中出现数量最多的颜色,并把这个颜色作为该张图片的文字颜色。

以上就是我的方法,但是很耗时间,各位老铁有什么更好的方法吗?


Python中如何识别一张图片上文字的颜色

30 回复

文字背景色是纯色么?你的方法能排除文字背景色么?觉得直接对文字部分位图数组遍历,排除掉背景色像素值,剩下前景色求颜色平均值,效率应该不会很差吧。


这个问题挺有意思的。识别图片上文字的颜色,关键在于先定位文字区域,再分析该区域的颜色。通常结合OCR(文字识别)和图像处理来做。

核心思路是:

  1. 文字检测与提取:用PaddleOCR、EasyOCR或Tesseract找到图片中的文字及其位置(包围框)。
  2. 颜色分析:对每个文字包围框内的像素进行颜色分析,比如取平均值或众数。

下面是一个使用PaddleOCR(识别准,对中文友好)和PIL的完整示例:

import cv2
import numpy as np
from PIL import Image
import paddleocr
from collections import Counter

def get_text_color(image_path):
    """
    识别图片中文字的颜色
    Args:
        image_path: 图片路径
    Returns:
        list: 每个元素是一个字典,包含文字、位置和主要颜色(RGB)
    """
    # 初始化PaddleOCR
    ocr = paddleocr.PaddleOCR(use_angle_cls=True, lang='ch')
    
    # 读取图片
    img_cv = cv2.imread(image_path)
    img_pil = Image.open(image_path).convert('RGB')
    
    # 进行OCR识别
    result = ocr.ocr(image_path, cls=True)
    
    text_infos = []
    
    if result and result[0]:
        for line in result[0]:
            # line结构: [[[x1,y1],[x2,y2],[x3,y3],[x4,y4]], (文字, 置信度)]
            box = line[0]  # 四个点的坐标
            text = line[1][0]  # 识别出的文字
            
            # 获取包围框的坐标边界
            xs = [point[0] for point in box]
            ys = [point[1] for point in box]
            x_min, x_max = int(min(xs)), int(max(xs))
            y_min, y_max = int(min(ys)), int(max(ys))
            
            # 从PIL图像中裁剪出文字区域
            text_region = img_pil.crop((x_min, y_min, x_max, y_max))
            
            # 将区域转换为numpy数组进行分析
            region_array = np.array(text_region)
            
            # 计算颜色直方图,取出现最多的颜色
            # 这里将颜色量化到16级以减少噪声
            pixels = region_array.reshape(-1, 3)
            quantized_pixels = (pixels // 16) * 16
            color_counts = Counter(map(tuple, quantized_pixels))
            most_common_color = color_counts.most_common(1)[0][0]
            
            text_infos.append({
                'text': text,
                'position': (x_min, y_min, x_max, y_max),
                'color_rgb': most_common_color
            })
    
    return text_infos

# 使用示例
if __name__ == "__main__":
    # 替换为你的图片路径
    results = get_text_color('your_image.jpg')
    
    for info in results:
        print(f"文字: {info['text']}")
        print(f"位置: {info['position']}")
        print(f"颜色(RGB): {info['color_rgb']}")
        print("-" * 30)

几点说明:

  • 安装依赖:运行前需要 pip install paddlepaddle paddleocr opencv-python pillow。PaddleOCR第一次运行会自动下载模型。
  • 颜色分析策略:示例中用了颜色量化后取众数,这能避免背景色干扰,更准确地代表文字本身的颜色。你也可以尝试其他方法,比如取中值或对文字笔画上的像素采样。
  • 复杂背景:如果背景很花哨,可能需要更精细的前景提取(比如用二值化或形态学操作先突出文字),再分析颜色。
  • 多颜色文字:如果单个文字或单词内部有渐变或多种颜色,这个方法会返回一个主要颜色。要检测颜色变化,需要更细粒度的分析,比如按像素或小区域处理。

简单说就是:用OCR定位文字,然后分析对应区域像素的颜色特征。

文字背景不一定是纯色的,但是使用 ocr 选中每一个颜色的框框里按道理来说文字所占的颜色面积最大,这是我的依据。直接排除背景色像素值,因为是这样,我会对 ocr 识别出的文字图片抽取 5 个颜色,所以现在就不知道哪个是背景哪个是前景,如果默认面积大的就是背景的话会有问题

我给你看看我这边做出来的效果吧,黑色是 0 ,也就是非文字,白色是 1 ,也就是文字颜色
![]( )
![]( )

我没有细想,你的黑白图哪来的?是 ocr 结果么?如果原图和黑白图大小一样,剩下的就是让程序读取原图在黑白图中为白色的部分。

黑白图是我用我上面说的方法自己做出来的效果,我这个方法是可以识别出部分文字颜色的,但是很耗时间,大概一张图要 1min+,所以想问下有没有更好的方法

有相关软件,叫什么 pickup colour 什么的

你说的是那种取色工具吗?我这里想实现完全自动化,让计算机识别文字颜色,中间不需要人为干预的那种 233

可以先把颜色从 RGB 转换成 HSV ,然后直接判断图片的颜色“角度”就可以了。

如果用 OpenCV 的话,可以考虑 cvtColor, InRange 两个函数,应该可以直接得到红色文字了。

没有用过 opencv ,你这个方法是指针对某个颜色的文字吗?假设文字的颜色有多种呢?我这里用的颜色通道是 LAB ,你说的颜色角度是啥?

如果有 ocr 工具的源代码,直接识别文字的时候顺带拿一下颜色应该最效率……

找特征点,遍历特征点找出现最多次的颜色.

补充一下,遍历特征点附近的 8*8 色块,找出现最多次的颜色

HSV 的颜色是用角度标识的, H 通道,在 openCV 里面范围是 0-180 。比如,红色是 0-10 和 160-180 ,蓝色大概是 35-55 ,等等,还可以区分绿色,紫色,青色等等。

好奇楼上,换成 HSV 颜色空间就能区分出字上的像素和背景像素?

我的思路: 1 )缩放到一个合适的比例再处理(怎么会一张图片几分钟……); 2 )边缘提取; 3 )细化边缘(用腐蚀?); 3 )求边缘像素的颜色众数。

细化边缘是因为字体和背景过渡的地方(很可能)反锯齿了。

或许应该用“线提取”而不是“边缘提取”。

他的意思是,转换成 HSV 后,颜色信息就只包含在一个通道内,检查这一个通道就可以判断颜色。如果是 RGB 的话,颜色信息就分散到三个通道内了。

原来如此,这个我倒是没有想到,但是我想了一下,如果只是换一下颜色空间的话貌似还是没解决我的问题,不过我试试 hsv 套在我的方法上会不会好点,谢谢两位

哎呀,我忘了缩放了,,你说的边缘提取这种需要先把图像二值化了把,但是不知道文字颜色的话如何二值化,咋设置 thresh ,我试过把一张图灰度化,然后二值化图像连通域分析,但是通常如果图像背景是深色,前景是淡色的话会有用,遇上背景是白色字是黑色这种情况就不行了,因为我二值化的时候都是把 thresh 设成 0.5 ,偏白色大部分会被二值化为 1 ,所以效果有限。也不知道 ocr 中识别文字区域的那一步是咋做的,我找找代码好了,谢谢老铁

OCR 选区建立的时候普遍就是根据颜色。
类似 PS 中的选择色彩范围。

边缘提取不能二值化啊 ==(只有两种像素还提取啥啊 ==)。通常先处理成灰度倒是真的。

你都得 OCR 的结果了,直接对结果进行边缘检测就能提取边缘了,干净有效。或者用 OCR 结果与原图逐个像素进行与运算,相当于抠图把文字从原图里抠出来,然后马赛克化,再从 HSV 通道统计颜色信息。
理论上来说,统计个颜色不会很慢,跑 1min 太夸张了


我根据两位的思路做了一个 ocr 的前期的文字区域识别的方法,但是有点问题,先给你们看下效果图:
![]( )
![]( )
![]( )
但是有个问题,在前期选区的时候需要对图像进行斑点检测,然后生成二值化图像,问题就出在二值化图像这里,阈值不好选,跟文字的颜色和文字所在背景的颜色有很大的关系,以下是检测出错的:
![]( )
两位老哥有啥建议不

对哦,我试试,谢谢啦

这些文字的框的坐标你都知道吗?(用的什么软件?)如果是自己代码找到了框的位置,画上去的,你就可以直接统计了啊。==

对,我进行斑点检测,找到的所有框,用 python 的 skimage 库做的, opencv 应该也可以。直接统计还是会有点小问题的,我还在想法解决

PHP 聚类算法 就可以的,代码不多 几百行搞定了
http://www.phpfensi.com/php/20140827/4848.html

谢谢啦,提取图像颜色不是问题,问题在于要提取图像上某一个元特定素的颜色的问题,这个可能就会涉及到识别和检测相关的算法

大佬,请问您最后解决的方案是什么呀

回到顶部