首先,在写这篇博文之前,先感谢一下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]);
}
其实通过读官方文档,你会发现其实很简单!