#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
//旋转文本图像矫正
int main()
{
//imread中0表示灰度返回,1表示原图返回
Mat src = imread("E:\\研究生\\学习材料\\学习书籍\\OpenCV图像处理编程实例-源码-20160801\\《OpenCV图像处理编程实例-源码-20160801\\images\\text.jpg",0);
if (!src.data)
return -1;
//src = src.rowRange(0,365);
imshow("src", src);
int nRows = src.rows;
int nCols = src.cols;
cout << "src rows: " << nRows << endl;
cout << "src cols: " << nCols << endl;
//获取DFT最佳尺寸
int cRows = getOptimalDFTSize(nRows);
int cCols = getOptimalDFTSize(nCols);
cout << "DFT rows: " << cRows << endl;
cout << "DFT cols: " << cCols << endl;
//图像拷贝,超出边界的填充0
Mat sizeConvMat;
copyMakeBorder(src,sizeConvMat,0,cRows-nRows,0,cCols-nCols,BORDER_CONSTANT,Scalar::all(0));
imshow("sizeConvMat",sizeConvMat);
//通道组建立,因为傅里叶变换后是实部和虚部
Mat groupMats[] = { Mat_(sizeConvMat),Mat::zeros(sizeConvMat.size(),CV_32F) };
Mat mergeMat;
merge(groupMats,2,mergeMat);
dft(mergeMat,mergeMat);
//分离通道
split(mergeMat,groupMats);
//计算幅值
magnitude(groupMats[0],groupMats[1],groupMats[0]);
Mat magnitudeMat = groupMats[0].clone();
//归一化操作
magnitudeMat += Scalar::all(1);
log(magnitudeMat,magnitudeMat);
normalize(magnitudeMat,magnitudeMat,0,1,CV_MINMAX);
magnitudeMat.convertTo(magnitudeMat,CV_8UC1,255,0);
imshow("magnitudeMat",magnitudeMat);
//中心平移
int cx = magnitudeMat.cols / 2;
int cy = magnitudeMat.rows / 2;
Mat tmp;
//为每个象限创建ROI
//左上
Mat q0(magnitudeMat,Rect(0,0,cx,cy));
//右上
Mat q1(magnitudeMat,Rect(cx,0,cx,cy));
//左下
Mat q2(magnitudeMat,Rect(0,cy,cx,cy));
//右下
Mat q3(magnitudeMat,Rect(cx,cy,cx,cy));
//交换象限
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q0);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
imshow("magnitudeMat2",magnitudeMat);
//固定阈值二值化处理
Mat binaryMagnMat;
threshold(magnitudeMat,binaryMagnMat,132,255,CV_THRESH_BINARY);
imshow("binaryMagnMat",binaryMagnMat);
//霍夫变换
vector lines;
binaryMagnMat.convertTo(binaryMagnMat,CV_8UC1,255,0);
HoughLines(binaryMagnMat,lines,1,CV_PI/180,100,0,0);
//检测线个数
cout << "lines size" << lines.size() << endl;
Mat houghMat(binaryMagnMat.size(),CV_8UC3);
for (int i = 0; i < lines.size(); i++)
{
float rho = lines[i][0], 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(houghMat,pt1,pt2,Scalar(0,255,0),3,CV_AA);
}
imshow("houghMat",houghMat);
//判断检测线
double theta;
for (int i = 0; i < lines.size(); i++)
{
float thetaTemp = lines[i][1] * 180 / CV_PI;
if (thetaTemp > 0 && thetaTemp < 90)
{
theta = thetaTemp;
break;
}
}
//取图像中心
Point2f centerPoint = Point2f(nCols,nRows);
double scale = 1;
//计算旋转矩阵
Mat warpMat = getRotationMatrix2D(centerPoint,theta,scale);
//进行仿射变换
Mat result(src.size(),src.type());
warpAffine(src,result,warpMat,result.size());
imshow("result",result);
waitKey(0);
return(0);
}
C++: void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0, double min_theta = 0, double max_theta = CV_PI )
第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。
第二个参数,InputArray类型的lines,经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量表示,其中,是离坐标原点((0,0)(也就是图像的左上角)的距离。 是弧度线条旋转角度(0~垂直线,π/2~水平线)。
第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。PS:Latex中/rho就表示 。
第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
第八个参数,double类型的 min_theta,对于标准和多尺度Hough变换,检查线条的最小角度。必须介于0和max_theta之间。
第九个参数,double类型的 max_theta, 对于标准和多尺度Hough变换,检查线条的最大角度。必须介于min_theta和CV_PI之间.
---------------------
解释为什么加1000*(-b)