繁体   English   中英

根据文本方向检测图像方向角度

[英]Detect image orientation angle based on text direction

我正在从事一项 OCR 任务,以从多个身份证明文件中提取信息。 一个挑战是扫描图像的方向。 需要修复 PAN、Aadhaar、驾驶执照或任何身份证明的扫描图像的方向。

已经在 Stackoverflow 和其他论坛上尝试了所有建议的方法,例如 OpenCV minAreaRect、霍夫线变换、FFT、单应性、带有 psm 0 的 tesseract osd。没有一个有效。

逻辑应返回文本方向的角度 - 0、90 和 270 度。 附上0、90、270度的图片。 这与确定偏度无关。 在此处输入图像描述

这是一种基于大部分文本偏向一侧的假设的方法。 这个想法是我们可以根据主要文本区域所在的位置来确定角度

  • 将图像转换为灰度和高斯模糊
  • 获取二值图像的自适应阈值
  • 使用轮廓区域查找轮廓和过滤
  • 在蒙版上绘制过滤轮廓
  • 根据方向水平或垂直分割图像
  • 计算每一半的像素数

转换为灰度和高斯模糊后,我们自适应阈值得到二值图像

在此处输入图像描述

从这里我们找到轮廓并使用轮廓区域进行过滤以去除小的噪声粒子和大边界。 我们将通过此过滤器的任何轮廓绘制到蒙版上

在此处输入图像描述

为了确定角度,我们根据图像的尺寸将图像分成两半。 如果width > height ,那么它必须是水平图像,所以我们垂直分成两半。 如果height > width ,那么它必须是垂直图像,所以我们水平分成两半

在此处输入图像描述 在此处输入图像描述

现在我们有两半,我们可以使用cv2.countNonZero()来确定每一半的白色像素的数量。 这是确定角度的逻辑:

if horizontal
    if left >= right 
        degree -> 0
    else 
        degree -> 180
if vertical
    if top >= bottom
        degree -> 270
    else
        degree -> 90

左 9703

对 3975

因此图像是0度。 这是其他方向的结果

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

左 3975

右 9703

我们可以得出结论,图像翻转了 180 度

这是垂直图像的结果。 注意因为它是一个垂直的图像,我们水平分割

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

在此处输入图像描述

顶部 3947

底部9550

因此结果是 90 度

import cv2
import numpy as np

def detect_angle(image):
    mask = np.zeros(image.shape, dtype=np.uint8)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (3,3), 0)
    adaptive = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,15,4)

    cnts = cv2.findContours(adaptive, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]

    for c in cnts:
        area = cv2.contourArea(c)
        if area < 45000 and area > 20:
            cv2.drawContours(mask, [c], -1, (255,255,255), -1)

    mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
    h, w = mask.shape
    
    # Horizontal
    if w > h:
        left = mask[0:h, 0:0+w//2]
        right = mask[0:h, w//2:]
        left_pixels = cv2.countNonZero(left)
        right_pixels = cv2.countNonZero(right)
        return 0 if left_pixels >= right_pixels else 180
    # Vertical
    else:
        top = mask[0:h//2, 0:w]
        bottom = mask[h//2:, 0:w]
        top_pixels = cv2.countNonZero(top)
        bottom_pixels = cv2.countNonZero(bottom)
        return 90 if bottom_pixels >= top_pixels else 270

if __name__ == '__main__':
    image = cv2.imread('1.png')
    angle = detect_angle(image)
    print(angle)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM