天天看點

OpenCV--基于直線檢測的文本圖像傾斜校正

圖像傾斜矯正的方式有很多種,今天簡單介紹一種基于直線檢查的傾斜校正。

這種方法暫時在如下圖的文本檔案上測試過,不一定能針對所有:

OpenCV--基于直線檢測的文本圖像傾斜校正

首先,因為這種圖像基本是比較常見的白底黑字,是以首先對這幅圖做一個灰階化,灰階化之後做一個二值化,得到二值圖像:

OpenCV--基于直線檢測的文本圖像傾斜校正

二值化之後,将X軸方向的的像素點連起來,這裡我采用的是形态學的膨脹,因為我做二值化的時候采用了取反的操作,這裡可以考慮不取反,但是要用腐蝕來做,這裡有個技巧,因為是要對X軸來做連接配接,是以可以在構造形态學核上将Y軸設定為1:

OpenCV--基于直線檢測的文本圖像傾斜校正

做了連接配接後可以使用canny邊緣檢測做一遍邊緣檢測,然後再做霍夫變化:

OpenCV--基于直線檢測的文本圖像傾斜校正

從上圖可以看出來基本上畫出來的直線方向跟文字的走向的一緻的,然後根據霍夫變換得到的角度來求平均值,這個平均值就是圖像要旋轉的角度。

OpenCV--基于直線檢測的文本圖像傾斜校正

上代碼:

#include <opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

void GetContoursPic(const char* pSrcFileName)
{
	Mat srcImg = imread(pSrcFileName);
	imshow("原始圖", srcImg);
	Mat gray, binImg;
	//灰階化
	cvtColor(srcImg, gray, COLOR_RGB2GRAY);
	imshow("灰階圖", gray);
	//二值化
	threshold(gray, binImg, 50, 255, CV_THRESH_BINARY_INV );
	imshow("二值化", binImg);

	Mat morphologyDst;
	cv::morphologyEx(binImg, morphologyDst, cv::MORPH_DILATE, 
	    cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 1)));
	imshow("膨脹", morphologyDst);

	Mat cannyDst;
	Canny(morphologyDst, cannyDst, 150, 200);
	imshow("Canny", cannyDst);

	vector<Vec2f> lines;
	HoughLines(cannyDst, lines, 1, CV_PI / 180, 130, 0, 0);
	Mat houghDst;
	srcImg.copyTo(houghDst);
	double meanAngle = 0.0;
	int numCnt = 0;
	for (size_t i = 0; i < lines.size(); i++)
	{
		float rho = lines[i][0]; //就是圓的半徑r
		float theta = lines[i][1]; //就是直線的角度
		Point pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a*rho, y0 = b*rho;
		pt1.x = cvRound(x0 + 1000 * (-b));
		pt1.y = cvRound(y0 + 1000 * (a));
		pt2.x = cvRound(x0 - 1000 * (-b));
		pt2.y = cvRound(y0 - 1000 * (a));

		line(houghDst, pt1, pt2, Scalar(55, 100, 195), 1);
		
		theta = theta * 180 / CV_PI - 90;
		//if (theta > -45 && theta < 45)
		{
			meanAngle += theta;
			numCnt++;
		}
	}
	meanAngle /= numCnt;
	imshow("霍夫變換", houghDst);
	cv::Point2f center(srcImg.cols / 2., srcImg.rows / 2.);
	//擷取旋轉矩陣(2x3矩陣)
	cv::Mat rot_mat = cv::getRotationMatrix2D(center, meanAngle, 1.0);
	cv::Size dst_sz(srcImg.cols, srcImg.rows);
	Mat warpDst;
	cv::warpAffine(srcImg, warpDst, rot_mat, dst_sz);
	imshow("旋轉矯正", warpDst);

	cv::waitKey(0);
}
           

結果如下:

OpenCV--基于直線檢測的文本圖像傾斜校正

這個方法有幾個重要的影響點:

1、二值化:二值化的門檻值選得不好的話結果是不能将前景和背景分離,我試過用OTSU,出來的二值化不是很好,然後檢測直線的時候就有一點不太準确,但是基本上也能檢測出來:

OpenCV--基于直線檢測的文本圖像傾斜校正
OpenCV--基于直線檢測的文本圖像傾斜校正

2、如果是白底黑字,就用腐蝕,反之有膨脹來做;

3、邊緣檢測也很重要,可想而知,不做邊緣檢測再來做霍夫變換,那得有多少條直線,直接備援不說,還非常容易幹擾檢測。

4、另外,對于一些高度大于寬度的圖像,其實可以采用分段檢測求平均,以保證每一段的高度小于寬度,因為我的檢測主要以X軸為主。

路漫漫其修遠兮

吾将上下而求索