做设计必知网站,电商公司官网,WordPress订阅下载插件,深圳市研发网站建设哪家好平滑处理–滤波 本文使用visual Studio MFC 平台实现对灰度图添加椒盐噪声#xff0c;并进行均值滤波与中值滤波 关于其他MFC单文档工程可参考 01-Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线 02-visual Studio MFC 绘制单一颜色三角形、渐变颜色边…平滑处理–滤波 本文使用visual Studio MFC 平台实现对灰度图添加椒盐噪声并进行均值滤波与中值滤波 关于其他MFC单文档工程可参考 01-Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线 02-visual Studio MFC 绘制单一颜色三角形、渐变颜色边框三角形、渐变填充三角形、边框渐变的正方形与填充渐变的正方形实例 文章目录 平滑处理--滤波一、添加椒盐噪声1.1 添加椒盐噪声的原理1.2 添加椒盐噪声的代码实现1.3 添加椒盐噪声后的效果 二、均值滤波2.1 均值滤波的原理2.2 均值滤波的代码实现2.3 均值滤波的实验效果 三、 中值滤波3.1 中值滤波的原理3.2 中值滤波的C实现3.3中值滤波后的效果图 一、添加椒盐噪声
1.1 添加椒盐噪声的原理
添加椒盐噪声是一种常见的图像噪声引入方式其原理是在图像中随机选择一些像素点并将这些像素点的灰度值设置为最大或最小值通常是白色最大值或黑色最小值。这样的噪声模拟了图像中出现的随机强烈亮或暗的噪声点类似于椒盐的颗粒因此得名。
具体步骤如下 选择噪声点 在图像中随机选择一些像素点作为噪声点。 设定噪声值 对于每个选定的噪声点将其灰度值设定为最大值白色或最小值黑色。
这样就在图像中引入了椒盐噪声这种噪声形式使图像中的某些区域变得非常亮或非常暗从而增加了图像的复杂性和难度。
椒盐噪声主要用于模拟一些特殊环境下的图像问题例如图像采集中的传感器错误、传输中的丢包等情况。在图像处理中去除或减轻椒盐噪声的方法通常包括滤波技术例如中值滤波。
1.2 添加椒盐噪声的代码实现
//添加椒盐噪声
void CMFCApplication1View::OnAddsaltpeppernoise()
{// TODO: 在此添加命令处理程序代码if (gray_data ! nullptr) {// 获取绘图设备CClientDC dc(this);CDC* pDC dc;// 创建临时数组用于保存添加噪声后的数据noisy_data new unsigned char[bmpWidth * bmpHeight];// 复制原始数据到临时数组std::copy(gray_data, gray_data bmpWidth * bmpHeight, noisy_data);// 添加椒盐噪声srand(static_castunsigned int(time(nullptr))); // 初始化随机数种子const double saltPepperRatio 0.01; // 椒盐噪声比例for (int i 0; i bmpWidth * bmpHeight; i) {double randomValue static_castdouble(rand()) / RAND_MAX;if (randomValue saltPepperRatio / 2) {noisy_data[i] 0; // 添加椒噪声}else if (randomValue saltPepperRatio) {noisy_data[i] 255; // 添加盐噪声}}// 绘制带有椒盐噪声的图像m_pBmp-drawGrayBmp(pDC, noisy_data, bmpWidth, bmpHeight, offset_left2*bmpWidth, offset_top 3 * bmpHeight);关于上面将原来灰度图的数据复制到新的数组noisy_data中的目的是为了保留添加椒盐噪声后的灰度图的数据以便后面的平滑操作 1.3 添加椒盐噪声后的效果 二、均值滤波
2.1 均值滤波的原理
均值滤波是一种常见的图像平滑处理方法其原理基于对图像的像素值进行平均运算。这种滤波方法主要用于去除图像中的噪声或细小的细节以产生更平滑的图像。
具体步骤如下 定义卷积核 选择一个固定大小的卷积核通常是一个正方形的矩阵。卷积核的大小取决于应用场景和对平滑度的需求。 卷积操作 将卷积核应用于图像的每个像素。对于每个像素将其与卷积核中对应位置的像素相乘然后将所有乘积的和除以卷积核的总权重。这个和的结果就是卷积核中心像素的新值。 更新图像 将卷积操作得到的新值赋予原始图像相应位置的像素形成平滑后的图像。
均值滤波的效果在平滑图像的同时会导致图像失真特别是对边缘和细节的处理较为粗糙。这是因为平均操作会模糊图像擦除图像中的高频信息。
公式表示如下其中 M 为卷积核的大小f(x, y) 为原始图像h(i, j) 为卷积核中的权重 g ( x , y ) 1 M ∑ i 1 M ∑ j 1 M h ( i , j ) ⋅ f ( x i , y j ) g(x, y) \frac{1}{M} \sum_{i1}^{M} \sum_{j1}^{M} h(i, j) \cdot f(xi, yj) g(x,y)M1i1∑Mj1∑Mh(i,j)⋅f(xi,yj)
其中g(x, y)是滤波后的像素值。
2.2 均值滤波的代码实现
//均值滤波
void CMFCApplication1View::OnMeanfilter()
{// TODO: 在此添加命令处理程序代码if (noisy_data ! nullptr) {// 获取绘图设备CClientDC dc(this);CDC* pDC dc;// 创建临时数组用于保存均值滤波后的数据unsigned char* filtered_data new unsigned char[bmpWidth * bmpHeight];// 设置均值滤波的卷积核大小3x3const int kernelSize 3;const int kernelHalfSize kernelSize / 2;// 应用均值滤波for (int y kernelHalfSize; y bmpHeight - kernelHalfSize; y) {for (int x kernelHalfSize; x bmpWidth - kernelHalfSize; x) {int sum 0;// 计算卷积核内的像素值之和for (int ky -kernelHalfSize; ky kernelHalfSize; ky) {for (int kx -kernelHalfSize; kx kernelHalfSize; kx) {int pixelValue noisy_data[(y ky) * bmpWidth (x kx)];sum pixelValue;}}// 计算均值并赋值给滤波后的像素filtered_data[y * bmpWidth x] static_castunsigned char(sum / (kernelSize * kernelSize));}}// 绘制均值滤波后的图像m_pBmp-drawGrayBmp(pDC, filtered_data, bmpWidth, bmpHeight, offset_left 3 * bmpWidth, offset_top 3 * bmpHeight);// 在图片下方添加文字GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;GdiplusStartup(gdiplusToken, gdiplusStartupInput, nullptr);{Graphics graphics(pDC-m_hDC);Gdiplus::Font font(LArial, 12);SolidBrush brush(Color(255, 128, 0, 128)); // 文字颜色为紫色// 文字的位置PointF point(offset_left 3* bmpWidth, offset_top 4 * bmpHeight);// 绘制文字graphics.DrawString(L均值滤波后的图像, -1, font, point, brush);}// 释放临时变量的内存delete[] filtered_data;GdiplusShutdown(gdiplusToken);}else {// 处理图像未加载的情况AfxMessageBox(_T(未加载图片));}
}
2.3 均值滤波的实验效果 三、 中值滤波
3.1 中值滤波的原理
中值滤波是一种非线性滤波方法它的原理是用像素点邻域灰度值的中值来代替该像素点的灰度值。中值滤波不会改变图像的灰度平均值但可以有效地去除图像中的椒盐噪声等离群点对于保持图像边缘细节方面也有一定的优势。
中值滤波的步骤如下 选择滤波模板大小 中值滤波通常采用3×3、5×5等奇数大小的模板。选择模板的大小会影响滤波效果。 将模板覆盖在图像的每个像素点上 以当前像素为中心取模板中所有像素的灰度值。 对模板中的灰度值进行排序 将模板中的灰度值按升序或降序排列。 取排序后的中值 选取排序后的中间值作为当前像素的新灰度值。 重复该过程 将模板在整个图像上滑动对每个像素应用相同的操作。
中值滤波的优点在于能够有效地去除椒盐噪声但在一些情况下可能会导致图像细节模糊。它特别适用于去除局部性较强的噪声。
3.2 中值滤波的C实现
//中值滤波
void CMFCApplication1View::OnMedianfilter()
{// TODO: 在此添加命令处理程序代码if (noisy_data ! nullptr) {// 获取绘图设备CClientDC dc(this);CDC* pDC dc;// 创建临时数组用于中值滤波处理unsigned char* median_filtered_data new unsigned char[bmpWidth * bmpHeight];// 中值滤波的处理代码int filter_size 3; // 中值滤波的邻域大小可以根据实际情况调整int filter_radius filter_size / 2;for (int y filter_radius; y bmpHeight - filter_radius; y) {for (int x filter_radius; x bmpWidth - filter_radius; x) {// 获取邻域内的像素值std::vectorunsigned char neighborhood;for (int j -filter_radius; j filter_radius; j) {for (int i -filter_radius; i filter_radius; i) {neighborhood.push_back(noisy_data[(y j) * bmpWidth (x i)]);}}// 对邻域内的像素值进行排序std::sort(neighborhood.begin(), neighborhood.end());// 计算中值并赋值给当前像素median_filtered_data[y * bmpWidth x] neighborhood[filter_size * filter_size / 2];}}// 绘制中值滤波后的图像m_pBmp-drawGrayBmp(pDC, median_filtered_data, bmpWidth, bmpHeight, offset_left 4 * bmpWidth, offset_top 3 * bmpHeight);// 在图片下方添加文字GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;GdiplusStartup(gdiplusToken, gdiplusStartupInput, nullptr);{Graphics graphics(pDC-m_hDC);Gdiplus::Font font(LArial, 12);SolidBrush brush(Color(255, 128, 0, 128)); // 文字颜色为紫色// 文字的位置PointF point(offset_left 4 * bmpWidth, offset_top 4 * bmpHeight);// 绘制文字graphics.DrawString(L中值滤波, -1, font, point, brush);}// 释放临时数组的内存delete[] median_filtered_data;GdiplusShutdown(gdiplusToken);}else {// 处理图像未加载的情况AfxMessageBox(_T(未加载图片));}
}
3.3中值滤波后的效果图