【OpenCV】基于傅立叶变换和霍夫变化的文本倾斜校正

// 此函数应用傅立叶变换进行原始图像倾斜校正
// Windows平台VS编译器
IplImage* mycvRotateImage(const IplImage* src) 
{
    int op_width = cvGetOptimalDFTSize(src->width);  //获取傅立叶变换的最佳尺寸
    int op_height = cvGetOptimalDFTSize(src->height);

    IplImage* borderImg = cvCreateImage(cvSize(op_width, op_height), IPL_DEPTH_8U, 1);  
    cvCopyMakeBorder(src, borderImg, cvPoint(0,0), IPL_BORDER_CONSTANT, cvScalarAll(0));  //边界扩充

    IplImage* image_real = cvCreateImage(cvGetSize(borderImg), IPL_DEPTH_32F, 1);  
    IplImage* image_imaginary = cvCreateImage(cvGetSize(borderImg), IPL_DEPTH_32F, 1);  
    IplImage* fourier = cvCreateImage(cvGetSize(borderImg), IPL_DEPTH_32F, 2);  

    cvConvertScale(borderImg, image_real, 1, 0);  //从原图像拷贝数据作为实部
    cvZero(image_imaginary);  //全0图像作为虚部

    cvMerge(image_real, image_imaginary, 0, 0, fourier);  //将实部虚部合并成双通道
    cvDFT(fourier, fourier, CV_DXT_FORWARD);  //傅里叶变换
    cvSplit(fourier, image_real, image_imaginary, 0, 0);  //将变换后的图像再分解

    cvPow(image_real, image_real, 2.0);  //计算sqrt(real^2+imaginary^2),再存回real 
    cvPow(image_imaginary, image_imaginary, 2.0);
    cvAdd(image_real, image_imaginary, image_real);
    cvPow(image_real, image_real, 0.5);

    cvAddS(image_real, cvScalar(1.0), image_real);  //计算log(1+real),再存回real  
    cvLog(image_real, image_real);

    Mat mat = image_real; 
    mat = mat(Rect(0, 0, mat.cols & -2, mat.rows & -2));

    //把低频移动到中心
    int cx = mat.cols/2;
    int cy = mat.rows/2;

    Mat q0(mat, Rect(0, 0, cx, cy));
    Mat q1(mat, Rect(0, cy, cx, cy));
    Mat q2(mat, Rect(cx, cy, cx, cy));
    Mat q3(mat, 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(mat, mat, 0, 1, CV_MINMAX);
    Mat magImg(mat.size(), CV_8UC1);
    mat.convertTo(magImg,CV_8UC1,255,0);

    IplImage* new_real;  //矩阵头换成图像头
    new_real = &IplImage(magImg);

    cvThreshold(new_real, new_real, 150, 255, CV_THRESH_BINARY);

    IplImage* grayImg = cvCreateImage(cvGetSize(new_real), IPL_DEPTH_8U, 1); //转换成cvHoughLines2函数参数形式
    cvConvertScale(new_real, grayImg);

    CvMemStorage *storage = cvCreateMemStorage(); 
    CvSeq *lines = 0;  
    lines = cvHoughLines2(grayImg, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 100);

    //找到符合条件的那条斜线
    float angel = 0;
    float piThresh = (float)CV_PI/90;
    float pi2 = (float)CV_PI / 2;
    for (int i = 0; i<lines->total; i++)
    {
        float *line = (float*)cvGetSeqElem(lines,i); 
        float rho = line[0];
        float theta = line[1];

        if (abs(theta) >= piThresh && abs(theta-pi2) >= piThresh)
        {
            angel = theta;
            break;
        }
    }
    angel = angel<pi2 ? angel : (angel-CV_PI);

    if (angel != pi2)
    {
        float angelT = (src->height) * tan(angel) / (src->width);
        angel = atan(angelT);
    }
    float angelD = angel*180/(float)CV_PI;
    cout << "The rotation angel to be applied is : " << angelD << endl;

    CvMat* rot_mat = cvCreateMat(2, 3, CV_32FC1);
    CvPoint2D32f center = cvPoint2D32f((src->width)/2, (src->height)/2);
    cv2DRotationMatrix(center, angelD, 1.0, rot_mat);
    IplImage* dst = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
    cvWarpAffine(src, dst, rot_mat, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll(255));

    cvNamedWindow("rotateImage", CV_WINDOW_AUTOSIZE);
    cvShowImage("rotateImage", dst);

    cvReleaseMemStorage(&storage);

    cvReleaseImage(&image_real);  
    cvReleaseImage(&image_imaginary);   
    cvReleaseImage(&fourier);  
    cvReleaseImage(&borderImg);  

    return dst;
 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值