用opencv求图像的快速傅里叶变换和反变换

首先,在写这篇博文之前,先感谢一下http://www.cnblogs.com/TonyHome/p/4010116.html这篇文章的作者!
接下来贴一下自己结合qt写的测试代码;

DFTWidget::DFTWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DFTWidget)
{
    ui->setupUi(this);
    connect(ui->open,SIGNAL(clicked(bool)),this,SLOT(openimageSLOT()));
    connect(ui->DFT,SIGNAL(clicked(bool)),this,SLOT(convertDFTSlot()));
    connect(ui->DFTshift,SIGNAL(clicked(bool)),this,SLOT(convertDFTshiftSlot()));
    connect(ui->DFT_INV,SIGNAL(clicked(bool)),this,SLOT(convertDFTinvSlot()));
}

DFTWidget::~DFTWidget()
{
    delete ui;
}

void DFTWidget::openimageSLOT()
{
    QString imageName = QFileDialog::getOpenFileName(this,tr("打开图片"),".",tr("Image Files(*.png *.jpg *.bmp *.jpeg)"));
    //src = cv::imread(imageName.toLatin1().data(),CV_LOAD_IMAGE_GRAYSCALE);
    std::string filename = imageName.toStdString();
    src = cv::imread(filename,CV_LOAD_IMAGE_GRAYSCALE);
    if(src.empty())
    {
        QMessageBox::information(this,"注意","图像加载失败",QMessageBox::Ok);
    }
    QImage image(imageName);
    ui->label->setPixmap(QPixmap::fromImage(image.scaled(320,240)));
}

void DFTWidget::convertDFTSlot()
{
    ui->label->clear();
    cv::Mat padded;
    int opw = cv::getOptimalDFTSize(src.cols);//找寻合适尺寸,最好是2,3,5的倍数
    int oph = cv::getOptimalDFTSize(src.rows);
    QString num1;
    QString num2;

    ui->opW->setText(num1.setNum(opw));
    ui->opH->setText(num2.setNum(oph));
    //copymakeborder是用来填充多余的尺寸
    cv::copyMakeBorder(src,padded,0,oph-src.rows,0,opw-src.cols,cv::BORDER_CONSTANT,cv::Scalar::all(0));

    cv::Mat planes[] = {cv::Mat_<float>(padded),cv::Mat::zeros(padded.size(),CV_32F)};
    //cv::Mat complexI;
    cv::merge(planes,2,complexI);

    cv::dft(complexI,complexI);

    cv::split(complexI,planes);
//    cv::imshow("plane_real",planes[0]);
//    cv::imshow("plane_inscriber",planes[1]);
    cv::magnitude(planes[0],planes[1],planes[0]);//计算梯度幅值
    cv::Mat log_img = planes[0];
    log_img +=cv::Scalar::all(1);
    cv::log(log_img,log_img);//一般幅值过大,而正常图像的显示在0~255之间,所以用log函数缩小幅值
    log_img = log_img(cv::Rect(0,0,log_img.cols & -2,log_img.rows & -2));

    dst = log_img.clone();
    //cv::normalize(dst,dst,0,1,CV_MINMAX);
    //运用log之后也不能保证数值一定在显示范围内,所以用normalize函数进一步缩小范围
    cv::normalize(dst,dst,0,1,CV_MINMAX);
    //dst.convertTo(dst,CV_8UC1,255,0);//第一个参数是输出图像,第二个参数是转换类型,第三个参数是尺度因子,第四个参数是偏移量
    //cv::imshow("dst",dst);
    dst = dst * 255;
    cv::imwrite("dst.jpg",dst);
    //cv::imshow("dst",dst);
    //qDebug() << dst.rows <<dst.cols;
    //dst = 255.0 * dst;

//    for(int i = 0;i<512;i++)
//    {
//        uchar* pdata = dst.ptr<uchar>(i);
//        for(int j = 0;j<512;j++)
//        {
//            pdata[j] = pdata[j] * 255.;
//        }
//    }
   // imshow("dft",dst);
//    QImage image = QImage(dst.cols,dst.rows,QImage::Format_ARGB32);
//    for(int i=0;i<image.width();i++)
//    {
//        for(int j=0;j<image.height();j++)
//        {
//            int pixel = dst.at<uchar>(j,i);
//            image.setPixel(i,j,qRgb(pixel,pixel,pixel));
//        }
//    }
    QImage image("dst.jpg");

    ui->label->setPixmap(QPixmap::fromImage(image.scaled(320,240)));

}

void DFTWidget::convertDFTshiftSlot()
{
    cv::Mat dst_2;
    dst.copyTo(dst_2);
    int cx = dst.cols/2;
    int cy = dst.rows/2;

    cv::Mat q0 = cv::Mat(dst_2,cv::Rect(0,0,cx,cy));
    cv::Mat q1 = cv::Mat(dst_2,cv::Rect(cx,0,cx,cy));
    cv::Mat q2 = cv::Mat(dst_2,cv::Rect(0,cy,cx,cy));
    cv::Mat q3 = cv::Mat(dst_2,cv::Rect(cx,cy,cx,cy));

    cv::Mat temp;
    q0.copyTo(temp);
    q3.copyTo(q0);
    temp.copyTo(q3);

    q1.copyTo(temp);
    q2.copyTo(q1);
    temp.copyTo(q2);

   // cv::imshow("dst_2",dst_2);
    cv::imwrite("dst_2.jpg",dst_2);
//    QImage image(dst_2.cols,dst_2.rows,QImage::Format_Indexed8);
//    image.setColorCount(256);
//    for(int i=0;i < 256;i++)
//    {
//        image.setColor(i,qRgb(i,i,i));
//    }
//    uchar *pSrc = dst_2.data;
//    for(int row = 0; row < dst_2.rows; row ++)
//    {
//        uchar *pDest = image.scanLine(row);
//        memcpy(pDest, pSrc, dst_2.cols);
//        pSrc += dst_2.step;
//    }
    QImage image("dst_2.jpg");
    ui->label->clear();

    ui->label->setPixmap(QPixmap::fromImage(image.scaled(320,240)));

}

void DFTWidget::convertDFTinvSlot()
{
    cv::Mat gaussianBlur(src.size(),CV_32FC2);
    cv::Mat BTWSD(src.size(),CV_32FC2);
    float D0 = 3.0e+4 ;
    QString num1 = ui->opH->text();
    QString num2 = ui->opW->text();
    int oph = num1.toInt();
    int opw = num2.toInt();
    cv::Mat origin[2];
    cv::split(complexI,origin);
    QVector<float> v;
    for(int i=0;i<oph;i++)
    {
        float *p = gaussianBlur.ptr<float>(i);
        float *q = BTWSD.ptr<float>(i);
        for(int j=0;j<opw;j++)
        {
            float d = pow(i - oph/2,2) + pow(j-opw/2,2);
            //float D = sqrt(pow(i,2)+pow(j,2));
            float x = origin[0].at<float>(i,j);
            float y = origin[1].at<float>(i,j);

            float D =sqrt(x*x+y*y);
            v.push_back(D);
            p[2*j] = expf(-d/D0);
            p[2*j+1] = expf(-d/D0);

            q[2*j] = 1 / (1 + pow(D/D0,2));
            q[2*j+1] = 1 / (1 + pow(D/D0,2));
        }
    }
    float max = v[0];
    for(int i=1;i<v.size();i++)
    {
        if(v[i] > max)
            max = v[i];
    }
    qDebug() << max ;
    //cv::multiply(complexI,gaussianBlur,gaussianBlur);
    cv::multiply(complexI,BTWSD,BTWSD);

    //cv::dft(gaussianBlur,gaussianBlur,CV_DXT_INVERSE);
    cv::dft(BTWSD,BTWSD,CV_DXT_INVERSE);//逆变换
    //cv::dft(complexI,complexI,CV_DXT_INVERSE);

   // cv::Mat dstBlur[2];
    cv::Mat btwsd[2];
//    cv::split(gaussianBlur,dstBlur);
    cv::split(BTWSD,btwsd);

//    cv::normalize(dstBlur[0],dstBlur[0],0,1,CV_MINMAX);
    //cv::normalize(origin[0],origin[0],0,1,CV_MINMAX);
    cv::normalize(btwsd[0],btwsd[0],0,1,CV_MINMAX);
    btwsd[0].convertTo(btwsd[0],CV_8UC1,255,0);
    cv::imwrite("btws.jpg",btwsd[0]);
    //QImage image = QImage((const uchar*)btwsd[0].data,btwsd[0].cols,btwsd[0].rows,btwsd[0].step,QImage::Format_Indexed8);
    QImage image("btws.jpg");
    ui->label->clear();
    ui->label->setPixmap(QPixmap::fromImage(image.scaled(320,240)));
    //cv::imshow("origin",origin[0]);
//    cv::imshow("dstblur",dstBlur[0]);
//    cv::imshow("btwsd",btwsd[0]);

}

其实通过读官方文档,你会发现其实很简单!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值