c++ opencv数字图像处理:频率域滤波--同态滤波
文章目錄
- 前言
- 一、同態濾波原理
- 1.處理原理
- 二、同態濾波器模板及MATLAB代碼
- 1.同態濾波器
- 2.代碼
前言
數字圖像處理c++ opencv(VS2019 opencv4.53)持續更新
一、同態濾波原理
1.處理原理
(1)認為圖像f(x,y)由兩部分組成:照射分量i(x,y),反射分量r(x,y):
f(x,y)=i(x,y)?r(x,y)f(x,y)=i(x,y)*r(x,y)f(x,y)=i(x,y)?r(x,y)
(2)但上式不能直接用于對兩個分量在頻率域進行處理,因為乘積的傅里葉變換不等于變換的乘積,因此,定義:
z(x,y)=lnf(x,y)=lni(x,y)+lnr(x,y)z(x,y)=lnf(x,y)=lni(x,y)+lnr(x,y)z(x,y)=lnf(x,y)=lni(x,y)+lnr(x,y)
(3)經過上面變換后可以進行傅里葉變換,有:
Z(u,v)=Fi(u,v)+Fr(u,v)Z(u,v)=F_i(u,v)+F_r(u,v)Z(u,v)=Fi?(u,v)+Fr?(u,v)
(4)然后可以設置一個濾波器H(u,v),對Z(u,v)進行濾波:
S(u,v)=H(u,v)?Z(u,v)=H(u,v)?Fi(u,v)+H(u,v)?Fr(u,v)S(u,v)=H(u,v)*Z(u,v)=H(u,v)*F_i(u,v)+H(u,v)*F_r(u,v)S(u,v)=H(u,v)?Z(u,v)=H(u,v)?Fi?(u,v)+H(u,v)?Fr?(u,v)
(5)對S(u,v)使用傅里葉逆變換得到s(x,y),則濾波后的圖像g(x,y):
g(x,y)=es(x,y)g(x,y)=e^{s(x,y)}g(x,y)=es(x,y)
在圖像中,認為低頻成分與照射分量相相聯系,高頻成分與反射分量相聯系。同態濾波就是設置一個濾波器H(x,y),使用不同的可控方法來影響低頻分量和高頻分量對圖像的影響。
二、同態濾波器模板及MATLAB代碼
1.同態濾波器
(1)高斯高通濾波的函數如下:
H(u,v)=1?e?D2(u,v)/2D02H(u,v)=1-e^{-D^2(u,v)/2D_0^2}H(u,v)=1?e?D2(u,v)/2D02?
高斯高通濾波器剖面圖如上,使低頻分量處為0,高頻分量處保持不變
(2)以高斯高通濾波器為模板改造的同態濾波器
H(u,v)=(γH?γL)[1?e?C[D2(u,v)/2D02]]+γLH(u,v)=(γ_H-γ_L)[1-e^{-C[D^2(u,v)/2D_0^2]}]+γ_LH(u,v)=(γH??γL?)[1?e?C[D2(u,v)/2D02?]]+γL?
其中γH和γL規定頻率的范圍,c控制中間的偏斜度其中γ_H和γ_L規定頻率的范圍,c控制中間的偏斜度其中γH?和γL?規定頻率的范圍,c控制中間的偏斜度
當γH>1γ_H>1γH?>1,γL<1γ_L<1γL?<1時,對應剖面圖為:
可以看出這個濾波器減少了低頻分量的影響,增加了高頻分量的影響。
(3)同態濾波步驟:
2.代碼
代碼如下:
#include<iostream> #include<opencv2/opencv.hpp> #include "MY_DFT.h"using namespace cv; using namespace std;int main() {Mat image, image_gray, image_output, image_transform; //定義輸入圖像,灰度圖像,輸出圖像image = imread("lena.png"); //讀取圖像;if (image.empty()){cout << "讀取錯誤" << endl;return -1;}imshow("image", image);cvtColor(image, image_gray, COLOR_BGR2GRAY); //轉換為灰度圖imshow("image_gray", image_gray); //顯示灰度圖//1、進行ln變換Mat image_gray2(image_gray.size(), CV_32F);for (int i = 0; i < image_gray.rows; i++){for (int j = 0; j < image_gray.cols; j++){image_gray2.at<float>(i, j) = log(image_gray.at<uchar>(i, j) + 0.1);}}//2、傅里葉變換,image_output為可顯示的頻譜圖,image_transform為傅里葉變換的復數結果My_DFT(image_gray2, image_output, image_transform);imshow("image_output", image_output);//3、高斯高通濾波Mat planes[] = { Mat_<float>(image_output), Mat::zeros(image_output.size(),CV_32F) };split(image_transform, planes);//分離通道,獲取實部虛部Mat image_transform_real = planes[0];Mat image_transform_imag = planes[1];int core_x = image_transform_real.rows / 2;//頻譜圖中心坐標int core_y = image_transform_real.cols / 2;int d0 = 10; //濾波半徑float h;//參數:float rh = 3;float rl = 0.5;float c = 5;for (int i = 0; i < image_transform_real.rows; i++){for (int j = 0; j < image_transform_real.cols; j++){h = (rh-rl) * (1 - exp(-c * ((i - core_x) * (i - core_x) + (j - core_y) * (j - core_y)) / (d0 * d0))) + rl;image_transform_real.at<float>(i, j) = image_transform_real.at<float>(i, j) * h;image_transform_imag.at<float>(i, j) = image_transform_imag.at<float>(i, j) * h;}}planes[0] = image_transform_real;planes[1] = image_transform_imag;Mat image_transform_ilpf;//定義高斯高通濾波結果merge(planes, 2, image_transform_ilpf);//4、傅里葉逆變換Mat iDft[] = { Mat_<float>(image_output), Mat::zeros(image_output.size(),CV_32F) };idft(image_transform_ilpf, image_transform_ilpf);//傅立葉逆變換split(image_transform_ilpf, iDft);//分離通道,主要獲取0通道magnitude(iDft[0], iDft[1], iDft[0]); //計算復數的幅值,保存在iDft[0]normalize(iDft[0], iDft[0], 0, 1, NORM_MINMAX);//歸一化處理exp(iDft[0], iDft[0]);normalize(iDft[0], iDft[0], 0, 1, NORM_MINMAX);//歸一化處理iDft[0].convertTo(iDft[0], CV_8U, 255 / 1.0, 0);imshow("idft", iDft[0]);//顯示逆變換圖像waitKey(0); //暫停,保持圖像顯示,等待按鍵結束return 0; }傅里葉變換代碼(.h文件):
#pragma once #include<iostream> #include<opencv2/opencv.hpp> #include<cmath>using namespace cv; using namespace std;void My_DFT(Mat input_image, Mat& output_image, Mat& transform_array);傅里葉變換代碼(.cpp文件):
#include "MY_DFT.h"//傅里葉變換得到頻譜圖和復數域結果 void My_DFT(Mat input_image, Mat& output_image, Mat& transform_image) {//1.擴展圖像矩陣,為2,3,5的倍數時運算速度快int m = getOptimalDFTSize(input_image.rows);int n = getOptimalDFTSize(input_image.cols);copyMakeBorder(input_image, input_image, 0, m - input_image.rows, 0, n - input_image.cols, BORDER_CONSTANT, Scalar::all(0));//2.創建一個雙通道矩陣planes,用來儲存復數的實部與虛部Mat planes[] = { Mat_<float>(input_image), Mat::zeros(input_image.size(), CV_32F) };//3.從多個單通道數組中創建一個多通道數組:transform_image。函數Merge將幾個數組合并為一個多通道陣列,即輸出數組的每個元素將是輸入數組元素的級聯merge(planes, 2, transform_image);//4.進行傅立葉變換dft(transform_image, transform_image);//5.計算復數的幅值,保存在output_image(頻譜圖)split(transform_image, planes); // 將雙通道分為兩個單通道,一個表示實部,一個表示虛部Mat transform_image_real = planes[0];Mat transform_image_imag = planes[1];magnitude(planes[0], planes[1], output_image); //計算復數的幅值,保存在output_image(頻譜圖)//6.前面得到的頻譜圖數級過大,不好顯示,因此轉換output_image += Scalar(1); // 取對數前將所有的像素都加1,防止log0log(output_image, output_image); // 取對數normalize(output_image, output_image, 0, 1, NORM_MINMAX); //歸一化//7.剪切和重分布幅度圖像限output_image = output_image(Rect(0, 0, output_image.cols & -2, output_image.rows & -2));// 重新排列傅里葉圖像中的象限,使原點位于圖像中心int cx = output_image.cols / 2;int cy = output_image.rows / 2;Mat q0(output_image, Rect(0, 0, cx, cy)); // 左上區域Mat q1(output_image, Rect(cx, 0, cx, cy)); // 右上區域Mat q2(output_image, Rect(0, cy, cx, cy)); // 左下區域Mat q3(output_image, Rect(cx, cy, cx, cy)); // 右下區域//交換象限中心化Mat tmp;q0.copyTo(tmp); q3.copyTo(q0); tmp.copyTo(q3);//左上與右下進行交換q1.copyTo(tmp); q2.copyTo(q1); tmp.copyTo(q2);//右上與左下進行交換Mat q00(transform_image_real, Rect(0, 0, cx, cy)); // 左上區域Mat q01(transform_image_real, Rect(cx, 0, cx, cy)); // 右上區域Mat q02(transform_image_real, Rect(0, cy, cx, cy)); // 左下區域Mat q03(transform_image_real, Rect(cx, cy, cx, cy)); // 右下區域q00.copyTo(tmp); q03.copyTo(q00); tmp.copyTo(q03);//左上與右下進行交換q01.copyTo(tmp); q02.copyTo(q01); tmp.copyTo(q02);//右上與左下進行交換Mat q10(transform_image_imag, Rect(0, 0, cx, cy)); // 左上區域Mat q11(transform_image_imag, Rect(cx, 0, cx, cy)); // 右上區域Mat q12(transform_image_imag, Rect(0, cy, cx, cy)); // 左下區域Mat q13(transform_image_imag, Rect(cx, cy, cx, cy)); // 右下區域q10.copyTo(tmp); q13.copyTo(q10); tmp.copyTo(q13);//左上與右下進行交換q11.copyTo(tmp); q12.copyTo(q11); tmp.copyTo(q12);//右上與左下進行交換planes[0] = transform_image_real;planes[1] = transform_image_imag;merge(planes, 2, transform_image);//將傅里葉變換結果中心化 }結果:
總結
以上是生活随笔為你收集整理的c++ opencv数字图像处理:频率域滤波--同态滤波的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GARFIELD@10-31-2004
- 下一篇: 纸娃娃系统再次增强