0031-在OpenCV環境下做旋轉文字影象的矯正!
阿新 • • 發佈:2018-11-16
直接上程式碼和執行結果截圖,具體的原理大家可以訪問下面的連結檢視!
連結:http://johnhany.net/2013/11/dft-based-text-rotation-correction/
如果上面的連結訪問不了,可以下載我離線儲存的網頁檔案檢視,下載連結如下:
連結:http://pan.baidu.com/s/1gfxnfCR 密碼:94pf程式碼如下:
程式碼中用到的影象下載連結:http://pan.baidu.com/s/1dFcYzMp 密碼:tfae
影象處理開發資料、影象處理開發需求、影象處理接私活掙零花錢,可以搜尋公眾號"qxsf321",並關注!
//opencv版本:OpenCV3.0 //VS版本:VS2013 //Author:qxsf321.net #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/imgproc/types_c.h> #include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui_c.h> #include <iostream> using namespace cv; using namespace std; #define GRAY_THRESH 150 #define HOUGH_VOTE 100 //#define DEGREE 27 int main(int argc, char **argv) { //Read a single-channel image const char* filename = "12_1.jpg"; Mat srcImg = imread(filename, CV_LOAD_IMAGE_GRAYSCALE); if (srcImg.empty()) return -1; imshow("source", srcImg); Point center(srcImg.cols / 2, srcImg.rows / 2); #ifdef DEGREE //Rotate source image Mat rotMatS = getRotationMatrix2D(center, DEGREE, 1.0); warpAffine(srcImg, srcImg, rotMatS, srcImg.size(), 1, 0, Scalar(255, 255, 255)); imshow("RotatedSrc", srcImg); //imwrite("imageText_R.jpg",srcImg); #endif //Expand image to an optimal size, for faster processing speed //Set widths of borders in four directions //If borderType==BORDER_CONSTANT, fill the borders with (0,0,0) Mat padded; int opWidth = getOptimalDFTSize(srcImg.rows); int opHeight = getOptimalDFTSize(srcImg.cols); copyMakeBorder(srcImg, padded, 0, opWidth - srcImg.rows, 0, opHeight - srcImg.cols, BORDER_CONSTANT, Scalar::all(0)); Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) }; Mat comImg; //Merge into a double-channel image merge(planes, 2, comImg); //Use the same image as input and output, //so that the results can fit in Mat well dft(comImg, comImg); //Compute the magnitude //planes[0]=Re(DFT(I)), planes[1]=Im(DFT(I)) //magnitude=sqrt(Re^2+Im^2) split(comImg, planes); magnitude(planes[0], planes[1], planes[0]); //Switch to logarithmic scale, for better visual results //M2=log(1+M1) Mat magMat = planes[0]; magMat += Scalar::all(1); log(magMat, magMat); //Crop the spectrum //Width and height of magMat should be even, so that they can be divided by 2 //-2 is 11111110 in binary system, operator & make sure width and height are always even magMat = magMat(Rect(0, 0, magMat.cols & -2, magMat.rows & -2)); //Rearrange the quadrants of Fourier image, //so that the origin is at the center of image, //and move the high frequency to the corners int cx = magMat.cols / 2; int cy = magMat.rows / 2; Mat q0(magMat, Rect(0, 0, cx, cy)); Mat q1(magMat, Rect(0, cy, cx, cy)); Mat q2(magMat, Rect(cx, cy, cx, cy)); Mat q3(magMat, Rect(cx, 0, cx, cy)); Mat tmp; q0.copyTo(tmp); q2.copyTo(q0); tmp.copyTo(q2); q1.copyTo(tmp); q3.copyTo(q1); tmp.copyTo(q3); //Normalize the magnitude to [0,1], then to[0,255] normalize(magMat, magMat, 0, 1, CV_MINMAX); Mat magImg(magMat.size(), CV_8UC1); magMat.convertTo(magImg, CV_8UC1, 255, 0); imshow("magnitude", magImg); //imwrite("imageText_mag.jpg",magImg); //Turn into binary image threshold(magImg, magImg, GRAY_THRESH, 255, CV_THRESH_BINARY); imshow("mag_binary", magImg); //imwrite("imageText_bin.jpg",magImg); //Find lines with Hough Transformation vector<Vec2f> lines; float pi180 = (float)CV_PI / 180; Mat linImg(magImg.size(), CV_8UC3); HoughLines(magImg, lines, 1, pi180, HOUGH_VOTE, 0, 0); int numLines = lines.size(); for (int l = 0; l<numLines; l++) { float rho = lines[l][0], theta = lines[l][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(linImg, pt1, pt2, Scalar(255, 0, 0), 3, 8, 0); } imshow("lines", linImg); //imwrite("imageText_line.jpg",linImg); if (lines.size() == 3){ cout << "found three angels:" << endl; cout << lines[0][1] * 180 / CV_PI << endl << lines[1][1] * 180 / CV_PI << endl << lines[2][1] * 180 / CV_PI << endl << endl; } //Find the proper angel from the three found angels float angel = 0; float piThresh = (float)CV_PI / 90; float pi2 = CV_PI / 2; for (int l = 0; l<numLines; l++) { float theta = lines[l][1]; if (abs(theta) < piThresh || abs(theta - pi2) < piThresh) continue; else{ angel = theta; break; } } //Calculate the rotation angel //The image has to be square, //so that the rotation angel can be calculate right angel = angel<pi2 ? angel : angel - CV_PI; if (angel != pi2){ float angelT = srcImg.rows*tan(angel) / srcImg.cols; angel = atan(angelT); } float angelD = angel * 180 / (float)CV_PI; cout << "the rotation angel to be applied:" << endl << angelD << endl << endl; //Rotate the image to recover Mat rotMat = getRotationMatrix2D(center, angelD, 1.0); Mat dstImg = Mat::ones(srcImg.size(), CV_8UC3); warpAffine(srcImg, dstImg, rotMat, srcImg.size(), 1, 0, Scalar(255, 255, 255)); imshow("result", dstImg); //imwrite("imageText_D.jpg",dstImg); waitKey(0); return 0; }
執行結果截圖如下: