Я пытаюсь создать полосовой фильтр для удаления некоторых низкочастотных компонентов и высокочастотного шума из входного изображения:
Я хочу избавиться от большого темного пятна на левой стороне изображения, информация о ярких строках за строкой полезна и должна сохраняться после фильтрации.
Это отфильтрованное изображение:
Фильтр, похоже, убрал темное пятно, но проблема в том, что интенсивность ярких пикселей явно уменьшилась, а это не то, чего я хочу, я хочу сохранить контраст между яркими рядами и темным фоном.
У меня не так много опыта с фильтрацией изображений в частотной области. Я не знаю, является ли этот результат нормальным, когда низкочастотный сигнал был удален? Фрагмент кода был прикреплен.
void fft_filtering(cv::Mat img_gray, cv::Mat img_alpha) {
int M = GetOptimalDftSize(img_gray.rows);
int N = GetOptimalDftSize(img_gray.cols);
cv::Mat img_gray_padded;
cv::Mat planes[2];
cv::copyMakeBorder(img_gray, img_gray_padded, 0, M - img_gray.rows, 0,
N - img_gray.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));
planes[0] = cv::Mat_<float>(img_gray_padded);
planes[1] = cv::Mat::zeros(img_gray_padded.size(), CV_32F);
cv::Mat img_complex;
cv::merge(planes, 2, img_complex);
cv::dft(img_complex, img_complex);
cv::Mat filter(img_complex.size(), CV_32F);
int f3_inpixel, f2_inpixel, f1_inpixel;
CreateGaussianFilter(filter, img_alpha, FilterType::kBandPass, f3_inpixel, f2_inpixel, f1_inpixel);
// Apply filter
shiftDFT(img_complex);
cv::mulSpectrums(img_complex, filter, img_complex, 0);
shiftDFT(img_complex);
// Do inverse DFT on the filtered image
cv::idft(img_complex, img_complex);
// Split into planes and extract plane 0 as output image
cv::split(img_complex, planes);
cv::Mat img_out;
cv::normalize(planes[0], img_out, 0, 1, CV_MINMAX);
cv::Rect img_roi(0, 0, img_gray.cols, img_gray.rows);
img_filtered = img_out(img_roi);
}
void CreateGaussianFilter(cv::Mat& filter, cv::Mat img_alpha, FilterType filter_type,
float cutoff_f_low_InPixels, float cutoff_f_high_InPixels, float cutoff_f_center_InPixels){
cv::Mat gf(filter.size(), CV_32F);
cv::Point centre(filter.cols / 2, filter.rows / 2);
for(int u = 0; u < gf.rows; u++) {
for(int v = 0; v < gf.cols; v++) {
switch (filter_type) {
case FilterType::kHighPass:
gf.at<float>(u, v) = 1- GaussianCoeff(u - centre.y, v - centre.x, cutoff_f_low_InPixels);
break;
case FilterType::kLowPass:
gf.at<float>(u, v) = GaussianCoeff(u - centre.y, v - centre.x, cutoff_f_high_InPixels);
break;
case FilterType::kBandPass:
gf.at<float>(u, v) = GaussianCoeff(u - centre.y, v - centre.x, cutoff_f_high_InPixels) -
GaussianCoeff(u - centre.y, v - centre.x, cutoff_f_low_InPixels);
break;
}
}
}
// Keep the center pixel
gf.at<float>(centre.y, centre.x) = 1.0;
cv::Mat toMerge[] = {gf, gf};
merge(toMerge, 2, filter);
}