start_time: 2024-04-29 05:43:00 +0800

OpenCV C++(十一)----频率域滤波

96
肉松饼饼
IP属地: 广东
0.1 2020.03.08 17:42 字数 1440

11.1概述和原理

  • 低频指的是图像的傅里叶变换“中心位置”附近的区域。 低频信息表示图像中灰度值缓慢变化的区域 。

  • 高频随着到“中心位置”距离的增加而增加, 即傅里叶变换中心位置的外围区域, 这里的“中心位置”指的是傅里叶变换所对应的幅度谱最大值的位置。高频信息则正好相反, 表示灰度值变化迅速的部分, 如边缘。

频率域滤波器在程序或者数学运算中的呈现可以理解为一个矩阵。下面所涉及的常用的低通、 高通、 带通、 带阻 等滤波的关键步骤, 就是通过一定的准则构造该矩阵的。

image.png

算法步骤:

  • 第一步: 输入图像矩阵I。
  • 第二步: 图像矩阵的每一个像素值乘以(-1) r+c得到矩阵I′, I′ =I.*(-1) r+c , 其中r和c代表当前像素值在矩阵中的位置索引。
  • 第三步: 因为图像矩阵的宽和高均为7, 为了利用傅里叶变换的快速算法, 对I′补0, 使用命令getOptimalDFTSize(7) 得到一个不小于7且可以分解为2p ×3q ×5r的最小整数, 计算结果为8。 所以在矩阵I′的右侧和下侧各补一行0, 记为f
  • 第四步: 利用傅里叶变换的快速算法得到复数矩阵F。
  • 第五步: 构建频率域滤波器Filter。 频率域滤波器本质上是一个和第四步得到的快速 傅里叶变换矩阵F 具有相同行数、 列数的复数矩阵, 一般情况下为实数矩阵
  • 第六步: 将第四步得到的快速傅里叶变换矩阵F 和第五步得到的频率域滤波器Filter 的对应位置相乘(矩阵的点乘) 。 当然,如果滤波器是一个实数矩阵,那么在代码实现中,将傅里叶变换的实部和虚部分别与频率域滤波器进行点乘即可,即F filter =F.*Filter,因为这里构造的滤波器是一个全是1的矩阵, 所以F filter =F
  • 第七步: 对第六步得到的点乘矩阵F filter进行傅里叶逆变换,得到复数矩阵F′。
  • 第八步: 取复数矩阵F′的实部。
  • 第九步: 与第二步类似, 将第八步得到的矩阵乘以(-1) r+c
  • 第十步:进行裁剪, 取该实部矩阵的左上角, 尺寸和原图相同。 裁剪得到的结果, 即为频率域滤波的结果。

11.2、低通滤波器和高通滤波器

11.2.1、低通滤波器

1、理想低通滤波器

image.png

2、巴特沃斯低通滤波器

image.png

3、高斯低通滤波器

image.png
//创建三种常见的低通滤波器
enum FILTER_TYPE {
    ILP_FILTER = 0,
    BLP_FILTER = 1,
    GLP_FILTER = 2
};

Mat creatLPFilter(Size size, Point center, float radius, FILTER_TYPE type, int n)
{
    Mat lpFilter = Mat::zeros(size, CV_32FC1);
    int rows = size.height;
    int cols = size.width;
    if (radius <= 0)
    {
        return lpFilter;
    }
    //构建理想低通滤波器
    if (type == ILP_FILTER)
    {
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                float norm2 = pow(abs(float(r - center.y)), 2) + pow(abs(float(c - center.x)), 2);
                if (sqrt(norm2) < radius)
                {
                    lpFilter.at<float>(r,c) = 1;
                }
                else
                {
                    lpFilter.at<float>(r, c) = 0;
                }
            }
        }
    }
    //构建巴特沃斯低通滤波器
    if (type == BLP_FILTER)
    {
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                lpFilter.at<float>(r, c) = float(1.0 / (1.0 + pow(sqrt(pow(r - center.y, 2.0) + pow(c - center.x, 2.0)) / radius, 2.0*n)));
            }
        }
    }
    //构建高斯低通滤波器
    if (type == GLP_FILTER)
    {
        for (int r = 0; r < rows; r++)
        {
            for (int c = 0; c < cols; c++)
            {
                lpFilter.at<float>(r, c) = float(exp(-(pow(r - center.y, 2.0) + pow(c - center.x, 2.0)) / (2 * pow(radius, 2.0))));
            }
        }
    }
    return lpFilter;
}

Mat I;//输入的图像矩阵
Mat F;//图像的快速傅里叶变换
Point maxLoc;//傅里叶谱的最大值的坐标
int radius = 20;//截断频率
const int Max_RADIUS = 100;//设置的最大的截断频率
Mat lpFilter;//低通滤波器
int lpType = 0;//低通滤波器的类型
const int MAX_LPTYPE = 2;
Mat F_lpFilter;//低通傅里叶变换
Mat flpSpectrum;//低通傅里叶变换的傅里叶谱的灰度级
Mat result;//低通滤波后的效果
string lpFilterspectrum = "低通傅里叶谱";//显示窗口的名称
void callback_lpFilter(int, void*);
int main()
{
    //step1:读入图像矩阵
    Mat I = imread("Koala.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    if (!I.data)
    {
        return -1;
    }
    //数据类型转换为浮点型
    Mat fI;
    I.convertTo(fI, CV_32FC1, 1.0, 0.0);
    //step2:每一个数乘于(-1)^(r+c)
    for (int r = 0; r < fI.rows; r++)
    {
        for (int c = 0; c < fI.cols; c++)
        {
            if ((r + c) % 2)
            {
                fI.at<float>(r, c) *= -1;
            }
        }
    }
    //step3:补零;step4:快速傅里叶变换
    fft2Image(fI, F);
    //傅里叶谱
    Mat amplSpec;
    amplitudeSpectrum(F, amplSpec);
    //傅里叶谱的灰度级显示
    Mat spectrum = graySpectrum(amplSpec);
    //找到傅里叶谱的最大值的坐标
    minMaxLoc(spectrum, NULL, NULL, NULL, &maxLoc);
    //低通滤波
    namedWindow(lpFilterspectrum, WINDOW_AUTOSIZE);
    createTrackbar("低通类型", lpFilterspectrum, &lpType, MAX_LPTYPE, callback_lpFilter);
    createTrackbar("半径", lpFilterspectrum, &radius, Max_RADIUS, callback_lpFilter);
    callback_lpFilter(0, 0);
    waitKey(0);
    return 0;
}


void callback_lpFilter(int, void*)
{
    //step5:构建低通滤波器
    lpFilter = creatLPFilter(F.size(), maxLoc, radius, lpType, 2);
    //step6:低通滤波器和图像的快速傅里叶变换点乘
    F_lpFilter.create(F.size(), F.type());
    for (int r = 0; r < F_lpFilter.rows; r++)
    {
        for (int c = 0; c < F_lpFilter.cols; c++)
        {
            //分别取出当前位置的快速傅里叶变换和理想低通滤波器的值
            Vec2f F_rc = F.at<Vec2f>(r, c);
            float lpFilter_rc = lpFilter.at<float>(r, c);
            //低通滤波器和图像的快速傅里叶变换的对应位置相乘
            F_lpFilter.at<Vec2f>(r, c) = F_rc * lpFilter_rc;
        }
    }
    //低通傅里叶变换的傅里叶谱
    amplitudeSpectrum(F_lpFilter, flpSpectrum);
    //低通傅里叶谱的灰度级显示
    flpSpectrum = graySpectrum(flpSpectrum);
    //step7、8:对低通滤波器变换执行傅里叶逆变换,并只取实部
    dft(F_lpFilter, result, DFT_SCALE + DFT_INVERSE + DFT_REAL_OUTPUT);
    //step9:同乘以(-1)^(x+y)
    for (int r = 0; r < result.rows; r++)
    {
        for (int c = 0; c < result.cols; c++)
        {
            if ((r + c) % 2)
            {
                result.at<float>(r, c)  *= -1;
            }
        }
    }
    //注意将结果转换为CV_8U类型
    result.convertTo(result, CV_8UC1, 1.0, 0);
    //step10:截取左上部分,其大小和输入图像的大小相同
    result = result(Rect(0, 0, I.cols, I.rows)).clone();
}

11.2.2、高通滤波器

1、理想高通滤波器

image.png

2、巴特沃斯高通滤波器

image.png

3、高斯高通滤波器

image.png

显然, 高通滤波器和低通滤波器满足这样的关系:

hpFilter=1-lpFilter

即1减去通过createLPFilter得到的矩阵就可以得到高通滤波器 。

11.3、带通和带阻滤波器

带通滤波是指只保留某一范围区域的频率带。

11.3.1、带通滤波器

1、理想带通滤波器

image.png

2、巴特沃斯带通滤波器

image.png

3、高斯带通滤波器

image.png

11.3.2、带阻滤波器

与带通滤波相反, 带阻滤波是指撤销或者消弱指定范围区域的频率带。

1、理想带阻滤波器

image.png

2、巴特沃斯带阻滤波器

image.png

3、高斯带阻滤波器

image.png

显然, 1减去带通滤波就可以得到相应的带阻滤波。

11.4、自定义滤波器

有一种通过交互式的方式, 构建自定义滤波, 便于消除指定的频率。 自定义滤波器通常用于消除结构化噪声或者目标。

11.5、同态滤波

同态滤波是一种减少低频增加高频,从而减少光照变化并锐化边缘或者细节的滤波方法。

对于一幅图像f(x,y),可以表示为照射分量i(x,y)和反射分量r(x,y)的乘积。
其中0<i(x,y)<∞,0<r(x,y)<1。

i(x,y)描述景物的照明,变化缓慢,处于低频成分。

r(x,y)描述景物的细节,变化较快,处于高频成分。

因为该性质是乘性的,所以不能直接使用傅里叶变换对i(x,y)和r(x,y)进行控制,因此可以先对f(x,y)取对数,分离i(x,y)和r(x,y)。令z(x,y) = ln f(x,y) = ln i(x,y) + ln r(x,y)。由于f(x,y)的取值范围为[0, L-1],为了避免出现ln(0)的情况,故采用ln ( f(x,y) + 1 ) 来计算。

image.png
image.png

同态滤波与频率域滤波的不同之处是, 它在最开始对输入的图像矩阵进行对数运 算, 在最后一步进行对数运算的逆运算, 即指数运算, 其中间步骤就是频率域滤波的步骤。

最后编辑于 :2020-03-08 17:42:47
©著作权归作者所有,转载或内容合作请联系作者
序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
783c64db 45e5 48d7 82e4 95736f50533e 沈念sama 阅读 159569 评论 4 赞 363
序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
783c64db 45e5 48d7 82e4 95736f50533e 沈念sama 阅读 67499 评论 1 赞 294
文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
8 开封第一讲书人 阅读 109271 评论 0 赞 244
文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
8 开封第一讲书人 阅读 44087 评论 0 赞 209
正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
388e473c fe2f 40e0 9301 e357ae8f1b41 茶点故事 阅读 52474 评论 3 赞 287
文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
8 开封第一讲书人 阅读 40670 评论 1 赞 222
那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
783c64db 45e5 48d7 82e4 95736f50533e 沈念sama 阅读 31911 评论 2 赞 313
文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
8 开封第一讲书人 阅读 30636 评论 0 赞 202
序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
783c64db 45e5 48d7 82e4 95736f50533e 沈念sama 阅读 34397 评论 1 赞 246
正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
388e473c fe2f 40e0 9301 e357ae8f1b41 茶点故事 阅读 30607 评论 2 赞 246
正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
388e473c fe2f 40e0 9301 e357ae8f1b41 茶点故事 阅读 32093 评论 1 赞 261
序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
783c64db 45e5 48d7 82e4 95736f50533e 沈念sama 阅读 28418 评论 2 赞 254
正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
388e473c fe2f 40e0 9301 e357ae8f1b41 茶点故事 阅读 33074 评论 3 赞 237
文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
8 开封第一讲书人 阅读 26092 评论 0 赞 8
文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
8 开封第一讲书人 阅读 26865 评论 0 赞 196
我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
783c64db 45e5 48d7 82e4 95736f50533e 沈念sama 阅读 35726 评论 2 赞 276
正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
388e473c fe2f 40e0 9301 e357ae8f1b41 茶点故事 阅读 35627 评论 2 赞 270
end_time: 2024-04-29 05:43:00 +0800 Completed in 120.933866ms