You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提取图像中文本颜色并隔离对应彩色文本?

提取图像文本颜色并过滤非文本内容的优化方案

你现在遍历所有颜色逐个掩蔽的方法,确实会生成大量无效图像,这里给你几个更高效的思路,直接定位文本对应的颜色:

方法一:先通过OCR定位文本区域,再提取区域内主颜色

既然已经在用pytesseract,可以先让它识别文本的位置,只在这些区域里统计颜色,不用处理整张图的所有颜色,直接锁定文本的颜色范围:

步骤:

  • 用pytesseract获取每个文本块的边界框
  • 裁剪出所有文本区域,合并成掩码区域
  • 在掩码区域内统计颜色频率,取占比最高的颜色作为文本色
  • 基于该颜色生成掩膜,保留文本内容

代码示例:

import cv2
import numpy as np
from PIL import Image
import pytesseract
from pytesseract import Output

# 读取图像
img = cv2.imread('z.jpg')
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(rgb_img)

# 用pytesseract获取文本区域的边界框
d = pytesseract.image_to_data(pil_img, output_type=Output.DICT)
n_boxes = len(d['text'])

# 创建文本区域掩码
mask = np.zeros(img.shape[:2], dtype=np.uint8)
for i in range(n_boxes):
    if int(d['conf'][i]) > 60:  # 过滤低置信度识别结果
        (x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
        mask[y:y+h, x:x+w] = 255

# 提取文本区域的像素
text_pixels = rgb_img[mask == 255]
if len(text_pixels) == 0:
    print("未识别到有效文本区域")
    exit()

# 统计文本区域内的颜色频率
from collections import Counter
color_counts = Counter([tuple(p) for p in text_pixels])
# 取占比最高的颜色(文本色)
dominant_color = color_counts.most_common(1)[0][0]
print(f"识别到的文本主颜色:{dominant_color}")

# 生成颜色掩膜(考虑颜色容差)
tol = 5
lower = np.array([dominant_color[0]-tol, dominant_color[1]-tol, dominant_color[2]-tol], dtype=np.uint8)
upper = np.array([dominant_color[0]+tol, dominant_color[1]+tol, dominant_color[2]+tol], dtype=np.uint8)
# 转换为OpenCV的BGR格式
lower_bgr = lower[::-1]
upper_bgr = upper[::-1]

text_mask = cv2.inRange(img, lower_bgr, upper_bgr)
# 保留文本内容,其余置为黑色
result = cv2.bitwise_and(img, img, mask=text_mask)

cv2.imshow('Text Only', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

方法二:用颜色聚类区分文本与背景

如果OCR定位不准,还可以用K-means聚类把图像颜色分成两类(文本和背景),再结合形态学特征判断哪一类是文本:

步骤:

  • 将图像像素转为二维数组,用K-means聚成2类
  • 分别生成两类的掩膜,通过连通域分析判断哪个是文本(文本通常是分散的小连通域,面积占比更小)
  • 保留对应类的颜色

代码示例:

import cv2
import numpy as np
from sklearn.cluster import KMeans

img = cv2.imread('z.jpg')
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 转换为二维像素数组
pixels = rgb_img.reshape((-1, 3))
# K-means聚类成2类
kmeans = KMeans(n_clusters=2, random_state=0).fit(pixels)
labels = kmeans.labels_.reshape(rgb_img.shape[:2])

# 获取两类的颜色
colors = kmeans.cluster_centers_.astype(np.uint8)

# 生成两个掩膜
mask0 = (labels == 0).astype(np.uint8)*255
mask1 = (labels == 1).astype(np.uint8)*255

# 判断哪个掩膜是文本:文本连通域数量通常更多
def is_text_mask(mask):
    num_labels, _ = cv2.connectedComponents(mask)
    return num_labels > 10  # 阈值可根据实际情况调整

text_mask = mask1 if is_text_mask(mask1) else mask0
text_color = colors[1] if is_text_mask(mask1) else colors[0]
print(f"聚类得到的文本颜色:{text_color}")

# 生成最终结果
result = cv2.bitwise_and(img, img, mask=text_mask)
cv2.imshow('Text Only', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

现有代码的问题修正

你原来的代码有两个小问题:

  • colors = sorted(image.getcolors(...)) 里的image应该是cimage,因为你用cimage = Image.open(...)初始化的图像对象
  • PIL的RGB格式和OpenCV的BGR格式不匹配,直接用cimage给OpenCV处理会导致颜色判断错误,需要先转换格式

内容的提问来源于stack exchange,提问作者kadash12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:52:46