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

无需手动选点的透视变换:畸变图像字符检测技术求助

解决方案

一、自动透视校正(无需手动选点)

针对3D畸变图像,先通过自动检测文档轮廓完成透视变换校正,解决畸变问题:

  1. 预处理图像:灰度化+高斯模糊去噪+Canny边缘检测+形态学闭操作增强轮廓
  2. 检测文档外轮廓:筛选面积最大的四边形轮廓(默认字符所在区域为近似矩形)
  3. 透视变换:将畸变四边形转换为正矩形,还原平面视角
import cv2
import numpy as np

def auto_perspective_correction(img):
    # 灰度化
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 高斯模糊去噪
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    # Canny边缘检测
    edges = cv2.Canny(blurred, 50, 150)
    # 形态学闭操作增强轮廓连贯性
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
    
    # 寻找轮廓并按面积排序
    cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]
    
    # 筛选四边形轮廓(文档边界)
    screenCnt = None
    for c in cnts:
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.02 * peri, True)
        if len(approx) == 4:
            screenCnt = approx
            break
    
    # 排序顶点(左上、右上、右下、左下)
    def order_points(pts):
        rect = np.zeros((4, 2), dtype="float32")
        s = pts.sum(axis=1)
        rect[0] = pts[np.argmin(s)]
        rect[2] = pts[np.argmax(s)]
        diff = np.diff(pts, axis=1)
        rect[1] = pts[np.argmin(diff)]
        rect[3] = pts[np.argmax(diff)]
        return rect
    
    rect = order_points(screenCnt.reshape(4, 2))
    (tl, tr, br, bl) = rect
    
    # 计算目标图像尺寸
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))
    
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))
    
    # 生成透视变换矩阵并应用
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")
    
    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(img, M, (maxWidth, maxHeight))
    
    return warped

二、校正后字符检测优化

校正后的图像用改进逻辑解决边缘字符漏检问题:

  1. 自适应阈值:替代固定阈值,适配边缘区域光照不均
  2. 轮廓过滤:通过面积、宽高比过滤非字符轮廓
  3. OCR验证:用Tesseract确认轮廓为字符区域
import pytesseract
import matplotlib.pyplot as plt

# 读取图像并完成校正
img = cv2.imread("hel2.png")
corrected_img = auto_perspective_correction(img)

# 预处理校正后的图像
gray_corrected = cv2.cvtColor(corrected_img, cv2.COLOR_BGR2GRAY)
# 自适应阈值处理,适配边缘光照差异
thresh_corrected = cv2.adaptiveThreshold(gray_corrected, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)

# 寻找轮廓
cntrs = cv2.findContours(thresh_corrected, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]

result = corrected_img.copy()
for c in cntrs:
    x, y, w, h = cv2.boundingRect(c)
    # 过滤过小或宽高比异常的轮廓
    if w < 5 or h < 10 or w/h > 3 or h/w > 5:
        continue
    # 提取区域用Tesseract验证是否为字符
    char_region = gray_corrected[y:y+h, x:x+w]
    char_text = pytesseract.image_to_string(char_region, config="--psm 10")
    if char_text.strip():
        cv2.rectangle(result, (x, y), (x + w, y + h), (0, 0, 255), 2)

# 显示结果
plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
plt.show()

额外说明

  • 若畸变场景为曲面(非平面3D畸变),可替换为SIFT特征匹配+单应性变换实现更鲁棒的校正
  • 自适应阈值相比固定阈值,能避免边缘字符因光照问题被误判为背景
  • 轮廓过滤+OCR验证可有效减少噪声轮廓干扰,提升边缘字符检测准确率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 07:17:51