Detect and correct text skew

Is there a way (using something like OpenCV) to detect skewed text and fix it by rotating the image? Is that pretty much the case?

enter image description here

enter image description here

Rotating the image seems simple enough if you know the angle, but for the images that I process, I will not ... it will need to be detected somehow.

+12
image-processing opencv
source share
3 answers

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

A 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 , may be helpful.

+10
source share

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); } } 
0
source share

Here's a Python implementation of the projection profile method for determining skew. After receiving the binary image, the idea is to rotate the image at different angles and generate a histogram of pixels in each iteration. To determine the angular skew, we compare the maximum difference between the peaks and, using this angular skew, we rotate the image to fix the skew


Input

enter image description here

Result

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() 
0
source share

All Articles