原理在于维护一个核的直方图数据,核的走向采用折线型,暂时没有对边界处理。

w:图像宽度

h:图像高度

n:中值滤波的核大小(n X n)

margin:设定边界的值,margin要大于n/2,否则程序会出错,这是由于没有对边界处理。

#define LEFT_MOVE 2
void medianFilterFast(unsigned char * data, int w, int h, int n, unsigned char* result, int margin)
{
   //qq:945806570
}
void MedianFilterThread::medianFilterFast(unsigned char * data, int w, int h, int n, unsigned char* result, int margin)
{
    int sx = n / 2;
    int sy = n / 2;
    n = (n / 2) * 2 + 1;
    unsigned char tmp[256];
    int counter = n * n ;
    int m = 0;
    unsigned char val = 0;
    memset(tmp, 0, sizeof(tmp));
    int indexx = margin;
    int marginy = n / 2;
    int indexy = n/2;
    int indexi = 0;
    int changeFlag = 1;
    //initialize kernel
    //memset(result, 0, w * h * sizeof(unsigned char));
    for (int i = -sy; i <= sy; i++)
    {
        for (int j = -sx; j <= sx; j++)
        {
            if (indexy + i >= 0 && indexy + i < h && indexx + j >= 0 && indexx + j < w)
            {
                val = data[(indexy + i) * w + j + indexx];
                tmp[val >> LEFT_MOVE]++;
            }
        }
    }
    counter = (counter >> 1) - 1;
    for (int i = 0; i < 256 >> LEFT_MOVE; i++)
    {
        m += tmp[i];
        if (m >= counter)
        {
            val = (unsigned char)i;
            indexi = i;
            break;
        }
    }
    result[indexx + indexy * w] = val << LEFT_MOVE;
    unsigned char *pd = NULL;
    unsigned char *pa = NULL;
    while (true)
    {
        if (indexy == marginy || indexy == h - marginy - 1)
        {
            changeFlag++;
        }
        //x shift
        if (changeFlag == 1)
        {
            pd = (data + indexx - sx + (indexy) * w);
            indexx++;
            if (indexx == w - margin)
                break;
            pa = (data + indexx + sx + (indexy) * w);
            for (int j = -sx; j <= sx; j++)
            {
                val = *(pd + j * w);
                tmp[val >> LEFT_MOVE]--;
                if (indexi >= (val >> LEFT_MOVE))m--;
                val = *(pa + j * w);
                if (indexi >= (val >> LEFT_MOVE))m++;
                tmp[val >> LEFT_MOVE]++;
            }
            sy = -sy;
        }
        else//y shift
        {
            changeFlag = 0;
            //degree 
            pd = (data + indexx + (indexy - sy)*w);
            //add
            if (sy > 0)indexy++;
            else indexy--;
            pa = (data + indexx + (indexy + sy)*w);
            for (int j = -sx; j <= sx; j++)
            {
                val = *(pd + j);
                if (indexi >= (val >> LEFT_MOVE))m--;
                tmp[val >> LEFT_MOVE]--;
                val = *(pa + j);
                tmp[val >> LEFT_MOVE]++;
                if (indexi >= (val >> LEFT_MOVE))m++;
            }
        }
        if (m < counter)
        {
            while (m < counter)
            {
                m += tmp[++indexi];
            }
            val = (unsigned char)(indexi);
        }
        else if(m >= counter)
        {
            while (m >= counter)
            {
                m -= tmp[indexi--];
            }
            val = (unsigned char)(++indexi);
            m += tmp[indexi];
        }
        result[indexx + indexy * w] = ((val << LEFT_MOVE) < data[indexx + indexy *w] - binary_value) ? 255 : 0;
    }

}