/* Performes a convolution by multiplication in frequency domain in input image kernel filter kernel return output image */ Mat frequencyConvolution(Mat& in, Mat& kernel) { const int kw = kernel.cols; const int kh = kernel.rows; Mat kernelBig = Mat::zeros(in.size(), in.type()); for (int x = 0; x < kw; ++x) { for (int y = 0; y < kh; ++y) { kernelBig.at<float>(x, y) = kernel.at<float>(x, y); } } Mat kernelBigShifted = circShift(kernelBig, -(kw/2), -(kh/2)); // transform into frequency domain Mat freqIn = Mat(in.size(), CV_32FC2); // complex Mat freqKernel = Mat(kernelBigShifted.size(), CV_32FC2); // complex dft(in, freqIn); dft(kernelBigShifted, freqKernel); // multiply in frequency domain (-> convolute in spatial domain) Mat freqRes = Mat(kernelBig.size(), CV_32FC2); // complex mulSpectrums(freqIn, freqKernel, freqRes, 0); // transform back into spatial domain Mat res(in.size(), in.type()); dft(freqRes, res, DFT_INVERSE | DFT_SCALE); return res; }
/* in input image kernel filter kernel return output image */ Mat Dip3::frequencyConvolution(Mat& in, Mat& kernel){ Mat tempA = Mat::zeros(in.rows, in.cols, CV_32FC1); Mat tempB = Mat::zeros(in.rows, in.cols, CV_32FC1); for (int x = 0; x < kernel.rows; x++) for (int y = 0; y < kernel.cols; y++) { tempB.at<float>(x, y) = kernel.at<float>(x, y); } tempB = circShift(tempB, -1, -1); dft(in, tempA, 0); dft(tempB, tempB, 0); mulSpectrums(tempA, tempB, tempB, 0); dft(tempB, tempA, DFT_INVERSE + DFT_SCALE); return tempA; }
void Dip3::test_circShift(void){ Mat in = Mat::zeros(3,3,CV_32FC1); in.at<float>(0,0) = 1; in.at<float>(0,1) = 2; in.at<float>(1,0) = 3; in.at<float>(1,1) = 4; Mat ref = Mat::zeros(3,3,CV_32FC1); ref.at<float>(0,0) = 4; ref.at<float>(0,2) = 3; ref.at<float>(2,0) = 2; ref.at<float>(2,2) = 1; if (sum((circShift(in, -1, -1) == ref)).val[0]/255 != 9){ cout << "ERROR: Dip3::circShift(): Result of circshift seems to be wrong!" << endl; return; } cout << "Message: Dip3::circShift() seems to be correct" << endl; }
/* in input image kernel filter kernel return output image */ Mat Dip3::frequencyConvolution(Mat& in, Mat& kernel){ Mat freq_in, freq_kernel, result; //copy kernel to large matrix (the size of input image) cv::Rect roi(cv::Point(0,0),kernel.size()); Mat destinationROI = Mat::zeros(in.size(), in.type()); kernel.copyTo(destinationROI(roi)); //perform circ shift on kernel Mat circ_kernel = circShift(destinationROI, -kernel.cols/2, -kernel.rows/2); //convert to frequency domains dft(in, freq_in, 0); dft(circ_kernel, freq_kernel, 0); //multiplication in freq domains mulSpectrums(freq_in, freq_kernel, freq_in,0); //convert to spatial domain dft(freq_in, result, DFT_INVERSE + DFT_SCALE); return result; }
/* degraded : degraded input image filter : filter which caused degradation return : restorated output image */ Mat Dip4::inverseFilter(Mat& degraded, Mat& filter){ // be sure not to touch them degraded = degraded.clone(); filter = filter.clone(); Mat tempA = Mat::zeros(degraded.size(), CV_32FC1); Mat degradedFreq = degraded.clone(); Mat filterFreq = Mat::zeros(degraded.size(), CV_32F); // add Border for (int x = 0; x < filter.rows; x++) for (int y = 0; y < filter.cols; y++) { filterFreq.at<float>(x, y) = filter.at<float>(x, y); } filterFreq = circShift(filterFreq, -1, -1); // transform to complex Mat planes[] = {degradedFreq, Mat::zeros(degraded.size(), CV_32F)}; Mat planesFilter[] = {filterFreq, Mat::zeros(filterFreq.size(), CV_32F)}; merge(planes, 2, degradedFreq); merge(planesFilter, 2, filterFreq); // convert to frequency spectrum dft(degradedFreq, degradedFreq, DFT_COMPLEX_OUTPUT); // degradedFreq == S dft(filterFreq, filterFreq, DFT_COMPLEX_OUTPUT); // filterFreq == P // create Q split(filterFreq, planes); Mat Re = planes[0]; Mat Im = planes[1]; // calculate Threshold double thresholdFactor = 0.05, threshold; double max = 0; // find maximum for (int x = 0; x < filterFreq.rows; x++) for (int y = 0; y < filterFreq.cols; y++) { float resq = Re.at<float>(x, y) * Re.at<float>(x, y); float imsq = Im.at<float>(x, y) * Im.at<float>(x, y); float absreim = sqrt(resq + imsq); if (absreim > max) { max = absreim; } } threshold = thresholdFactor * max; for (int x = 0; x < filterFreq.rows; x++) for (int y = 0; y < filterFreq.cols; y++) { float resq = Re.at<float>(x, y) * Re.at<float>(x, y); float imsq = Im.at<float>(x, y) * Im.at<float>(x, y); float absreim = sqrt(resq + imsq); if (absreim >= threshold) { Re.at<float>(x, y) = Re.at<float>(x, y) / (resq + imsq); Im.at<float>(x, y) = Im.at<float>(x, y) / (resq + imsq); } else { Re.at<float>(x, y) = 0; Im.at<float>(x, y) = 0; } } Mat Q = Mat::zeros(filterFreq.size(), CV_32F); merge(planes, 2, Q); Mat original; mulSpectrums(degradedFreq, Q, original, 1); dft(original, original, DFT_INVERSE + DFT_SCALE); split(original, planes); original = planes[0]; normalize(original, original, 0, 255, CV_MINMAX); original.convertTo(original, CV_8UC1); return original; }