ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

快速高斯模糊[剪裁版]

2022-05-19 11:34:57  阅读:164  来源: 互联网

标签:模糊 高斯 bottom float w2 b2 b3 剪裁 w1


高斯模糊函数的升级版本,带剪裁区域。

函数check_rect()是处理剪裁区域矩形。如果不打算剪裁,只需要设置left, top, right, bottom都为0就可以了;另外位图的存储格式是上下反转的,如果正常剪裁的话,只需要设置bottom为 -bottom即可。

 

bool check_rect(int width, int height, int& left, int& top, int& right, int& bottom)
{
    if(!left && !top && !right && !bottom)
    {//不进行剪裁
        left   = 0;
        top    = 0;
        right  = width;
        bottom = height;
        return true;
    }
 
    if(!(right-left) || !(bottom-top))
    {//0面积矩形
        return false;
    }
 
    if(bottom <= 0)
    {//反转上下
        int h  = -bottom - top;
        bottom = height - top;
        top    = bottom - h;
    }
    if(right <= 0)
    {//反转左右
        int w = -right - left;
        right = width - left;
        left  = right - w;
    }
 
    left   = max(left,   0);
    top    = max(top,    0);
    right  = min(right,  width);
    bottom = min(bottom, height);
 
    return true;
}
 
 
//快速高斯模糊函数,by sdragonx 2014-08-01
int gauss_blur(
    byte_t* image,    //位图数据
    int linebytes,    //位图行字节数,BMP数据在windows中是4字节对齐的。否则在处理非二次幂的图像时会有偏差
    int width,        //位图宽度
    int height,        //位图高度
    int cbyte,        //颜色通道数量
    int left,        //滤镜剪裁区域,都为0是不剪裁
    int top,
    int right,
    int bottom,
    float sigma        //高斯系数
    )
{
    int x = 0, y = 0, n = 0;
    int channel = 0;
    int srcline = 0, dstline = 0;
    int channelsize = 0;
    int bufsize = 0;
    float *w1 = NULL, *w2 = NULL, *imgbuf = NULL;
    int time = 0;
 
    #if defined(_INC_WINDOWS)
        time = GetTickCount();
    #elif defined(_CLOCK_T)
        time  = clock();
    #endif
 
    if(!check_rect(width, height, left, top, right, bottom))
    {
        return -1;
    }
 
    //剪裁宽度和高度
    int rc_width  = right - left;
    int rc_height = bottom - top;
 
    channelsize = rc_width*rc_height;
    bufsize     = rc_width > rc_height ? rc_width + 4 : rc_height + 4;
 
    w1 = (float*)malloc(bufsize * sizeof(float));
    if(!w1)
    {
        return -1;
    }
    w2 = (float*)malloc(bufsize * sizeof(float));
    if(!w2)
    {
        free(w1);
        return -1;
    }
    imgbuf = (float*)malloc(channelsize * sizeof(float));
    if(!imgbuf)
    {
        free(w1);
        free(w2);
        return -1;
    }
 
//----------------计算高斯核---------------------------------------//
    float q  = 0;
    float q2 = 0, q3 = 0;
    float b0 = 0, b1 = 0, b2 = 0, b3 = 0;
    float B  = 0;
 
    if (sigma >= 2.5f)
    {
        q = 0.98711f * sigma - 0.96330f;
    }
    else if ((sigma >= 0.5f) && (sigma < 2.5f))
    {
        q = 3.97156f - 4.14554f * (float) sqrt (1.0f - 0.26891f * sigma);
    }
    else
    {
        q = 0.1147705018520355224609375f;
    }
 
    q2 = q * q;
    q3 = q * q2;
    b0 = (1.57825f+ (2.44413f*q)+(1.4281f *q2)+(0.422205f*q3));
    b1 = (         (2.44413f*q)+(2.85619f*q2)+(1.26661f* q3));
    b2 = (                     -((1.4281f*q2)+(1.26661f* q3)));
    b3 = (                                    (0.422205f*q3));
    B = 1.0f-((b1+b2+b3)/b0);
 
    b1 /= b0;
    b2 /= b0;
    b3 /= b0;
//----------------计算高斯核结束---------------------------------------//
 
    // 处理图像的多个通道
    for (channel = 0; channel < cbyte; ++channel)
    {
 
        // 获取一个通道的所有像素值,并预处理
        srcline = top*linebytes + left*cbyte + channel;
        dstline = 0;
        for(y=0; y<rc_height; ++y, srcline+=linebytes, dstline+=rc_width)
        {
            for(x=0, n=0; x<rc_width; ++x, n+=cbyte)
            {
                (imgbuf+dstline)[x] = float((image+srcline)[n]);
            }
        }
 
        for (int x=0; x<rc_width; ++x)
        {//横向处理
 
            w1[0] = (imgbuf + x)[0];
            w1[1] = (imgbuf + x)[0];
            w1[2] = (imgbuf + x)[0];
 
            for (y=0, n=0; y<rc_height; ++y, n+=rc_width)
            {
                w1[y+3] = B*(imgbuf + x)[n] + (b1*w1[y+2] + b2*w1[y+1] + b3*w1[y+0]);
            }
 
            w2[rc_height+0]= w1[rc_height+2];
            w2[rc_height+1]= w1[rc_height+1];
            w2[rc_height+2]= w1[rc_height+0];
 
            for (int y=rc_height-1, n=y*rc_width; y>=0; --y, n-=rc_width)
            {
                (imgbuf + x)[n] = w2[y] = B*w1[y+3] + (b1*w2[y+1] + b2*w2[y+2] + b3*w2[y+3]);
            }
        }//横向处理
 
        srcline = 0;
        dstline = top*linebytes + left*cbyte + channel;
        for (y=0; y<rc_height; ++y, srcline+=rc_width, dstline+=linebytes)
        {//纵向处理
 
            //取当前行数据
            w1[0] = (imgbuf + srcline)[0];
            w1[1] = (imgbuf + srcline)[0];
            w1[2] = (imgbuf + srcline)[0];
 
            //正方向横向处理3个点的数据
            for (x=0; x<rc_width; ++x)
            {
                w1[x+3] = B*(imgbuf + srcline)[x] + (b1*w1[x+2] + b2*w1[x+1] + b3*w1[x+0]);
            }
 
            w2[rc_width+0]= w1[rc_width+2];
            w2[rc_width+1]= w1[rc_width+1];
            w2[rc_width+2]= w1[rc_width+0];
 
            //反方向处理
            for (x=rc_width-1, n=x*cbyte; x>=0; --x, n-=cbyte)
            {
                //(imgbuf + srcline)[x] = w2[x] = B*w1[x+3] + (b1*w2[x+1] + b2*w2[x+2] + b3*w2[x+3]);
                (image + dstline)[n] = w2[x] = B*w1[x+3] + (b1*w2[x+1] + b2*w2[x+2] + b3*w2[x+3]);
            }
        }//纵向处理
 
        /*
        //存储处理完毕的通道
        for(int y=0; y<rc_height; ++y)
        {
            int dstline = (y+top)*linebytes + left*cbyte;
            int srcline = y*rc_width;
            for (int x=0, n=channel; x<rc_width; ++x, n+=cbyte)
            {
                (image + dstline)[n] = (imgbuf + srcline)[x];
                    //byte_edge((imgbuf + srcline)[x]);
            }
        }//存储循环
        //*/
    }//通道循环
 
    free (w1);
    w1 = NULL;
    free (w2);
    w2 = NULL;
    free(imgbuf);
    imgbuf = NULL;
 
    #if defined(_INC_WINDOWS)
        return GetTickCount() - time;
    #elif defined(_CLOCK_T)
        return clock() - time;
    #else
        return 0;
    #endif
}
 
int gauss_blur(
    byte_t* image,    //位图数据
    int linebytes,    //位图行字节数,BMP数据在windows中是4字节对齐的。否则在处理非二次幂的图像时会有偏差
    int width,    //位图宽度
    int height,    //位图高度
    int cbyte,    //颜色通道数量
    float sigma    //高斯系数
    )
{
    return gauss_blur(image, linebytes, width, height, cbyte, 0, 0, 0, 0, sigma);
}

 

一下是剪裁效果图:

 

文章发布于 2014-08-01 14:53:35 CSDN,现转博客园。

标签:模糊,高斯,bottom,float,w2,b2,b3,剪裁,w1
来源: https://www.cnblogs.com/sdragonx/p/16287852.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有