资源描述
作业:对lean.raw文件,采用中值滤波和均值滤波,完成图象去噪
中值滤波:
/************************************************************************* *
* 函数名称:
* MedianFilter() *
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * int iFilterH - 滤波器的高度 * int iFilterW - 滤波器的宽度
* int iFilterMX - 滤波器的中心元素X坐标 * int iFilterMY - 滤波器的中心元素Y坐标 *
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。 *
* 说明:
* 该函数对DIB图像进行中值滤波。 *
************************************************************************/
BOOL WINAPI MedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,
int iFilterH, int iFilterW, int iFilterMX, int iFilterMY) {
// 指向源图像的指针 unsigned char* lpSrc;
// 指向要复制区域的指针 unsigned char* lpDst;
// 指向复制图像的指针 LPSTR lpNewDIBBits; HLOCAL hNewDIBBits;
// 指向滤波器数组的指针 unsigned char * aValue; HLOCAL hArray;
// 循环变量 LONG i; LONG j; LONG k; LONG l;
// 图像每行的字节数 LONG lLineBytes;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
// 判断是否内存分配失败 if (hNewDIBBits == NULL) {
// 分配内存失败 return FALSE; }
// 锁定内存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化图像为原始图像
memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight);
// 暂时分配内存,以保存滤波器数组
hArray = LocalAlloc(LHND, iFilterH * iFilterW);
// 判断是否内存分配失败 if (hArray == NULL) {
// 释放内存
LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits);
// 分配内存失败
return FALSE;
}
// 锁定内存
aValue = (unsigned char * )LocalLock(hArray);
// 开始中值滤波
// 行(除去边缘几行)
for(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++) {
// 列(除去边缘几列)
for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++) {
// 指向新DIB第i行,第j个象素的指针
lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight -
1 - i) + j;
// 读取滤波器数组
for (k = 0; k < iFilterH; k++) {
for (l = 0; l < iFilterW; l++) {
// 指向DIB第i - iFilterMY + k行,第j -
iFilterMX + l个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes
* (lHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;
// 保存象素值
aValue[k * iFilterW + l] = *lpSrc; } }
// 获取中值
* lpDst = GetMedianNum(aValue, iFilterH * iFilterW); } }
// 复制变换后的图像
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); LocalUnlock(hArray); LocalFree(hArray);
// 返回 return TRUE;
}
均值滤波:
/************************************************************************* *
* 函数名称:
* GetMedianNum() *
* 参数:
* unsigned char * bpArray - 指向要获取中值的数组指针 * int iFilterLen - 数组长度
*
* 返回值:
* unsigned char - 返回指定数组的中值。
*
* 说明:
* 该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。 *
************************************************************************/
unsigned char WINAPI GetMedianNum(unsigned char * bArray, int iFilterLen) {
// 循环变量 int i; int j;
// 中间变量
unsigned char bTemp;
// 用冒泡法对数组进行排序
for (j = 0; j < iFilterLen - 1; j ++)
{
for (i = 0; i < iFilterLen - j - 1; i ++)
{
if (bArray[i] > bArray[i + 1])
{
// 互换
bTemp = bArray[i];
bArray[i] = bArray[i + 1];
bArray[i + 1] = bTemp;
}
}
}
// 计算中值
if ((iFilterLen & 1) > 0)
{
// 数组有奇数个元素,返回中间一个元素 bTemp = bArray[(iFilterLen + 1) / 2]; }
else {
// 数组有偶数个元素,返回中间两个元素平均值
bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2; }
// 返回中值 return bTemp; }
/// <summary>
9 /// 中值滤波算法处理
10 /// </summary>
11 /// <param name="bmp">原始图片</param>
12 /// <param name="bmp">是否是彩色位图</param>
13 /// <param name="windowRadius">过滤半径</param>
14 public Bitmap ColorfulBitmapMedianFilterFunction(Bitmap srcBmp, int windowRadius, bool IsColorfulBitmap)
15 {
16 if (windowRadius < 1)
17 {
18 throw new Exception("过滤半径小于1没有意义");
19 }
20 //创建一个新的位图对象
21 Bitmap bmp = new Bitmap(srcBmp.Width, srcBmp.Height);
22
23 //存储该图片所有点的RGB值
24 byte[,] mR,mG,mB;
25 mR = new byte[srcBmp.Width, srcBmp.Height];
26 if (IsColorfulBitmap)
27 {
28 mG = new byte[srcBmp.Width, srcBmp.Height];
29 mB = new byte[srcBmp.Width, srcBmp.Height];
30 }
31 else
32 {
33 mG = mR;
34 mB = mR;
35 }
36
37 for (int i = 0; i <= srcBmp.Width - 1; i++)
38 {
39 for (int j = 0; j <= srcBmp.Height - 1; j++)
40 {
41 mR[i, j] = srcBmp.GetPixel(i, j).R;
42 if (IsColorfulBitmap)
43 {
44 mG[i, j] = srcBmp.GetPixel(i, j).G;
45 mB[i, j] = srcBmp.GetPixel(i, j).B;
46 }
47 }
48 }
49
50 mR = MedianFilterFunction(mR, windowRadius);
51 if (IsColorfulBitmap)
52 {
53 mG = MedianFilterFunction(mG, windowRadius);
54 mB = MedianFilterFunction(mB, windowRadius);
55 }
56 else
57 {
58 mG = mR;
59 mB = mR;
60 }
61 for (int i = 0; i <= bmp.Width - 1; i++)
62 {
63 for (int j = 0; j <= bmp.Height - 1; j++)
64 {
65 bmp.SetPixel(i, j, Color.FromArgb(mR[i, j], mG[i, j], mB[i, j]));
66 }
67 }
68 return bmp;
69 }
70
71 /// <summary>
72 /// 对矩阵M进行中值滤波
73 /// </summary>
74 /// <param name="m">矩阵M</param>
75 /// <param name="windowRadius">过滤半径</param>
76 /// <returns>结果矩阵</returns>
77 private byte[,] MedianFilterFunction(byte[,] m, int windowRadius)
78 {
79 int width = m.GetLength(0);
80 int height = m.GetLength(1);
81
82 byte[,] lightArray = new byte[width, height];
83
84 //开始滤波
85 for (int i = 0; i <= width - 1; i++)
86 {
87 for (int j = 0; j <= height - 1; j++)
88 {
89 //得到过滤窗口矩形
90 Rectangle rectWindow = new Rectangle(i - windowRadius, j - windowRadius, 2 * windowRadius + 1, 2 * windowRadius + 1);
91 if (rectWindow.Left < 0) rectWindow.X = 0;
92 if (rectWindow.Top < 0) rectWindow.Y = 0;
93 if (rectWindow.Right > width - 1) rectWindow.Width = width - 1 - rectWindow.Left;
94 if (rectWindow.Bottom > height - 1) rectWindow.Height = height - 1 - rectWindow.Top;
95 //将窗口中的颜色取到列表中
96 List<byte> windowPixelColorList = new List<byte>();
97 for (int oi = rectWindow.Left; oi <= rectWindow.Right - 1; oi++)
98 {
99 for (int oj = rectWindow.Top; oj <= rectWindow.Bottom - 1; oj++)
100 {
101 windowPixelColorList.Add(m[oi, oj]);
102 }
103 }
104 //排序
105 windowPixelColorList.Sort();
106 //取中值
107 byte middleValue = 0;
108 if ((windowRadius * windowRadius) % 2 == 0)
109 {
110 //如果是偶数
111 middleValue = Convert.ToByte((windowPixelColorList[windowPixelColorList.Count / 2] + windowPixelColorList[windowPixelColorList.Count / 2 - 1]) / 2);
112 }
113 else
114 {
115 //如果是奇数
116 middleValue = windowPixelColorList[(windowPixelColorList.Count - 1) / 2];
117 }
118 //设置为中值
119 lightArray[i, j] = middleValue;
120 }
121 }
122 return lightArray;
123 }
MATLAB算法实现的方法
一个均值滤波的例子:
I=imread('cameraman.tif');%读入图像
J=imnoise(I,'salt & pepper',0.02);%给图像添加椒盐噪声
K=imnoise(I,'gaussian',0,0.005);%给图像添加均值为0,方差为0.005的高斯噪声 subplot(231),imshow(I) title('原图像')
subplot(232),imshow(J) title('添加椒盐噪声图像') subplot(233),imshow(K) title('添加高斯噪声图像') subplot(234),imshow(I) title('原图像')
K1=filter2(fspecial('average',3),J)/255;%使用3×3模板均值滤波 subplot(235),imshow(K1) title('3*3椒盐噪声均值滤波')
K2=filter2(fspecial('average',3),K)/255;%使用3×3模板均值滤波 subplot(236),imshow(K2) title('3*3高斯噪声均值滤波')
一个中值滤波的例子:
I=imread('cameraman.tif');%读入图像
J=imnoise(I,'salt & pepper',0.02);%给图像添加椒盐噪声
K=imnoise(I,'gaussian',0,0.005);%给图像添加均值为0,方差为0.005的高斯噪声 subplot(231),imshow(I) title('原图像')
subplot(232),imshow(J) title('添加椒盐噪声图像') subplot(233),imshow(K) title('添加高斯噪声图像') subplot(234),imshow(I) title('原图像')
K1=medfilt2(J,[3,3]);%使用3×3模板中值滤波 subplot(235),imshow(K1) title('3*3椒盐噪声中值滤波')
K2=medfilt2(K,[3,3]);%使用3×3模板中值滤波 subplot(236),imshow(K2) title('3*3高斯噪声中值滤波')
3、均值滤波与中值滤波的对比
I=imread('cameraman.tif');%读入图像
J=imnoise(I,'salt & pepper',0.02);%给图像添加椒盐噪声
K=imnoise(I,'gaussian',0,0.005);%给图像添加均值为0,方差为0.005的高斯噪声 subplot(331),imshow(I) title('原图像')
subplot(332),imshow(J) title('添加椒盐噪声图像') subplot(333),imshow(K) title('添加高斯噪声图像') subplot(334),imshow(I) title('原图像')
K1=filter2(fspecial('average',3),J)/255;%使用3×3模板均值滤波 subplot(335),imshow(K1) title('3*3椒盐噪声均值滤波')
K2=filter2(fspecial('average',3),K)/255;%使用3×3模板均值滤波 subplot(336),imshow(K2) title('3*3高斯噪声均值滤波') subplot(337),imshow(I) title('原图像')
K3=medfilt2(J,[3,3]);%使用3×3模板中值滤波 subplot(338),imshow(K3) title('3*3椒盐噪声中值滤波')
K4=medfilt2(K,[3,3]);%使用3×3模板中值滤波 subplot(339),imshow(K4) title('3*3高斯噪声中值滤波')
展开阅读全文