opencv实现旋转文本矫正

#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);
}

opencv实现旋转文本矫正_第1张图片

opencv实现旋转文本矫正_第2张图片

opencv实现旋转文本矫正_第3张图片

opencv实现旋转文本矫正_第4张图片

opencv实现旋转文本矫正_第5张图片

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之间.
--------------------- 

opencv实现旋转文本矫正_第6张图片

解释为什么加1000*(-b)

你可能感兴趣的:(opencv学习)