Обнаружение и исправление перекоса текста

Есть ли способ (используя что-то вроде OpenCV) для обнаружения перекоса текста и исправления его путем поворота изображения? В значительной степени это так?

enter image description here

enter image description here

Поворот изображения кажется достаточно простым, если вы знаете угол, но для изображений, которые я обрабатываю, я не буду... его нужно будет каким-то образом обнаружить.

Ответ 1

На основе вашего вышеуказанного комментария здесь приведен код, основанный на учебнике здесь, отлично работающем для вышеуказанного изображения,

Источник

enter image description here

повернутого

enter image description here

 Mat src=imread("text.png",0);
 Mat thr,dst;
 threshold(src,thr,200,255,THRESH_BINARY_INV);
 imshow("thr",thr);

  std::vector<cv::Point> points;
  cv::Mat_<uchar>::iterator it = thr.begin<uchar>();
  cv::Mat_<uchar>::iterator end = thr.end<uchar>();
  for (; it != end; ++it)
    if (*it)
      points.push_back(it.pos());

  cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));
  cv::Mat rot_mat = cv::getRotationMatrix2D(box.center, box.angle, 1);

  //cv::Mat rotated(src.size(),src.type(),Scalar(255,255,255));
  Mat rotated;
  cv::warpAffine(src, rotated, rot_mat, src.size(), cv::INTER_CUBIC);
 imshow("rotated",rotated);

Edit:

Также см. ответ здесь, может быть полезно.

Ответ 2

Я бы предоставил javacv для вашей справки.

package com.test13;

import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgcodecs.Imgcodecs;

public class EdgeDetection {

    static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }

    public static void main( String[] args ) throws Exception{      
        Mat src = Imgcodecs.imread("src//data//inclined_text.jpg");
        Mat src_gray = new Mat();
        Imgproc.cvtColor(src, src_gray, Imgproc.COLOR_BGR2GRAY);
        Imgcodecs.imwrite("src//data//inclined_text_src_gray.jpg", src_gray);

        Mat output = new Mat();
        Core.bitwise_not(src_gray, output);
        Imgcodecs.imwrite("src//data//inclined_text_output.jpg", output);

        Mat points = Mat.zeros(output.size(),output.type());  
        Core.findNonZero(output, points);   

        MatOfPoint mpoints = new MatOfPoint(points);    
        MatOfPoint2f points2f = new MatOfPoint2f(mpoints.toArray());
        RotatedRect box = Imgproc.minAreaRect(points2f);

        Mat src_squares = src.clone();
        Mat rot_mat = Imgproc.getRotationMatrix2D(box.center, box.angle, 1);
        Mat rotated = new Mat(); 
        Imgproc.warpAffine(src_squares, rotated, rot_mat, src_squares.size(), Imgproc.INTER_CUBIC);
        Imgcodecs.imwrite("src//data//inclined_text_squares_rotated.jpg",rotated);    
    }
}

Ответ 3

Здесь реализация Python метода профиля проекции для определения перекоса. После получения двоичного изображения идея состоит в том, чтобы поворачивать изображение под различными углами и генерировать гистограмму пикселей в каждой итерации. Чтобы определить angular перекоса, мы сравниваем максимальную разницу между пиками и, используя этот angular перекоса, поворачиваем изображение, чтобы исправить перекос


Входной

enter image description here

Результат

enter image description here

Detected skew angle: -5

import cv2
import numpy as np
from scipy.ndimage import interpolation as inter

def correct_skew(image, delta=1, limit=5):
    def determine_score(arr, angle):
        data = inter.rotate(arr, angle, reshape=False, order=0)
        histogram = np.sum(data, axis=1)
        score = np.sum((histogram[1:] - histogram[:-1]) ** 2)
        return histogram, score

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] 

    scores = []
    angles = np.arange(-limit, limit + delta, delta)
    for angle in angles:
        histogram, score = determine_score(thresh, angle)
        scores.append(score)

    best_angle = angles[scores.index(max(scores))]

    (h, w) = image.shape[:2]
    center = (w // 2, h // 2)
    M = cv2.getRotationMatrix2D(center, best_angle, 1.0)
    rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, \
              borderMode=cv2.BORDER_REPLICATE)

    return best_angle, rotated

if __name__ == '__main__':
    image = cv2.imread('1.png')
    angle, rotated = correct_skew(image)
    print(angle)
    cv2.imshow('rotated', rotated)
    cv2.imwrite('rotated.png', rotated)
    cv2.waitKey()