Periodic noise produces spikes in the Fourier domain that can often be detected by visual analysis.
Periodic noise can be reduced significantly via frequency domain filtering. On this page we use a notch reject filter with an appropriate radius to completely enclose the noise spikes in the Fourier domain. The notch filter rejects frequencies in predefined neighborhoods around a center frequency. The number of notch filters is arbitrary. The shape of the notch areas can also be arbitrary (e.g. rectangular or circular). On this page we use three circular shape notch reject filters. Power spectrum densify of an image is used for the noise spike’s visual detection.
#include <iostream>
void fftshift(
const Mat& inputImg,
Mat& outputImg);
void filter2DFreq(
const Mat& inputImg,
Mat& outputImg,
const Mat& H);
void synthesizeFilterH(
Mat& inputOutput_H,
Point center,
int radius);
void calcPSD(
const Mat& inputImg,
Mat& outputImg,
int flag = 0);
"{help h usage ? | | print this message }"
"{@image |period_input.jpg | input image name }"
;
int main(
int argc,
char* argv[])
{
string strInFileName = parser.get<
String>(
"@image");
samples::addSamplesDataSearchSubDirectory("doc/tutorials/imgproc/periodic_noise_removing_filter/images");
Mat imgIn = imread(samples::findFile(strInFileName), IMREAD_GRAYSCALE);
{
cout << "ERROR : Image cannot be loaded..!!" << endl;
return -1;
}
imshow("Image corrupted", imgIn);
imgIn = imgIn(roi);
calcPSD(imgIn, imgPSD);
fftshift(imgPSD, imgPSD);
normalize(imgPSD, imgPSD, 0, 255, NORM_MINMAX);
const int r = 21;
synthesizeFilterH(H,
Point(705, 458), r);
synthesizeFilterH(H,
Point(850, 391), r);
synthesizeFilterH(H,
Point(993, 325), r);
fftshift(H, H);
filter2DFreq(imgIn, imgOut, H);
normalize(imgOut, imgOut, 0, 255, NORM_MINMAX);
imwrite("result.jpg", imgOut);
imwrite("PSD.jpg", imgPSD);
fftshift(H, H);
normalize(H, H, 0, 255, NORM_MINMAX);
imshow("Debluring", imgOut);
imwrite("filter.jpg", H);
waitKey(0);
return 0;
}
void fftshift(
const Mat& inputImg,
Mat& outputImg)
{
outputImg = inputImg.
clone();
int cx = outputImg.
cols / 2;
int cy = outputImg.
rows / 2;
Mat q0(outputImg,
Rect(0, 0, cx, cy));
Mat q1(outputImg,
Rect(cx, 0, cx, cy));
Mat q2(outputImg,
Rect(0, cy, cx, cy));
Mat q3(outputImg,
Rect(cx, cy, cx, cy));
q3.copyTo(q0);
q1.copyTo(tmp);
q2.copyTo(q1);
}
void filter2DFreq(
const Mat& inputImg,
Mat& outputImg,
const Mat& H)
{
merge(planes, 2, complexI);
dft(complexI, complexI, DFT_SCALE);
merge(planesH, 2, complexH);
idft(complexIH, complexIH);
split(complexIH, planes);
outputImg = planes[0];
}
void synthesizeFilterH(
Mat& inputOutput_H,
Point center,
int radius)
{
Point c2 = center, c3 = center, c4 = center;
c2.
y = inputOutput_H.
rows - center.
y;
c3.x = inputOutput_H.
cols - center.
x;
circle(inputOutput_H, center, radius, 0, -1, 8);
circle(inputOutput_H, c2, radius, 0, -1, 8);
circle(inputOutput_H, c3, radius, 0, -1, 8);
circle(inputOutput_H, c4, radius, 0, -1, 8);
}
void calcPSD(
const Mat& inputImg,
Mat& outputImg,
int flag)
{
merge(planes, 2, complexI);
planes[0].
at<
float>(0) = 0;
planes[1].
at<
float>(0) = 0;
pow(imgPSD, 2, imgPSD);
outputImg = imgPSD;
if (flag)
{
imglogPSD = imgPSD + Scalar::all(1);
log(imglogPSD, imglogPSD);
outputImg = imglogPSD;
}
}
Designed for command line parsing.
Definition utility.hpp:890
Template matrix class derived from Mat.
Definition mat.hpp:2247
n-dimensional dense array class
Definition mat.hpp:829
CV_NODISCARD_STD Mat clone() const
Creates a full copy of the array and the underlying data.
MatSize size
Definition mat.hpp:2177
void copyTo(OutputArray m) const
Copies the matrix to another one.
_Tp & at(int i0=0)
Returns a reference to the specified array element.
int cols
Definition mat.hpp:2155
bool empty() const
Returns true if the array has no elements.
int rows
the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
Definition mat.hpp:2155
void convertTo(OutputArray m, int rtype, double alpha=1, double beta=0) const
Converts an array to another data type with optional scaling.
_Tp y
y coordinate of the point
Definition types.hpp:202
_Tp x
x coordinate of the point
Definition types.hpp:201
Template class for 2D rectangles.
Definition types.hpp:444
Size_< _Tp > size() const
size (width, height) of the rectangle
void split(const Mat &src, Mat *mvbegin)
Divides a multi-channel array into several single-channel arrays.
void mulSpectrums(InputArray a, InputArray b, OutputArray c, int flags, bool conjB=false)
Performs the per-element multiplication of two Fourier spectrums.
void magnitude(InputArray x, InputArray y, OutputArray magnitude)
Calculates the magnitude of 2D vectors.
void merge(const Mat *mv, size_t count, OutputArray dst)
Creates one multi-channel array out of several single-channel ones.
void idft(InputArray src, OutputArray dst, int flags=0, int nonzeroRows=0)
Calculates the inverse Discrete Fourier Transform of a 1D or 2D array.
void dft(InputArray src, OutputArray dst, int flags=0, int nonzeroRows=0)
Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating-point array.
std::string String
Definition cvstd.hpp:151
#define CV_8U
Definition interface.h:73
#define CV_32F
Definition interface.h:78
@ circle
Definition gr_skig.hpp:62
int main(int argc, char *argv[])
Definition highgui_qt.cpp:3
Periodic noise reduction by frequency domain filtering consists of power spectrum density calculation (for the noise spikes visual detection), notch reject filter synthesis and frequency filtering:
A function synthesizeFilterH() forms a transfer function of an ideal circular shape notch reject filter according to a center frequency and a radius:
A function filter2DFreq() filters an image in the frequency domain. The functions fftshift() and filter2DFreq() are copied from the tutorial Out-of-focus Deblur Filter.
The figure below shows an image heavily corrupted by periodical noise of various frequencies.
The noise components are easily seen as bright dots (spikes) in the Power spectrum density shown in the figure below.
The figure below shows a notch reject filter with an appropriate radius to completely enclose the noise spikes.
The result of processing the image with the notch reject filter is shown below.
The improvement is quite evident. This image contains significantly less visible periodic noise than the original image.