OpenCV实现基于傅里叶变换(FFT)的旋转文本校正(文字方向检测)
Posted 凌风探梅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV实现基于傅里叶变换(FFT)的旋转文本校正(文字方向检测)相关的知识,希望对你有一定的参考价值。
OpenCV实现基于傅里叶变换的旋转文本校正
from: http://johnhany.net/2013/11/dft-based-text-rotation-correction/
代码
先给出代码,再详细解释一下过程:
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语言实现(源代码) |