Visual C++ 2019中MFC图像处理编程(三) 图像增强

Visual C++ 2019 中 MFC 图像处理编程(三)

选择两个模板,编写图像增强的 C++语言程序。

  • 中值滤波
    图像的中值滤波是一种非线性的图像处理方法,它通过对邻域内像素按灰度排序的结果决定中心像素的灰度。图像的中值滤波在少量离散杂点的消除方面效果显著。

    在中值滤波算法中,对于孤立像素的属性并不非常关注,而是认为图像中的每个像素都跟邻域内其他像素有着密切的关系,对于每一个邻域,算法都会在采样得到的若干像素中,选择一个最有可能代表当前邻域特征的像素的灰度作为中心像素灰度,这样就有效避免了离散型杂点对图像的影响。

    如何有效地选择一个最有可能代表邻域特征的像素灰度是算法的核心问题。邻域像素中灰度大小居中的点通常能很好地描述邻域的属性,因此在中值滤波算法中,中心像素的灰度是通过对邻域内像素灰度排序然后取中值来确定的

    中值滤波不仅对孤立杂点的消除效果显著,对稍密集的杂点或稍大的杂点也有很好的去除效果。

    下面是使用 VS2019 C++ MFC 实现中值滤波的具体步骤:
    ① 将含若干个点的滑动窗口在图像中滑动,并将模板中心与图像中的某个像素位置重合;
    ② 读取模板中各对应像素的灰度值;
    ③ 将这些灰度值从小到大排序;
    ④ 取这一列数据的中间数据,将其赋值给对应模板中心位置的像素。
  • Sobel 算子
    有时还需要加强图像中景物的边缘和轮廓,边缘和轮廓通常位于图像中灰度突出的地方,因而可以直观的想到用灰度的差分对边缘和轮廓进行提取,通常可以通过梯度算子进行提取。图像锐化的目的是提高图像的对比度,从而使图像更清晰,通过提高邻域内像素的灰度差来提高图像的对比度。

    图像的边缘检测处理可以简单理解为提取图像中区域的轮廓。图像中区域的划分以像素灰度为依据,每个区域中的像素灰度大致相同,而区域之间的边界就称为边缘,寻找这些边缘就是图像边缘检测的目的。

    Sobel 边缘检测是基于多个卷积核扩展卷积操作而实现的,因此需要定义卷积核结构数组来说明其使用的卷积核。Sobel 边缘检测使用的卷积核数组,如下所示。

在这里插入图片描述

该算子包含两组 3x3 的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以 A 代表原始图像,Gx 及 Gy 分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:

在这里插入图片描述

图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:

在这里插入图片描述

通常,为了提高效率使用不开平方的近似值:

在这里插入图片描述

如果梯度 G 大于某一阀值,则认为该点(x,y)为边缘点。

Sobel 算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。

  • 中值滤波关键代码的实现:
    对原始图像进行中值滤波,构造两个循环。外循环对原始图像的每个像素逐个进行处理,内循环对中值滤波的核内的像素进行排序操作,找出中值,再赋给原像素。
do {
flag = 0;
for (m = 0; m < 9; m++){
if (kernel[m] < kernel[m + 1]){
temp = kernel[m];
kernel[m] = kernel[m + 1];
kernel[m + 1] = temp;
flag = 1;
}}} while (flag == 1);
mid = kernel[4];
filterpData[j * biWidth + i] = mid;
}}

再通过外循环对每个像素进行内循环操作。
  • Sobel 算子关键代码的实现:
  1. 定义 Sobel 算子:其中 xedge 用于检测 x 方向,yedge 用于检测 y 方向。
int xedge[3][3] = { {-1,0,1}, {-2,0,2},{-1,0,1} };
int yedge[3][3] = { {-1,-2,-1},{0,0,0},{1,2,1} };
  1. 将两个方向的 sobel 算子和核内的像素分别进行卷积运算,即相乘求和。
for (int a = -1; a <= 1; a++)
for (int b = -1; b <= 1; b++){{
dx = xedge[1 + a][1 + b];
dy = yedge[1 + a][1 + b];
c = pData[(i + a) * biWidth + (j + b)];
sx = sx + c * dx;
sy = sy + c * dy;
}
  1. 将两个方向的结果取绝对值后求和即为输出像素值。
int sxabs = abs(sx);
int syabs = abs(sy);
int r = sxabs + syabs;
sobelpData[i * biWidth + j] = r;
}
  • 运行结果如下所示:
    关于直方图的绘制后续有时间再做介绍。
    由图可得,分别使用不同大小的核对原始图像进行中值滤波。经过 3×3 大小的核进行中值滤波后,图像的边缘及细节明显变得模糊,这是由于中值滤波在滤除噪声及干扰的同时,会使边缘模糊,但较局部平滑法等其他空域平滑的方法而言,已经有效的保护边缘少受模糊了。减小核的大小,如 2×2 大小的核进行中值滤波。不同大小的核对图像进行滤波得到的图像信息不同,随着核的大小的增大,计算的像素点越多,也就意味着滤波后的图像包含了更多的低频信息,这样,随着核大小的增大,高频信息丢失,其模糊程度与核的大小成正比。从图中可以看出,Sobel 边缘检测的结果能用线条较好地描述图像。

在这里插入图片描述

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值