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

如何使用Pytesseract和Python 3从复杂背景照片中提取文本?

嘿,我完全懂你现在的窘境——复杂背景的OCR可比单一底色的验证码难多了,尤其是你作为刚接触Python+CV+Tesseract的新手,试了一堆方法都没效果肯定头大。不过别慌!既然你提到所有字符的字体颜色是统一的,这就是咱们的突破口,接下来我给你一套针对性的解决方案,一步步来搞定域名和电话号码的提取:

第一步:利用颜色分割精准分离字符与背景

因为字符颜色是固定的,咱们可以直接通过颜色过滤把字符从杂乱背景里抠出来,这比通用的灰度二值化靠谱多了。这里推荐用HSV色彩空间(比RGB更抗光照干扰),步骤如下:

import cv2
import numpy as np

# 读取目标图片
img = cv2.imread('your_photo.jpg')
# 转成HSV色彩空间(OpenCV默认是BGR,所以要转)
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 重点:调整下面的HSV范围,匹配你的字符颜色
# 你可以用取色工具(比如Photoshop、在线取色器)获取字符的HSV值,然后上下浮动范围
lower_char_color = np.array([90, 50, 50])  # 示例:蓝色下限
upper_char_color = np.array([130, 255, 255])  # 示例:蓝色上限

# 生成颜色掩码:只保留符合颜色范围的区域
color_mask = cv2.inRange(hsv_img, lower_char_color, upper_char_color)
# 把掩码和原图结合,只留下字符区域
char_only_img = cv2.bitwise_and(img, img, mask=color_mask)
# 转灰度图,方便后续处理
gray_char = cv2.cvtColor(char_only_img, cv2.COLOR_BGR2GRAY)
# 二值化:让字符变成纯黑/纯白,增强对比度
_, thresh_img = cv2.threshold(gray_char, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
第二步:用形态学操作清理干扰噪点

复杂背景下,颜色分割后可能会残留一些小噪点,或者字符有轻微断裂,咱们用开闭运算来修复:

# 创建结构元素:根据字符大小调整,比如3x3的矩形(字符大就用5x5)
kernel = np.ones((3, 3), np.uint8)
# 先腐蚀掉小噪点,再膨胀修复字符断裂(闭运算)
cleaned_img = cv2.morphologyEx(thresh_img, cv2.MORPH_CLOSE, kernel)
第三步:文本区域裁剪(可选但能大幅提升识别率)

如果图片里的文本分散在不同位置,咱们可以用轮廓检测定位所有字符区域,然后合并裁剪成一个小图,让Tesseract聚焦在文本上:

# 查找所有轮廓
contours, _ = cv2.findContours(cleaned_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 过滤掉太小的轮廓(排除非字符的噪点)
min_char_area = 50  # 根据你的字符大小调整,比如小字符设30,大字符设100
text_boxes = []
for cnt in contours:
    area = cv2.contourArea(cnt)
    if area > min_char_area:
        x, y, w, h = cv2.boundingRect(cnt)
        text_boxes.append((x, y, w, h))

# 合并所有文本区域成一个大框
if text_boxes:
    x_min = min([x for x, y, w, h in text_boxes])
    y_min = min([y for x, y, w, h in text_boxes])
    x_max = max([x + w for x, y, w, h in text_boxes])
    y_max = max([y + h for x, y, w, h in text_boxes])
    cropped_text_img = cleaned_img[y_min:y_max, x_min:x_max]
else:
    cropped_text_img = cleaned_img
第四步:用Tesseract针对性识别+正则提取目标内容

咱们不需要识别所有文本,只需要域名和电话号码,所以给Tesseract加配置限制识别范围,再用正则表达式精准过滤:

import pytesseract
import re

# 如果你没把Tesseract加到环境变量,就指定路径
# pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'

# 自定义配置:只识别字母、数字、点、横杠(刚好匹配域名和电话的字符)
# --oem 3:使用默认OCR引擎;--psm 6:假设图片是单一文本块
custom_config = r'--oem 3 --psm 6 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-'
raw_text = pytesseract.image_to_string(cropped_text_img, config=custom_config)

# 用正则提取域名(匹配xxx.com/xxx.net这类格式)
domain_regex = r'\b(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}\b'
extracted_domains = re.findall(domain_regex, raw_text)

# 用正则提取电话号码(匹配带区号、横杠、空格的常见格式)
phone_regex = r'\b(?:\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b'
extracted_phones = re.findall(phone_regex, raw_text)

# 输出结果
print("提取到的域名:", extracted_domains)
print("提取到的电话号码:", extracted_phones)
新手调试小技巧
  • HSV范围调整:这是最关键的一步!如果掩码没把所有字符留住,就扩大HSV的上下限;如果背景残留太多,就缩小范围。你可以写个小脚本用滑动条实时调整,比手动试高效多了。
  • 字符倾斜矫正:如果文本是倾斜的,先用霍夫变换检测直线角度,把图片旋转回水平,再进行后续处理。
  • Tesseract参数调整:如果识别不准,试试换psm参数(比如psm 3是自动分页,psm 4是假设单列文本),或者更新Tesseract的语言包。

慢慢来,先拿一张样本图把预处理参数调对,再逐步扩展到其他图片,肯定能搞定的!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 15:39:06