Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect and fix text skew by rotating image

Is there a way (using something like OpenCV) to detect text skew and correct it by rotating the image? Pretty much like this?

enter image description here

enter image description here

Rotating an image seems easy enough if you know the angle, but for the images I'm processing, I wont...it will need to be detected somehow.

like image 316
Sam Jarman Avatar asked Apr 25 '14 03:04

Sam Jarman


People also ask

How do you correct the skew of an image?

Given an image containing a rotated block of text at an unknown angle, we need to correct the text skew by: Detecting the block of text in the image. Computing the angle of the rotated text. Rotating the image to correct for the skew.

How to use Skew detection and deskew to remove the skew?

The skew detection script takes image file as input, then performs the following steps: The deskew script uses the skew angle determined using skew detection script to remove the skew from the image. To calculate the skew angle for a given image file, use -i option followed by the path to file:

How do I determine the skew angle of a text block?

There can be various approaches to determine skew angle, but we’ll stick to the simple one — take the largest text block and use its angle. # Apply dilate to merge text into meaningful lines/paragraphs. # Use larger kernel on X axis to merge characters into single line, cancelling out any spaces. # Determine the angle.

How do you determine the skew angle of a binary image?

After obtaining a binary image, the idea is rotate the image at various angles and generate a histogram of pixels in each iteration. To determine the skew angle, we compare the maximum difference between peaks and using this skew angle, rotate the image to correct the skew


3 Answers

I would provide javacv for your reference.

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);    
    }
}
like image 177
Anton KONG Avatar answered Oct 19 '22 20:10

Anton KONG


Based on your above comment, here is the code based on the tutorial here, working fine for the above image,

Source

enter image description here

Rotated

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:

Also see the answer here , might be helpful.

like image 10
Haris Avatar answered Oct 19 '22 21:10

Haris


Here's an implementation of the Projection Profile Method algorithm for skew angle estimation. Various angle points are projected into an accumulator array where the skew angle can be defined as the angle of projection within a search interval that maximizes alignment. The idea is to rotate the image at various angles and generate a histogram of pixels for each iteration. To determine the skew angle, we compare the maximum difference between peaks and using this skew angle, rotate the image to correct the skew.


Input

enter image description here

Result

enter image description here

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, dtype=float)
        score = np.sum((histogram[1:] - histogram[:-1]) ** 2, dtype=float)
        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)
    corrected = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, \
            borderMode=cv2.BORDER_REPLICATE)

    return best_angle, corrected

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

Note: You may have to adjust the delta or limit values depending on the image. The delta value controls iteration step, it will iterate up until the limit which controls the maximum angle. This method is straightforward by iteratively checking each angle + delta and currently only works to correct skew in the range of +/- 5 degrees. If you need to correct at a larger angle, adjust the limit value.

like image 5
nathancy Avatar answered Oct 19 '22 20:10

nathancy