注:1.局部区域边界为红色R=255,G=B=0;
2.模糊取值为滤波内像素值均值;
3.通过拾取局部区域内部一点,对整个局部区域进行模糊;
4.使用了CDib类指向图像内存;
定义变量:
int radiusX,radiusY;//模糊滤波半径
typedef struct{
int Height;
int Width;
}Seed;//种子栈
int iCurrentPixelx,iCurrentPixely;//从当前种子栈中取出的点
Size ImageSize;//图像的大小
int colcount[];//存储列上像素之和
int colsum;//滤波的像素和
算法思想:
线扫面法+滤波移动法
线扫描法算法:
(1)初始化一个空的栈用于存放种子点,将种子点(x, y)入栈;
(2)判断栈是否为空,如果栈为空则结束算法,否则取出栈顶元素作为当前扫描线的种子点(x, y),y是当前的扫描线;
(3)从种子点(x, y)出发,沿当前扫描线向左、右两个方向填充,直到边界。分别标记区段的左、右端点坐标为xLeft和xRight;
(4)分别检查与当前扫描线相邻的y - 1和y + 1两条扫描线在区间[xLeft, xRight]中的像素,从xLeft开始向xRight方向搜索,若存在非边界且未填充的像素点,则找出这些相邻的像素点中最右边的一个,并将其作为种子点压入栈中,然后返回第(2)步;
滤波移动算法:读取以P0(x0,y0)点为中心,读取图像上 0 < i < ImageSize.x, y0 - radiusY < j < y0+radiusY上点的像素,将像素列之和存储到数组colcount[]中,计算[p0-radiusX,p0+radiusX]上每一列的像素之和,保存在colsum中,则colsum是指定的滤波上所有像素之和,模糊后的p0像素值为colsum/(radiusX*radiusY);
局部区域中其他点的模糊算法为:按行模糊,由线扫描法的(3)可知填充是按行进行的,故模糊也可按行进行,向左填充(模糊)时,新滤波模板=旧滤波模板+模板左侧列像素和-模板右侧列像素和;向右填充(模糊)时,新模板=旧模板+右侧列像素和-左侧列像素和,遇到边界则填充结束。
扫描线算法步骤(4)则是找出新的边界点,将新边界点放入栈顶,一般情况下,新边界点与旧边界点在y值上仅差1,故在模糊新的一行像素点时可仍充分利用旧像素模板,具体算法为:若向上填充:for(int i=0;i< ImageSize.x ;i ++)
{
colcount[i]=colcount[i]+p(i,j-radiuxY-1)-p(i,i+radiusY);//加上上一行各个点像素值,减去下一行各个点像素值;
}
向下填充:
for(int i=0;i< ImageSize.x ;i ++)
{
colcount[i]=colcount[i]-p(i,j-radiuxY-1)+p(i,i+radiusY);//加上上一行各个点像素值,减去下一行各个点像素值;
}
使用上下模板移动的前提是下一个扫描的种子点和上一个扫描的种子点y值差1;否则需要对下一个种子点的0 < i < ImageSize.x, y0 - radiusY < j < y0+radiusY 范围上重新去读像素,重复上一过程。
。。。。。。未完待续