您的位置:首页 > 运维架构

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

2016-07-27 11:18 423 查看
首先,在写这篇博文之前,先感谢一下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]);

}


其实通过读官方文档,你会发现其实很简单!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opencv qt