Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 检测文本图像是否颠倒_Python_Opencv_Image Rotation_Skew - Fatal编程技术网

Python 检测文本图像是否颠倒

Python 检测文本图像是否颠倒,python,opencv,image-rotation,skew,Python,Opencv,Image Rotation,Skew,我有数百张图片(扫描的文档),大部分都是歪斜的。我想使用Python对它们进行反扭曲。 以下是我使用的代码: import numpy as np import cv2 from skimage.transform import radon filename = 'path_to_filename' # Load file, converting to grayscale img = cv2.imread(filename) I = cv2.cvtColor(img, COLOR_BGR2

我有数百张图片(扫描的文档),大部分都是歪斜的。我想使用Python对它们进行反扭曲。
以下是我使用的代码:

import numpy as np
import cv2

from skimage.transform import radon


filename = 'path_to_filename'
# Load file, converting to grayscale
img = cv2.imread(filename)
I = cv2.cvtColor(img, COLOR_BGR2GRAY)
h, w = I.shape
# If the resolution is high, resize the image to reduce processing time.
if (w > 640):
    I = cv2.resize(I, (640, int((h / w) * 640)))
I = I - np.mean(I)  # Demean; make the brightness extend above and below zero
# Do the radon transform
sinogram = radon(I)
# Find the RMS value of each row and find "busiest" rotation,
# where the transform is lined up perfectly with the alternating dark
# text and white lines
r = np.array([np.sqrt(np.mean(np.abs(line) ** 2)) for line in sinogram.transpose()])
rotation = np.argmax(r)
print('Rotation: {:.2f} degrees'.format(90 - rotation))

# Rotate and save with the original resolution
M = cv2.getRotationMatrix2D((w/2,h/2),90 - rotation,1)
dst = cv2.warpAffine(img,M,(w,h))
cv2.imwrite('rotated.jpg', dst)
此代码适用于大多数文档,但某些角度除外:(180和0)和(90和270)通常被检测为相同的角度(即,(180和0)和(90和270)之间没有区别)。所以我得到了很多颠倒的文件

下面是一个例子:

我得到的结果图像与输入图像相同

有没有建议使用Opencv和Python检测图像是否颠倒?
PS:我尝试使用EXIF数据检查方向,但没有找到任何解决方案


编辑:
可以使用Tesseract(Pyteseract for Python)检测方向,但仅当图像包含大量字符时才可能检测方向。
对于可能需要此功能的任何人:

import cv2
import pytesseract


print(pytesseract.image_to_osd(cv2.imread(file_name)))
如果文档包含足够的字符,则Tesseract可以检测方向。但是,当图像的线条较少时,Tesseract建议的方向角通常是错误的。因此,这不可能是100%的解决方案。

您可以使用该模块。要安装它,请执行以下操作:

pip安装alyn
然后使用它来取消查看图像(从主页上拍摄):


请注意,
Alyn
仅用于桌面文字。

假设您已经在图像上运行了角度校正,您可以尝试以下操作以确定图像是否翻转:

  • 将校正后的图像投影到y轴,以便获得每条线的“峰值”。重要提示:实际上几乎总是有两个子峰
  • 通过高斯卷积平滑该投影,以消除精细结构、噪声等
  • 对于每个峰值,检查更强的子峰值是在顶部还是在底部
  • 计算底部有子峰的峰的分数。这是一个标量值,可以让您确信图像的方向正确
  • 步骤3中的峰值查找是通过查找具有高于平均值的截面来完成的。然后通过argmax找到子峰

    这里有一个图来说明这个方法;您的示例图像的几行

    • 蓝色:原始投影
    • 橙色:平滑投影
    • 水平线:整个图像平滑投影的平均值

    下面是一些实现此功能的代码:

    import cv2
    import numpy as np
    
    # load image, convert to grayscale, threshold it at 127 and invert.
    page = cv2.imread('Page.jpg')
    page = cv2.cvtColor(page, cv2.COLOR_BGR2GRAY)
    page = cv2.threshold(page, 127, 255, cv2.THRESH_BINARY_INV)[1]
    
    # project the page to the side and smooth it with a gaussian
    projection = np.sum(page, 1)
    gaussian_filter = np.exp(-(np.arange(-3, 3, 0.1)**2))
    gaussian_filter /= np.sum(gaussian_filter)
    smooth = np.convolve(projection, gaussian_filter)
    
    # find the pixel values where we expect lines to start and end
    mask = smooth > np.average(smooth)
    edges = np.convolve(mask, [1, -1])
    line_starts = np.where(edges == 1)[0]
    line_endings = np.where(edges == -1)[0]
    
    # count lines with peaks on the lower side
    lower_peaks = 0
    for start, end in zip(line_starts, line_endings):
        line = smooth[start:end]
        if np.argmax(line) < len(line)/2:
            lower_peaks += 1
    
    print(lower_peaks / len(line_starts))
    
    导入cv2
    将numpy作为np导入
    #加载图像,转换为灰度,在127处设置阈值并反转。
    page=cv2.imread('page.jpg')
    page=cv2.cvt颜色(page,cv2.COLOR\u bgr2灰色)
    page=cv2.threshold(第127255页,cv2.THRESH\u BINARY\u INV)[1]
    #将页面投影到侧面,并使用高斯曲线使其平滑
    投影=np.和(第1页)
    高斯滤波器=np.exp(-(np.arange(-3,3,0.1)**2))
    高斯滤波器/=np.和(高斯滤波器)
    平滑=np.卷积(投影,高斯滤波器)
    #找到我们期望线条开始和结束的像素值
    遮罩=平滑>np.平均值(平滑)
    边=np.卷积(掩码,[1,-1])
    线_开始=np.其中(边==1)[0]
    行\尾端=np。其中(边==-1)[0]
    #对下侧有峰值的线进行计数
    下_峰值=0
    对于开始,以zip结尾(行\u开始,行\u结束):
    直线=平滑[开始:结束]
    如果np.argmax(线)
    这会为给定的图像打印0.125,因此方向不正确,必须翻转

    请注意,如果图像或图像中的任何内容(可能是数学或图片)没有按行组织,这种方法可能会严重中断。另一个问题是行太少,导致统计数据不准确

    此外,不同的字体可能会导致不同的发行版。你可以在一些图片上尝试一下,看看这种方法是否有效。我没有足够的数据。

    无法对齐扫描的文档

    旋转文档并对行求和。当文档旋转0度和180度时,图像中会出现大量黑色像素:

    使用记分法。为每幅图像的斑马图案相似性评分。具有最佳分数的图像具有正确的旋转。链接到的图像已关闭0.5度。为了可读性,我省略了一些函数,完整的代码可以

    #将图像旋转一圈
    角度=0
    斜纹斑马线
    分数=np.计数非零(行和)
    分数。附加(分数)
    #图像具有最佳旋转
    
    若分数若你们在图像上有脸,那个么它很容易被发现。 我创建了下面的代码来检测脸部是否倒置。 在颠倒的情况下,我们没有得到面编码

    # first install face_recognition
    # pip install --upgrade face_recognition
    def is_image_upside_down(img):
        import face_recognition
        face_locations = face_recognition.face_locations(img)
        encodings = face_recognition.face_encodings(img, face_locations)
        image_is_upside_down = (len(encodings) == 0)
        return image_is_upside_down
    
    import cv2
    filename = 'path_to_filename'
    # Load file, converting to grayscale
    img = cv2.imread(filename)
    if is_image_upside_down(img):
        print("rotate to 180 degree")
    else:
        print("image is straight")
    
    

    这不是一个解决方案,但您可以使用的另一个启发式方法(假设您正在阅读拉丁语脚本)是比较左半部和右半部或上半部和下半部的黑色量。如果一页的右边(换行符)和/或底部的黑色明显增多,我猜很可能是颠倒的。报纸上是否总是有标题?你能说是否有规律可循吗?我会把OCR作为最后一个选项……它将更容易检测白点,创建一个矩形并测量其大小。就像标题和其他部分之间的白点一样。@singrium嗯,我不确定,如果它们的大小是恒定的,你可以使用一些卷积滤波器,看看它们是直立还是倒置工作得更好(你得到更多的“匹配”)。。。否则我不确定(我对CV tbh不太了解),我的意思是你当然可以创建一个神经网络或其他分类方法,但这需要更多的工作。好的,对于那些带有蓝线的文档,你可以读取图像的蓝色通道,并创建一个蓝色的树状结构。如果它检测到蓝色的存在,并且在文档的中间,您可以说文档是颠倒的。您可以将页面预处理为完全灰度高对比度,然后按照jdehesa的建议应用黑白测试
    # Rotate the image around in a circle
    angle = 0
    while angle <= 360:
        # Rotate the source image
        img = rotate(src, angle)    
        # Crop the center 1/3rd of the image (roi is filled with text)
        h,w = img.shape
        buffer = min(h, w) - int(min(h,w)/1.15)
        roi = img[int(h/2-buffer):int(h/2+buffer), int(w/2-buffer):int(w/2+buffer)]
        # Create background to draw transform on
        bg = np.zeros((buffer*2, buffer*2), np.uint8)
        # Compute the sums of the rows
        row_sums = sum_rows(roi)
        # High score --> Zebra stripes
        score = np.count_nonzero(row_sums)
        scores.append(score)
        # Image has best rotation
        if score <= min(scores):
            # Save the rotatied image
            print('found optimal rotation')
            best_rotation = img.copy()
        k = display_data(roi, row_sums, buffer)
        if k == 27: break
        # Increment angle and try again
        angle += .75
    cv2.destroyAllWindows()
    
    # Find the area from the top of page to top of image
    _, bg = area_to_top_of_text(best_rotation.copy())
    right_side_up = sum(sum(bg))
    # Flip image and try again
    best_rotation_flipped = rotate(best_rotation, 180)
    _, bg = area_to_top_of_text(best_rotation_flipped.copy())
    upside_down = sum(sum(bg))
    # Check which area is larger
    if right_side_up < upside_down: aligned_image = best_rotation
    else: aligned_image = best_rotation_flipped
    # Save aligned image
    cv2.imwrite('/home/stephen/Desktop/best_rotation.png', 255-aligned_image)
    cv2.destroyAllWindows()
    
    # first install face_recognition
    # pip install --upgrade face_recognition
    def is_image_upside_down(img):
        import face_recognition
        face_locations = face_recognition.face_locations(img)
        encodings = face_recognition.face_encodings(img, face_locations)
        image_is_upside_down = (len(encodings) == 0)
        return image_is_upside_down
    
    import cv2
    filename = 'path_to_filename'
    # Load file, converting to grayscale
    img = cv2.imread(filename)
    if is_image_upside_down(img):
        print("rotate to 180 degree")
    else:
        print("image is straight")