I'm just learning to use OpenCV and am having a problem with using DFT. I've d开发者_StackOverflow社区one a signal processing class which used MatLab, so I'm trying to go through some of the exercises we did in that class. I'm trying to get and display the FT of an image, so I can mask some of the frequencies. I'd like to be able to see the FT, so I know how big to make the mask, but when I tried, I got an image like this:
rather than like one of these alt text http://www.ceremade.dauphine.fr/~peyre/numerical-tour/tours/graphics_synthesis_fourier/index_03.png Am I forgetting a step somewhere? I'm loading the image, converting its type to CV_32FC1, getting the matrix of it, getting the DFT, and then getting turning the resulting matrix back into an image. I'll post the code I'm using if it will be of any help? Or if someone has a link to an example of displaying the FT? I could only find ones which used it for the convolution.EDIT: Did I get the Phase of the image?
I have run into similar trouble in trying to visualize the magnitude of a 2D DFT on an image with respect to OpenCV. I finally churned out a working implementation. I wouldn't consider it great code, and it has only been tested on a 256 x 256 8-bit (gray-scale) single-channel image--lenna.png (it may need to be tweaked to appropriately pad for other image dimensions). The mean-squared error between the input image and the reconstructed image is zero, so it is working as it should. OpenCV v2.1 is required.
file: mstrInclude.h
#ifndef _MASTER_INCLUDE_
#define _MASTER_INCLUDE_
// Standard
#include <stdio.h>
#include <string>
#include <sstream>
#include <iostream>
#include <cmath>
using namespace std;
// OpenCV2.1
#include "cv.h"
#include "highgui.h"
using namespace cv;
#define LOAD_IMAGE "lenna.png"
#endif // _MASTER_INCLUDE_
file: main.cpp
#include "mstrInclude.h"
void translateImg(Mat& imgIn, Mat& imgOut)
{
int i, j;
for (i = 0; i < imgIn.rows; i++)
for (j = 0; j < imgIn.cols; j++)
imgOut.at<double>(i,j) = imgIn.at<double>(i,j) * pow(-1.0, i+j);
}
void scaleImg(Mat& imgIn, Mat& imgOut, float scaleFactor)
{
int i, j;
for (i = 0; i < imgIn.rows; i++)
for (j = 0; j < imgIn.cols; j++)
imgOut.at<double>(i,j) = (double)scaleFactor * log(1.0 + imgIn.at<double>(i,j));
}
void consoleOut(cv::Mat outMat, int rows = 5, int cols = 5)
{
rows = ((rows == -1 || rows >= outMat.rows) ? outMat.rows : rows);
cols = ((cols == -1 || cols >= outMat.cols) ? outMat.cols : cols);
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
cout << outMat.at<double>(i, j);
cout << " ";
}
cout << endl;
}
}
double calcMSE(Mat& imgOrig, Mat& imgReconst)
{
int valOrig = 0, valReconst = 0;
double MSE = 0.0;
for(int i = 0; i < imgOrig.rows; i++)
{
for (int j = 0; j < imgOrig.cols; j++)
{
valOrig = imgOrig.at<unsigned char>(i, j);
valReconst = imgReconst.at<unsigned char>(i, j);
MSE += pow( (double)(valOrig - valReconst), 2.0 );
}
}
return (MSE / (imgOrig.rows * imgOrig.cols));
}
string convertInt(int number) // converts integer to string
{
stringstream ss;
ss << number;
return ss.str();
}
int main(unsigned int argc, char* const argv[])
{
int dftH, dftW;
cv::Mat imgIn;
imgIn = cv::imread(LOAD_IMAGE, 0); //grayscale
cv::imshow("Original Image", imgIn);
waitKey();
dftH = cv::getOptimalDFTSize(imgIn.rows);
dftW = cv::getOptimalDFTSize(imgIn.cols);
Mat imgMod;
Mat imgPrecFFT(dftH, dftW, CV_64FC1, Scalar::all(0));
imgIn.convertTo(imgMod, CV_64FC1);
imgPrecFFT = imgMod(cv::Range::all(), cv::Range::all()).clone();
// translate image
std::vector<Mat> imgsTrans;
imgsTrans.push_back(Mat_<double>(imgIn.size(), CV_64FC1));
imgsTrans.push_back(Mat_<double>(imgIn.size(), CV_64FC1));
imgsTrans[1].setTo(Scalar::all(0), Mat());
translateImg(imgPrecFFT, imgsTrans[0]);
Mat imgPrecTransFFT(imgIn.size(), CV_64FC2, Scalar::all(0));
cv::merge(imgsTrans, imgPrecTransFFT);
// dft
cv::Mat imgFFT;
dft(imgPrecTransFFT, imgFFT, DFT_COMPLEX_OUTPUT);
cv::Mat imgDispFFT;
// calculate magnitude
Mat imgMagnitude(imgIn.size(), CV_64FC1);
std::vector<Mat> chans;
cv::split(imgFFT, chans);
cv::magnitude(chans[0], chans[1], imgMagnitude);
// scale magnitude image
Mat imgMagnitudeScaled(imgIn.size(), CV_64FC1);
scaleImg(imgMagnitude, imgMagnitudeScaled, 10.0);
// display magnitude image
cv::Mat imgDisp;
cv::convertScaleAbs(imgMagnitudeScaled, imgDisp);
imshow("Magnitude Output", imgDisp);
waitKey();
// inverse dft
cv::split(imgFFT, chans);
chans[1].zeros(imgIn.size(), CV_64FC1);
cv::merge(chans, imgFFT);
cv::Mat invFFT;
cv::idft(imgFFT, invFFT, DFT_REAL_OUTPUT + DFT_SCALE);
// translate image back to original location
cv::split(invFFT, imgsTrans);
Mat imgAfterTrans(imgIn.size(), CV_64FC1);
translateImg(imgsTrans[0], imgAfterTrans);
imgAfterTrans.convertTo(imgDisp, CV_8UC1);
imshow("After Inverse Output", imgDisp);
waitKey();
// calculate and output mean-squared error between input/output images
double MSE = calcMSE(imgIn, imgDisp);
cout<<endl<<"MSE: "<<MSE<<endl;
waitKey();
return 0;
}
精彩评论