1、作业:对lean.raw文件,采用中值滤波和均值滤波,完成图象去噪 中值滤波: /************************************************************************* * * 函数名称: * MedianFilter() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight
2、 - 源图像高度(象素数) * int iFilterH - 滤波器的高度 * int iFilterW - 滤波器的宽度 * int iFilterMX - 滤波器的中心元素X坐标 * int iFilterMY - 滤波器的中心元素Y坐标 * * 返回值: * BOOL - 成功返回TRUE,否则返回FALSE。 * * 说明: *
3、 该函数对DIB图像进行中值滤波。 * ************************************************************************/ BOOL WINAPI MedianFilter(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, int iFilterH, int iFilterW, int iFilterMX, int iFilterMY) {
4、 // 指向源图像的指针 unsigned char* lpSrc; // 指向要复制区域的指针 unsigned char* lpDst; // 指向复制图像的指针 LPSTR lpNewDIBBits; HLOCAL hNewDIBBits; // 指向滤波器数组的指针 unsigned char * aValue; HLOCAL hArray; // 循环变量 LONG i; LONG j; LONG k; LONG
5、 l; // 图像每行的字节数 LONG lLineBytes; // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(lWidth * 8); // 暂时分配内存,以保存新图像 hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); // 判断是否内存分配失败 if (hNewDIBBits == NULL) { // 分配内存失败 return FALSE
6、 } // 锁定内存 lpNewDIBBits = (char * )LocalLock(hNewDIBBits); // 初始化图像为原始图像 memcpy(lpNewDIBBits, lpDIBBits, lLineBytes * lHeight); // 暂时分配内存,以保存滤波器数组 hArray = LocalAlloc(LHND, iFilterH * iFilterW); // 判断是否内存分配失败 if (hArray == NULL) {
7、 // 释放内存 LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); // 分配内存失败 return FALSE; } // 锁定内存 aValue = (unsigned char * )LocalLock(hArray); // 开始中值滤波 // 行(除去边缘几行) for(i = iFilterMY; i < lHeight - iFilterH + iFilter
8、MY + 1; i++) { // 列(除去边缘几列) for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++) { // 指向新DIB第i行,第j个象素的指针 lpDst = (unsigned char*)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j;
9、 // 读取滤波器数组 for (k = 0; k < iFilterH; k++) { for (l = 0; l < iFilterW; l++) { // 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针 lpSrc = (unsigned char*)lpDIBBits + lL
10、ineBytes * (lHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l; // 保存象素值 aValue[k * iFilterW + l] = *lpSrc; } } // 获取中值 * lpDst = GetMedianNum(aValue, iFilt
11、erH * iFilterW); } } // 复制变换后的图像 memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); // 释放内存 LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); LocalUnlock(hArray); LocalFree(hArray); // 返回 return TRUE; } 均值滤波:
12、/************************************************************************* * * 函数名称: * GetMedianNum() * * 参数: * unsigned char * bpArray - 指向要获取中值的数组指针 * int iFilterLen - 数组长度 * * 返回值: * unsigned char - 返回指定
13、数组的中值。 * * 说明: * 该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。 * ************************************************************************/ unsigned char WINAPI GetMedianNum(unsigned char * bArray, int iFilterLen) { // 循环变量 int i; int j; // 中间变量 unsign
14、ed 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];
15、 bArray[i] = bArray[i + 1]; bArray[i + 1] = bTemp; } } } // 计算中值 if ((iFilterLen & 1) > 0) { // 数组有奇数个元素,返回中间一个元素 bTemp = bArray[(iFilterLen + 1) / 2]; } else { // 数组有偶数个元素,返回中间两个元素平均值
16、
bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2; }
// 返回中值 return bTemp; }
///
17、p">是否是彩色位图 13 /// 过滤半径 14 public Bitmap ColorfulBitmapMedianFilterFunction(Bitmap srcBmp, int windowRadius, bool IsColorfulBitmap) 15 { 16 if (windowRadius < 1) 17 { 18 throw
18、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
19、 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
20、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
21、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 = MedianFilterFunctio
22、n(mR, windowRadius); 51 if (IsColorfulBitmap) 52 { 53 mG = MedianFilterFunction(mG, windowRadius); 54 mB = MedianFilterFunction(mB, windowRadius); 55 } 56 else 57 { 58
23、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[
24、i, j], mB[i, j]));
66 }
67 }
68 return bmp;
69 }
70
71 ///
25、aram>
76 ///
26、eight]; 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
27、 - 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 = widt
28、h - 1 - rectWindow.Left;
94 if (rectWindow.Bottom > height - 1) rectWindow.Height = height - 1 - rectWindow.Top;
95 //将窗口中的颜色取到列表中
96 List
29、indow.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
30、 } 103 } 104 //排序 105 windowPixelColorList.Sort(); 106 //取中值 107 byte middleValue = 0; 108 if ((windowRadius * windowRadius) % 2 == 0) 109 { 11
31、0 //如果是偶数 111 middleValue = Convert.ToByte((windowPixelColorList[windowPixelColorList.Count / 2] + windowPixelColorList[windowPixelColorList.Count / 2 - 1]) / 2); 112 } 113 else 114 {
32、 115 //如果是奇数 116 middleValue = windowPixelColorList[(windowPixelColorList.Count - 1) / 2]; 117 } 118 //设置为中值 119 lightArray[i, j] = middleValue; 120 } 121
33、 } 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
34、),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高斯噪声
35、均值滤波') 一个中值滤波的例子: 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)
36、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=imno
37、ise(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椒盐噪声
38、均值滤波') 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高斯噪声中值滤波')






