OpenCV实现基于傅里叶变换(FFT)的旋转文本校正(文字方向检测)

Posted 凌风探梅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV实现基于傅里叶变换(FFT)的旋转文本校正(文字方向检测)相关的知识,希望对你有一定的参考价值。

OpenCV实现基于傅里叶变换的旋转文本校正

from: http://johnhany.net/2013/11/dft-based-text-rotation-correction/

发布于 2013年11月25日 11,222次阅读

代码

        先给出代码,再详细解释一下过程:


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 #include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #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 = "imageText.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

以上是关于OpenCV实现基于傅里叶变换(FFT)的旋转文本校正(文字方向检测)的主要内容,如果未能解决你的问题,请参考以下文章

纯干货:FFT快速傅里叶变换的Python语言实现(源代码)

FPGA教程案例37通信案例7——基于FPGA的FFT,IFFT傅里叶变换和逆变换

快速傅里叶变换(FFT)详解

快速傅里叶变换fft

傅里叶变换(FFT)的多相滤波结构实现

Lua的快速傅里叶变换FFT?

(c)2006-2024 SYSTEM All Rights Reserved IT常识