原始图像

help(argv);
CommandLineParser parser(argc, argv, keys);
if (parser.has("help"))
{
help(argv);
return 0;
}
string filename = parser.get<string>(0);
Mat img = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
if( img.empty() )
{
help(argv);
printf("Cannot read image file: %s\n", filename.c_str());
return -1;
}
imshow("source", img);自定义旋转

//旋转原图像
Point center(img.cols/2,img.rows/2);
Mat rotMatS = getRotationMatrix2D(center, DEGREE, 1.0);
warpAffine(img, img, rotMatS, img.size(), 1, 0, Scalar(255,255,255));
imshow("Rotatedimg", img);dft加速

//加速算法
//获取图像dft尺寸合适尺寸, 图像尺寸是2,3和5的倍数时处理最快
int M = getOptimalDFTSize( img.rows );
int N = getOptimalDFTSize( img.cols );
//填充图像img, 为了让原图像和扩大图像左上角对齐
Mat padded;
copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0));
//把要处理的图像作为输入实部,一个全零图像作为输入的虚部
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat complexImg;
//将plans融合成一个多通道数组complexImg
merge(planes, 2, complexImg);
//dft变换
dft(complexImg, complexImg);
// compute log(1 + sqrt(Re(DFT(img))**2 + Im(DFT(img))**2))
split(complexImg, planes);
//实部planes[0] = Re(DFT(I)), 虚部planes[1] = Im(DFT(I))
magnitude(planes[0], planes[1], planes[0]);
Mat mag = planes[0];
mag += Scalar::all(1);
//转到对数尺度
log(mag, mag);
//对奇数行或列 对频谱进行裁剪
mag = mag(Rect(0, 0, mag.cols & -2, mag.rows & -2));
//排列dft图像中的象限 使原点位于图像中心
int cx = mag.cols/2;
int cy = mag.rows/2;
Mat tmp;
Mat q0(mag, Rect(0, 0, cx, cy));//左上角图像ROI
Mat q1(mag, Rect(cx, 0, cx, cy));//右上角
Mat q2(mag, Rect(0, cy, cx, cy));//左下角
Mat q3(mag, Rect(cx, cy, cx, cy));//右下角
//变换左上角和右下角象限
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
//变换右上角和左下角象限
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
//归一化处理
normalize(mag, mag, 0, 1, NORM_MINMAX);
imshow("spectrum magnitude", mag);
Mat magImg(mag.size(), CV_8UC1);
mag.convertTo(magImg,CV_8UC1,255,0);
imshow("magnitude", magImg);二值化处理

//二值处理
threshold(mag,mag,GRAY_THRESH,255,CV_THRESH_BINARY);
imshow("mag_binary", mag);直线检测

//Hough Transformation 到线
vector<Vec2f> lines;
float pi180 = (float)CV_PI/180;
Mat linImg(mag.size(),CV_8UC3);
//二值化处理得到的img很重要 必须有黑白差异Hh才可找到直线否则crash
HoughLines(mag,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);
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;
}矫正图像

//三条线的夹角
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;
}
}
//对输入图像是正方形计算旋转角度
angel = angel<pi2 ? angel : angel-CV_PI;
if(angel != pi2){
float angelT = img.rows*tan(angel)/img.cols;
angel = atan(angelT);
}
float angelD = angel*180/(float)CV_PI;
cout << "the rotation angel to be applied:" << endl << angelD << endl << endl;
//旋转图像到正确位置
Mat rotMat = getRotationMatrix2D(center,angelD,1.0);
Mat dstImg = Mat::ones(img.size(),CV_8UC3);
warpAffine(img,dstImg,rotMat,img.size(),1,0,Scalar(255,255,255));
imshow("result",dstImg);
waitKey(0);