数字图像处理(四)——均值滤波
上次提到产生高斯噪声的算法,我们知道,椒盐噪声是可以通过中值滤波来修复的,高斯噪声也可以通过均值滤波来还原。
顾名思义,均值滤波也是构建一个 n*n 的模板,然后取其平均值来替代模板中间的值。这样做出的效果明显不如用中值滤波修复椒盐噪声的效果好,不过当 n 取很大值的时候,图片看起来像是高斯模糊,不知道是不是一个原理……
看效果,n=3 时:
n=11 时:
算法更加简单,有以前的基础不成问题:
BmpPixmap &
BmpPixmap::mean_filter (int n)
{
assert (n >= 3 && n % 2);
int ii, jj, nn, sum [3];
BmpPixmap *temp = new BmpPixmap (*this);
for (i = n / 2; i < height - n / 2; i++) {
for (j = n / 2; j < width - n / 2; j++) {
for (nn = 0; nn < 3; nn++) {
sum [nn] = 0;
}
/*-----------------------------------------------------------------------------
* Calculate the average of the model.
*-----------------------------------------------------------------------------*/
for (ii = i - n / 2, nn = 0; ii <= i + n / 2; ii++) {
for (jj = j - n / 2; jj <= j + n / 2; jj++, nn++) {
sum [0] += pdata [ii][jj]->get_blue ();
sum [1] += pdata [ii][jj]->get_green ();
sum [2] += pdata [ii][jj]->get_red ();
}
}
temp->pdata [i][j]->set (sum [0] / (n * n), sum [1] / (n * n), sum [2] / (n * n));
}
}
return *temp;
} /* ----- end of method BmpPixmap::mean_filter ----- */
数字图像处理(三)——高斯噪声
与椒盐噪声相似,高斯噪声(gauss noise)也是数字图像的一个常见噪声,产生该噪声的算法也很简单。
上次说过,椒盐噪声是出现在随机位置、噪点深度基本固定的噪声,高斯噪声与其相反,是几乎每个点上都出现噪声、噪点深度随机的噪声。
该噪声效果如下:
这个算法比较简单,需要注意,颜色值不要超出范围(0-255),不然效果很可怕……
代码如下:
BmpPixmap &
BmpPixmap::gauss (int level)
{
assert (level >= 0);
BmpPixmap *temp = new BmpPixmap (*this);
int k, rand_temp, pixel [3];
/*-----------------------------------------------------------------------------
* Init the random seed with time.
*-----------------------------------------------------------------------------*/
srand (time (NULL));
/*-----------------------------------------------------------------------------
* Salt & Pepper.
*-----------------------------------------------------------------------------*/
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
rand_temp = rand () % level - level / 2;
pixel [0] = temp->pdata [i][j]->get_blue () + rand_temp;
pixel [1] = temp->pdata [i][j]->get_green () + rand_temp;
pixel [2] = temp->pdata [i][j]->get_red () + rand_temp;
for (k = 0; k < 3; k++) {
if (pixel [k] < 0) {
pixel [k] = 0;
} else if (pixel [k] > 255) {
pixel [k] = 255;
}
}
temp->pdata [i][j]->set (pixel [0], pixel [1], pixel [2]);
}
}
return *temp;
} /* ----- end of method BmpPixmap::gauss ----- */
数字图像处理(二)——中值滤波
中值滤波(median filter)是一种有效消除椒盐噪声的算法。
基本原理是,对图像中所有点进行遍历,对于每个点,取以其为中心的 n * n 的矩形区域,对矩形区域中点的灰度值进行排序,取其中间值替换当前点。
这样,如果这个点灰度值与周围点相差较大的话,就可以将其平滑化。
当然,这里要求 n 是个大于 1 的奇数。
在这里,我对算法进行了优化,使只有当前点是矩形区域灰度值的最大或者最小值的时候才进行替换,这样效果好了很多。
原始图像:
椒盐噪声:
中值滤波后:
可以看到,图像损失很小,只有边缘处有小的细节损失。同时,由于所加的噪点比较密集,少数地方仍然有噪点,这是因为矩形区域噪点太多,以至于中值本身也是个噪点了。
源代码:
BmpPixmap & BmpPixmap::median_filter (int n) { assert (n >= 3 && n % 2); int ii, jj, nn; Byte model [3][n * n]; BmpPixmap *temp = new BmpPixmap (*this); for (i = n / 2; i < height - n / 2; i++) { for (j = n / 2; j < width - n / 2; j++) { /*----------------------------------------------------------------------------- * Put n*n pixels around current pixels to the model. *-----------------------------------------------------------------------------*/ for (ii = i - n / 2, nn = 0; ii <= i + n / 2; ii++) { for (jj = j - n / 2; jj <= j + n / 2; jj++, nn++) { model [0][nn] = pdata [ii][jj]->get_blue (); model [1][nn] = pdata [ii][jj]->get_green (); model [2][nn] = pdata [ii][jj]->get_red (); } } /*----------------------------------------------------------------------------- * Sort the model. *-----------------------------------------------------------------------------*/ qsort (model [0], nn, sizeof (Byte), cmp_Byte); qsort (model [1], nn, sizeof (Byte), cmp_Byte); qsort (model [2], nn, sizeof (Byte), cmp_Byte); if (pdata [i][j]->get_blue () == model [0][nn - 1] || pdata [i][j]->get_blue () == model [0][0] || pdata [i][j]->get_green () == model [1][nn - 1] || pdata [i][j]->get_green () == model [1][0] || pdata [i][j]->get_red () == model [2][nn - 1] || pdata [i][j]->get_red () == model [2][0]) { temp->pdata [i][j]->set (model [0][nn / 2], model [1][nn / 2], model [2][nn / 2]); } } } return *temp; } /* ----- end of method BmpPixmap::median_filter ----- */
数字图像处理(一)——椒盐噪声
椒盐噪声(salt & pepper noise)是数字图像的一个常见噪声,产生该噪声的算法也比较简单。
椒盐,按我的理解,椒就是黑,盐就是白,椒盐噪声就是在图像上随机出现黑色白色的像素。
那么传入两个参数,分别为黑白像素在图像上所占比例,就可以对图像进行修改。
我们可以使用 srand 函数,根据 time 产生一个随机种子(以免每次随机的结果相同),然后使用 rand 函数产生随机数,rand 产生的随机数是 0 到 RAND_MAX 之间的整数,可以通过使用 double (rand ()) / RAND_MAX 产生一个 0 到 1 之间的浮点型。
这样,当这个随机数小于 pepper 时,就把该点调黑,大于 1 - salt 时,就把该点调白,就可以产生随机的椒盐噪声了。
效果如图:
源代码:
#include #include #include "bmp_pixmap.h" /* *-------------------------------------------------------------------------------------- * Class: BmpPixmap * Method: salt_pepper * Description: Add salt and pepper noise to the pixmap. *-------------------------------------------------------------------------------------- */ void BmpPixmap::salt_pepper (double salt, double pepper) { double temp; /*----------------------------------------------------------------------------- * Salt & Pepper should be between 0 and 1. *-----------------------------------------------------------------------------*/ salt -= int (salt); pepper -= int (pepper); /*----------------------------------------------------------------------------- * Init the random seed with time. *-----------------------------------------------------------------------------*/ srand (time (NULL)); /*----------------------------------------------------------------------------- * Salt & Pepper. *-----------------------------------------------------------------------------*/ for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { temp = double (rand ()) / RAND_MAX; if (temp > 1 - salt) { pdata [i][j]->set (255, 255, 255); } else if (temp < pepper) { pdata [i][j]->set (0, 0, 0); } } } return ; } /* ----- end of method BmpPixmap::salt_pepper ----- */
试试用 C++ 实现数字图像处理
看到同寝的在学数字图像处理,好像很好玩啊……
正好正在学 C++,决定用 C++ 实现一下(他原来用的是 C、C++ 混编,代码惨不忍睹……)。
C++ 真的是个很麻烦的东西啊,定义一个类要费那么长时间,读写文件也没有 C 那么轻松,真怀疑它的用处了……
还是 Python 最简洁,C 我也很喜欢,真不明白那些自己用 C++ 写程序的人,怎么受得了这种笨重的搭建速度……现在做 C++ 作业,一个没什么用的小程序都要写一下午……
不说了,代码在 http://github.com/iven/dip/
写了个提取手机屏幕数据的程序 fb2bmp
我的 E680i 已经买了三年了,一直想要研究它,却苦于技术不足。网上的手机程序,大多是二进制包,想要学习也没有办法。
以前在 Windows 下,甚至可以通过一个叫做 MotoVision 的程序,把手机当摄像头用,可惜根本找不到源代码……
昨天查了查资料,发现小 i 的屏幕色深是 16 位的,也就是每个像素点的颜色值存储为两个字节,那么整个屏幕的数据就是 320*240*2/1024=150 KB,每个像素点分为 RGB 三色,存储方法为 RRRRRGGG GGGBBBBB (16 位 565 方式),那么根据最近学的一点数字图象处理的知识,很容易就可以把它转换成 BMP 格式。
小 i 的操作系统是 Linux,屏幕设备文件是 /dev/fb0,也就是 framebuffer,这也是我把程序叫做 fb2bmp 的原因。只要通过 telnet 把 /dev/fb0 拷贝到电脑上,得到的就是拷贝瞬间的屏幕数据。
fb2bmp,可以将 fb0 的数据转换成 16bit 和 24bit 的 BMP 文件,16bit 比较好办,加上个文件头即可,需要注意的是要加上 3 个 DWORD 类型的掩码,表示 RGB 三种颜色分别占哪几位。24bit 则需要对数据进行移位,然后再加上文件头。
项目已经放在 http://github.com/iven/e680_fb2bmp/ ,有兴趣可以去看看。
补上图:








