Related
Im struggling with the shape detection using OpenCV for C++. The edged figures such as triangle and rectangular are detected trouble-free. But when it comes to circle it estimates number of vertices up to 6-8. Could somebody help me?
void getContours(Mat video){
Mat grayscale, canny_output;
cvtColor(video, grayscale,COLOR_RGB2GRAY);//converting image to grayscale
GaussianBlur(grayscale, grayscale, Size(9, 9), 2, 2 );
threshold(grayscale, grayscale,60,255,THRESH_BINARY);
vector <vector<Point>> contours, output_contour;
vector <Vec4i> hierarchy;
findContours( grayscale, contours, hierarchy, RETR_TREE,CHAIN_APPROX_SIMPLE );
Mat drawing = Mat::zeros( grayscale.size(), CV_8UC3 );
vector<Point> c;
for (size_t i = 0; i<contours.size(); i++){
c = contours[i];
Rect crect = boundingRect(c);
// compute the center of the contour, then detect the name of the
// shape using only the contour
Moments M = moments(c);
int cX, cY;
cX = static_cast<int>(M.m10/M.m00);
cY = static_cast<int>(M.m01/M.m00);
string shape = detect(Mat(c));
drawContours( drawing, contours, (int)i, Scalar(0, 255, 0), 2);
Point pt(cX,cY);
putText(drawing,shape,pt, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255), 2);
imshow("contour", drawing);
}
}
string detect(const Mat &curve){
string shape = "unidentified";
double peri = arcLength(curve, true);
Mat approx;
approxPolyDP(curve, approx, 0.04 * peri, true); // 0.01~0.05
const int num_of_vertices = approx.rows;
if(num_of_vertices == 0){
shape = "circle";
}
if(num_of_vertices==2){
shape = "line";
}
cout<<"\n"<<num_of_vertices;
return to_string(num_of_vertices);
}
How to make my video not delay, in the beginning of the code it's not delay, but if I use the GaussianBlur, morphology operation, and SimpleBlobDetector, the video gets delayed, please someone help me..
Thanks in advance
using namespace cv;
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
VideoCapture cap(0);
cap.open("file.mp4"); //read the video
if (!cap.isOpened())
{
cout << "Cannot open the video cam" << endl;
return -1;
}
double Width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
double Height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
cvNamedWindow("MyVideo", CV_WINDOW_AUTOSIZE);
while (1)
{
Mat frame;
bool bSuccess = cap.read(frame);
SimpleBlobDetector::Params params;
// Change thresholds
params.minThreshold = 0;
params.maxThreshold = 255;
params.filterByColor = true;
params.blobColor = 255;
// Filter by Area.
params.filterByArea = true;
params.minArea = 5 ;
// Filter by Circularity
params.filterByCircularity = true;
params.minCircularity = 0.1;
// Filter by Convexity
params.filterByConvexity = true;
params.minConvexity = 0.87;
// Filter by Inertia
params.filterByInertia = true;
params.minInertiaRatio = 0.01;
//crop the image with the pixel i want
Mat blur, crop;
GaussianBlur(frame, blur, Size(15, 15), 0); //blur the image
Point corners[1][4];
corners[0][0] = Point(550, 30); //top left
corners[0][1] = Point(250, 700); //bottom left
corners[0][2] = Point(1100, 700); //bottom right
corners[0][3] = Point(600, 30); //top right
const Point* corner_list[1] = { corners[0] };
int num_points = 4;
int num_polygons = 1;
int line_type = 8;
Mat mask(720, 1280, CV_8UC3, cv::Scalar(0, 0, 0));
fillPoly(mask, corner_list, &num_points, num_polygons, cv::Scalar(255, 255, 255), line_type);
bitwise_and(blur, mask, crop);//combine the image
Mat gray, changeToBlack;
cvtColor(crop, gray, COLOR_BGR2GRAY); //grayscale citra
inRange(gray, Scalar(0), Scalar(0), changeToBlack);
Mat black_image(gray.size(), CV_8U, Scalar(255));
black_image.copyTo(gray, changeToBlack);
Mat thres, tes;
threshold(gray, tes, 51, 255, THRESH_BINARY_INV); //threshold citra and 51 set value
Mat erosi, dilasi, open, close, tophat;
Mat kernel = Mat(3, 3, CV_8UC1, Scalar(1));
morphologyEx(tes, erosi, MORPH_ERODE, kernel, Point(-1, -1), 3);
morphologyEx(erosi, dilasi, MORPH_DILATE, kernel, Point(-1, -1), 20);
vector<KeyPoint> keypoints;
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
detector->detect(dilasi, keypoints);
Mat im_with_keypoints;
drawKeypoints(dilasi, keypoints, im_with_keypoints, Scalar(205, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imshow("gray", frame);
imshow("MyVideo", im_with_keypoints);
if (waitKey(30) == 27)
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
Anyone please help me
Oh! All actions and memory allocation inside loop. Try this:
int _tmain(int argc, _TCHAR* argv[]){
VideoCapture cap(0);
cap.open("file.mp4"); //read the video
if (!cap.isOpened())
{
cout << "Cannot open the video cam" << endl;
return -1;
}
double Width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
double Height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
cvNamedWindow("MyVideo", CV_WINDOW_AUTOSIZE);
Mat frame;
Mat blur, crop;
Mat mask(720, 1280, CV_8UC3, cv::Scalar(0, 0, 0));
Mat gray, changeToBlack;
Mat black_image(gray.size(), CV_8U, Scalar(255));
Mat thres, tes;
Mat erosi, dilasi, open, close, tophat;
Mat kernel = Mat(3, 3, CV_8UC1, Scalar(1));
Mat im_with_keypoints;
SimpleBlobDetector::Params params;
// Change thresholds
params.minThreshold = 0;
params.maxThreshold = 255;
params.filterByColor = true;
params.blobColor = 255;
// Filter by Area.
params.filterByArea = true;
params.minArea = 5 ;
// Filter by Circularity
params.filterByCircularity = true;
params.minCircularity = 0.1;
// Filter by Convexity
params.filterByConvexity = true;
params.minConvexity = 0.87;
// Filter by Inertia
params.filterByInertia = true;
params.minInertiaRatio = 0.01;
vector<KeyPoint> keypoints;
Ptr<SimpleBlobDetector> detector = SimpleBlobDetector::create(params);
while (cap.read(frame))
{
//crop the image with the pixel i want
GaussianBlur(frame, blur, Size(15, 15), 0); //blur the image
Point corners[1][4];
corners[0][0] = Point(550, 30); //top left
corners[0][1] = Point(250, 700); //bottom left
corners[0][2] = Point(1100, 700); //bottom right
corners[0][3] = Point(600, 30); //top right
const Point* corner_list[1] = { corners[0] };
int num_points = 4;
int num_polygons = 1;
int line_type = 8;
fillPoly(mask, corner_list, &num_points, num_polygons, cv::Scalar(255, 255, 255), line_type);
bitwise_and(blur, mask, crop);//combine the image
cvtColor(crop, gray, COLOR_BGR2GRAY); //grayscale citra
inRange(gray, Scalar(0), Scalar(0), changeToBlack);
black_image.copyTo(gray, changeToBlack);
threshold(gray, tes, 51, 255, THRESH_BINARY_INV); //threshold citra and 51 set value
morphologyEx(tes, erosi, MORPH_ERODE, kernel, Point(-1, -1), 3);
morphologyEx(erosi, dilasi, MORPH_DILATE, kernel, Point(-1, -1), 20);
detector->detect(dilasi, keypoints);
drawKeypoints(dilasi, keypoints, im_with_keypoints, Scalar(205, 0, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imshow("gray", frame);
imshow("MyVideo", im_with_keypoints);
if (waitKey(1) == 27)
{
cout << "esc key is pressed by user" << endl;
break;
}
}
return 0;
}
I have followed this article on how to calculate and deskew an image for better Tesseract OCR results: http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
The correct angle is calculated, but the text is never actually rotated.
These are the methods I am using:
+(UIImage *) prepareImage: (UIImage *)image{
return deskew(image, computeSkew(image));
}
// Organization -> Deskewing
double computeSkew(UIImage *image)
{
Mat src;
UIImageToMat(image, src);
cv::Size size = src.size();
bitwise_not(src, src);
vector<Vec4i> lines;
HoughLinesP(src, lines, 1, CV_PI/180, 100, size.width / 2.f, 20);
Mat disp_lines(size, CV_8UC1, Scalar(0, 0, 0));
double angle = 0.;
unsigned nb_lines = lines.size();
for (unsigned i = 0; i < nb_lines; ++i)
{
line(disp_lines, cv::Point(lines[i][0], lines[i][1]),
cv::Point(lines[i][2], lines[i][3]), Scalar(255, 0 ,0));
angle += atan2((double)lines[i][3] - lines[i][1],
(double)lines[i][2] - lines[i][0]);
}
angle /= nb_lines; // mean angle, in radians.
cout << angle << endl;
return angle;
}
UIImage* deskew(UIImage *image, double angle)
{
Mat img;
UIImageToMat(image, img);
bitwise_not(img, img);
vector<cv::Point> points;
Mat_<uchar>::iterator it = img.begin<uchar>();
Mat_<uchar>::iterator end = img.end<uchar>();
for (; it != end; ++it)
if (*it)
points.push_back(it.pos());
RotatedRect box = minAreaRect(Mat(points));
Mat rot_mat = getRotationMatrix2D(box.center, angle, 1);
Mat rotated;
warpAffine(img, rotated, rot_mat, img.size(), INTER_CUBIC);
return MatToUIImage(rotated);
}
UIImageToMat and MatToUIImage are reliable methods that convert back and forth. I have also tried to return the angle in both radians and degrees. Both times the image returned from the prepareImage function is still tilted at the same angle as the original image.
I'm trying to extract from an image only the contours which have a specific size.
I process like this
int offsetX ;
int offsetY ;
//here: read original image as 8UC3
cv::Mat original = cv::imread("0.png");
Mat imgx=original.clone();
cv::imshow("original", original);
cvtColor(imgx,imgx,CV_BGR2GRAY);
Mat thresh;
vector<Vec4i> hierarchy;
RNG rng(12345);
vector < vector<Point> > contours;
adaptiveThreshold(imgx, thresh, 255, 1, 1, 31, 2);
findContours(thresh, contours, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
Mat drawing = Mat::zeros(thresh.size(), CV_8UC3);
cout << "drawing "<<drawing.type()<<endl;
cv::Mat image = cv::Mat(original.rows, original.cols, original.type());
image.setTo(cv::Scalar::all(255));
for (size_t i = 0; i < contours.size(); i++)
{
vector < Point > cnt = contours[i];
if (contourArea(cnt) > 0)
{
Rect rec = boundingRect(cnt);
if ((rec.height > 20 ) &&(3.5*rec.height>rec.width)&& (rec.width>15)/*&& (rec.width<40)*/)
{
cout<<rec.x<<" "<<rec.y<<endl;
offsetX=rec.x;
offsetY=rec.y;
Mat roi = original(rec);
int width = roi.cols;
int height = roi.rows;
cout <<"h= "<<height<<" w= "<<width<<endl;
cv::Rect characterLocation;
if(height>35)
characterLocation = cv::Rect(offsetX+3, offsetY, width, height);
else
characterLocation = cv::Rect(offsetX, offsetY, width, height);
original(characterLocation).copyTo(image(characterLocation));
imshow("jihedddd",roi);
imwrite("xxxxxx.png",roi);
Mat stagedImage;
Mat img;
Scalar color = Scalar(255, 255, 255);
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
imshow("Contours", drawing);
waitKey();
GaussianBlur(stagedImage, img, Size(5, 5), 2, 2);
medianBlur(img, stagedImage, 3);
Mat copy = original.clone();
rectangle(copy, Point(rec.x, rec.y),
Point(rec.x + rec.width, rec.y + rec.height),
CV_RGB(0x00,0x00,0xff), 3);
cv::imshow("char copied", image);
}
}
}
medianBlur(image,image,3);
cv::imshow("char copied", image);
cv::imwrite("characterC_result.tiff ", image);
cv::waitKey();
But when I run this code I have an error
opencv error :assertion failed
This is an example of image which give me the error.
you have to be careful with this:
characterLocation = cv::Rect(offsetX+3, offsetY, width, height);
if width is the imagewidth, you are out of bounds here. you either have to subtract x from width, or crop the rect to the image borders:
// get the Rect for the original image:
cv::Rect borders(Point(0,0), image.size());
// crop to the legal size:
characterLocation = cv::Rect(offsetX+3, offsetY, width, height) & borders;
I'm making a couple of wrapper methods for fourier transform of image and have encountered a problem. Whenever I use the standard methods:
void fft::dfft(Mat* img,Mat* result){
Mat image;
img->convertTo(image, CV_32F);
cv::dft(image, *result, cv::DFT_SCALE|cv::DFT_COMPLEX_OUTPUT);
}
Invert the operations:
void fft::idft(Mat* fourier, Mat* img) {
//invert:
Mat inverseTransform;
dft(*fourier, inverseTransform, cv::DFT_INVERSE|cv::DFT_REAL_OUTPUT);
//restore image to 8 bits (fourier needs to use float at least
Mat res;
inverseTransform.convertTo(res, CV_8U);
res.copyTo(*img);
}
everything is ok. However when I try to use this pair:
void fft::dfft(Mat* img, Mat* mag, Mat* phi, Mat* re, Mat* im) {
/*SPECAL NOTE: dft is faster for images with size being multiple of two three and five. An OCV fmethod getOptrimalDFTSize comes in handy*/
Mat paddedImg; //expand input image to the optimal size
int m = getOptimalDFTSize(img->rows);
int n = getOptimalDFTSize(img->cols);
copyMakeBorder(*img, paddedImg, 0, m - img->rows, 0, n-img->cols, BORDER_CONSTANT, Scalar::all(0));
/*prepare space to store the image*/
Mat planes[] = {Mat_<float>(paddedImg), Mat::zeros(paddedImg.size(), CV_32F)};
Mat complexImg;
merge(planes, 2, complexImg);
/*Actual dft:*/
dft(complexImg, complexImg);
/*Get magnitude:*/
split(complexImg, planes);
Mat magImg, phasImg;
planes[0].copyTo(*re);
planes[1].copyTo(*im);
cout << "intern Real = "<< planes[0] << endl;
magnitude(planes[0], planes[1], magImg); //magnitude will be stored in planes[0]
phase(planes[0], planes[1], phasImg);
magImg.copyTo(*mag);
phasImg.copyTo(*phi);
#ifdef debug
namedWindow("Input Image", 0 );
imshow("Input Image", *img);
namedWindow( "Image magnitude", 0 );
imshow("Image magnitude", magImg);
waitKey(0);
#endif
}
To extract the specific parameters, I can't put it back together. Currently I'm focusing on Real and Imaginary part, because I feel that the Mag/Phi one will work in identical way just converting to real and imaginary back from Mag/Phi first.
void fft::idft(Mat* re, Mat* im, Mat* img, bool dummy) {
Mat inverseTransform;
Mat fourier(re->rows, re->cols, CV_32FC2);
vector<Mat> planes;
planes.push_back(*re);
planes.push_back(*im);
//re and im get inside correctly (verified)
Mat padded;
Mat complex;
Mat pp[] = {Mat_<float>(*re), Mat::zeros(re->size(), CV_32F)};
pp[0] = *re;
pp[1] = *im;
merge(pp, 2, complex); // Add to the expanded another plane with zeros
cv::merge(planes, fourier);
dft(complex, inverseTransform, cv::DFT_INVERSE|cv::DFT_REAL_OUTPUT);
Mat res;
inverseTransform.convertTo(res, CV_8U);
cv::imshow("iFFT1", res);
dft(fourier, inverseTransform, cv::DFT_INVERSE|cv::DFT_REAL_OUTPUT);
inverseTransform.convertTo(res, CV_8U);
cv::imshow("iFFT2", res);
res.copyTo(*img);
}
Both approaches (with vector and with array pp) produce the same white rectangle. To see if it does anything I passed
fft::idft(&re, &re, &img, true);
in such case result was identical in both windows (some random garbage but identical)
I suspect the problem lies in wrong merge procedure, but I have no other ideas how to restore the original form?
Thanks in advance for insights.
Here is my fourier domain filter, I think it should be useful:
#pragma once
#include <string>
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
//----------------------------------------------------------
// Recombinate quadrants
//----------------------------------------------------------
void Recomb(Mat &src,Mat &dst)
{
int cx = src.cols>>1;
int cy = src.rows>>1;
Mat tmp;
tmp.create(src.size(),src.type());
src(Rect(0, 0, cx, cy)).copyTo(tmp(Rect(cx, cy, cx, cy)));
src(Rect(cx, cy, cx, cy)).copyTo(tmp(Rect(0, 0, cx, cy)));
src(Rect(cx, 0, cx, cy)).copyTo(tmp(Rect(0, cy, cx, cy)));
src(Rect(0, cy, cx, cy)).copyTo(tmp(Rect(cx, 0, cx, cy)));
dst=tmp;
}
//----------------------------------------------------------
// Forward fft
//----------------------------------------------------------
void ForwardFFT(Mat &Src, Mat *FImg)
{
int M = getOptimalDFTSize( Src.rows );
int N = getOptimalDFTSize( Src.cols );
Mat padded;
copyMakeBorder(Src, padded, 0, M - Src.rows, 0, N - Src.cols, BORDER_CONSTANT, Scalar::all(0));
// Create complex image
// planes[0] image , planes[1] filled by zeroes
Mat planes[2] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat complexImg;
merge(planes, 2, complexImg);
dft(complexImg, complexImg,DFT_SCALE);
// After tranform we also get complex image
split(complexImg, planes);
//
planes[0] = planes[0](Rect(0, 0, planes[0].cols & -2, planes[0].rows & -2));
planes[1] = planes[1](Rect(0, 0, planes[1].cols & -2, planes[1].rows & -2));
Recomb(planes[0],planes[0]);
Recomb(planes[1],planes[1]);
FImg[0]=planes[0].clone();
FImg[1]=planes[1].clone();
}
//----------------------------------------------------------
// Inverse FFT
//----------------------------------------------------------
void InverseFFT(Mat *FImg,Mat &Dst)
{
Recomb(FImg[0],FImg[0]);
Recomb(FImg[1],FImg[1]);
Mat complexImg;
merge(FImg, 2, complexImg);
// Inverse transform
dft(complexImg, complexImg, DFT_INVERSE);
split(complexImg, FImg);
FImg[0].copyTo(Dst);
}
//----------------------------------------------------------
// Forward FFT using Magnitude and phase
//----------------------------------------------------------
void ForwardFFT_Mag_Phase(Mat &src, Mat &Mag,Mat &Phase)
{
Mat planes[2];
ForwardFFT(src,planes);
Mag.zeros(planes[0].rows,planes[0].cols,CV_32F);
Phase.zeros(planes[0].rows,planes[0].cols,CV_32F);
cv::cartToPolar(planes[0],planes[1],Mag,Phase);
}
//----------------------------------------------------------
// Inverse FFT using Magnitude and phase
//----------------------------------------------------------
void InverseFFT_Mag_Phase(Mat &Mag,Mat &Phase, Mat &dst)
{
Mat planes[2];
planes[0].create(Mag.rows,Mag.cols,CV_32F);
planes[1].create(Mag.rows,Mag.cols,CV_32F);
cv::polarToCart(Mag,Phase,planes[0],planes[1]);
InverseFFT(planes,dst);
}
//----------------------------------------------------------
// MAIN
//----------------------------------------------------------
int main(int argc, char* argv[])
{
// src image
Mat img;
// Magnitude
Mat Mag;
// Phase
Mat Phase;
// Image loading
img=imread("d:\\ImagesForTest\\lena.jpg",0);
resize(img,img,Size(512,512));
// Image size
cout<<img.size().width<<endl;
cout<<img.size().height<<endl;
//
ForwardFFT_Mag_Phase(img,Mag,Phase);
//----------------------------------------------------------
// Filter
//----------------------------------------------------------
// draw ring
int R=100; // External radius
int r=30; // internal radius
Mat mask;
mask.create(Mag.cols,Mag.rows,CV_32F);
int cx = Mag.cols>>1;
int cy = Mag.rows>>1;
mask=1;
cv::circle(mask,cv::Point(cx,cy),R,CV_RGB(0,0,0),-1);
cv::circle(mask,cv::Point(cx,cy),r,CV_RGB(1,1,1),-1);
//mask=1-mask; // uncomment for inversion
//cv::multiply(Mag,mask,Mag); // uncomment to turn filter on
//cv::multiply(Phase,mask,Phase);
//----------------------------------------------------------
// Inverse transform
//----------------------------------------------------------
InverseFFT_Mag_Phase(Mag,Phase,img);
//----------------------------------------------------------
// Results output
//----------------------------------------------------------
//
Mat LogMag;
LogMag.zeros(Mag.rows,Mag.cols,CV_32F);
LogMag=(Mag+1);
cv::log(LogMag,LogMag);
//---------------------------------------------------
imshow("Magnitude Log", LogMag);
imshow("Phase", Phase);
// img - now in CV_32FC1 format,we need CV_8UC1 or scale it by factor 1.0/255.0
img.convertTo(img,CV_8UC1);
imshow("Filtering result", img);
//----------------------------------------------------------
// Wait key press
//----------------------------------------------------------
waitKey(0);
return 0;
}
Sorry, I can't reproduce you result I've tested the code and it works fine:
#pragma once
#include <string>
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
//----------------------------------------------------------
// Recombinate quadrants
//----------------------------------------------------------
void Recomb(Mat &src,Mat &dst)
{
int cx = src.cols>>1;
int cy = src.rows>>1;
Mat tmp;
tmp.create(src.size(),src.type());
src(Rect(0, 0, cx, cy)).copyTo(tmp(Rect(cx, cy, cx, cy)));
src(Rect(cx, cy, cx, cy)).copyTo(tmp(Rect(0, 0, cx, cy)));
src(Rect(cx, 0, cx, cy)).copyTo(tmp(Rect(0, cy, cx, cy)));
src(Rect(0, cy, cx, cy)).copyTo(tmp(Rect(cx, 0, cx, cy)));
dst=tmp;
}
//----------------------------------------------------------
// Forward fft
//----------------------------------------------------------
void ForwardFFT(Mat &Src, Mat *FImg)
{
int M = getOptimalDFTSize( Src.rows );
int N = getOptimalDFTSize( Src.cols );
Mat padded;
copyMakeBorder(Src, padded, 0, M - Src.rows, 0, N - Src.cols, BORDER_CONSTANT, Scalar::all(0));
// Create complex image
// planes[0] image , planes[1] filled by zeroes
Mat planes[2] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
Mat complexImg;
merge(planes, 2, complexImg);
dft(complexImg, complexImg,DFT_SCALE);
// After tranform we also get complex image
split(complexImg, planes);
//
planes[0] = planes[0](Rect(0, 0, planes[0].cols & -2, planes[0].rows & -2));
planes[1] = planes[1](Rect(0, 0, planes[1].cols & -2, planes[1].rows & -2));
Recomb(planes[0],planes[0]);
Recomb(planes[1],planes[1]);
FImg[0]=planes[0].clone();
FImg[1]=planes[1].clone();
}
//----------------------------------------------------------
// Inverse FFT
//----------------------------------------------------------
void InverseFFT(Mat *FImg,Mat &Dst)
{
Recomb(FImg[0],FImg[0]);
Recomb(FImg[1],FImg[1]);
Mat complexImg;
merge(FImg, 2, complexImg);
// Inverse transform
dft(complexImg, complexImg, DFT_INVERSE);
split(complexImg, FImg);
FImg[0].copyTo(Dst);
}
//----------------------------------------------------------
// Forward FFT using Magnitude and phase
//----------------------------------------------------------
void ForwardFFT_Mag_Phase(Mat &src, Mat &Mag,Mat &Phase)
{
Mat planes[2];
ForwardFFT(src,planes);
Mag.zeros(planes[0].rows,planes[0].cols,CV_32F);
Phase.zeros(planes[0].rows,planes[0].cols,CV_32F);
cv::cartToPolar(planes[0],planes[1],Mag,Phase);
}
//----------------------------------------------------------
// Inverse FFT using Magnitude and phase
//----------------------------------------------------------
void InverseFFT_Mag_Phase(Mat &Mag,Mat &Phase, Mat &dst)
{
Mat planes[2];
planes[0].create(Mag.rows,Mag.cols,CV_32F);
planes[1].create(Mag.rows,Mag.cols,CV_32F);
cv::polarToCart(Mag,Phase,planes[0],planes[1]);
InverseFFT(planes,dst);
}
//----------------------------------------------------------
// MAIN
//----------------------------------------------------------
int main(int argc, char* argv[])
{
// src image
Mat img;
// Magnitude
Mat Mag;
// Phase
Mat Phase;
// Image loading (grayscale)
img=imread("d:\\ImagesForTest\\lena.jpg",0);
ForwardFFT_Mag_Phase(img,Mag,Phase);
//----------------------------------------------------------
// Inverse transform
//----------------------------------------------------------
InverseFFT_Mag_Phase(Mag,Phase,img);
img.convertTo(img,CV_8UC1);
imshow("Filtering result", img);
//----------------------------------------------------------
// Wait key press
//----------------------------------------------------------
waitKey(0);
return 0;
}
And it get the same image as input.