• 快速堆栈模糊算法


    上一篇快速高斯模糊的原作者也有另一个比较快速的模糊算法Stack Blur,字面意思为堆栈模糊。

    源地址为:http://incubator.quasimondo.com/processing/fast_blur_deluxe.php

    这个算法在多个平台上都有实现,安卓以及IOS,JS等。

    processing源码:http://incubator.quasimondo.com/processing/stackblur.pde

    效果图:

    转为C语言实现版本。

    代码如下:
    // Stack Blur v1.0
    //
    // Author: Mario Klingemann <mario@quasimondo.com>
    // http://incubator.quasimondo.com
    // created Feburary 29, 2004
    // C version updated and performance optimization by tntmonks(http://tntmonks.cnblogs.com)
    
    // This is a compromise between Gaussian Blur and Box blur
    // It creates much better looking blurs than Box Blur, but is
    // 7x faster than my Gaussian Blur implementation.
    //
    // I called it Stack Blur because this describes best how this
    // filter works internally: it creates a kind of moving stack
    // of colors whilst scanning through the image. Thereby it
    // just has to add one new block of color to the right side
    // of the stack and remove the leftmost color. The remaining
    // colors on the topmost layer of the stack are either added on
    // or reduced by one, depending on if they are on the right or
    // on the left side of the stack. 
    //
    // If you are using this algorithm in your code please add
    // the following line:
    // 
    // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
    
    #define MAX(x,y) (x>y?x:y) 
    #define MIN(x,y) (x>y?y:x)
    void fastStackBlur(unsigned char* pix, unsigned int w, unsigned int h, unsigned int comp, int radius) {
    	unsigned int wm = w - 1;
    	unsigned int hm = h - 1;
    	unsigned int imageSize = w * h;
    	unsigned int div = radius + radius + 1;
    
    	unsigned char *	rgb = (unsigned char *)malloc(sizeof(unsigned char) * imageSize * 3);
    	unsigned char *	r = rgb;
    	unsigned char *	g = rgb + imageSize;
    	unsigned char *	b = rgb + imageSize * 2;
    	int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
    
    	unsigned int *vmin = (unsigned int *)malloc(MAX(w, h) * sizeof(unsigned int));
    
    	int divsum = (div + 1) >> 1;
    	divsum *= divsum;
    	int *dv = (int *)malloc(256 * divsum * sizeof(int));
    	for (i = 0; i < 256 * divsum; i++) {
    		dv[i] = (i / divsum);
    	}
    
    	yw = yi = 0;
    
    	int(*stack)[3] = (int(*)[3])malloc(div * 3 * sizeof(int));
    	unsigned int stackpointer;
    	unsigned int stackstart;
    	int *sir;
    	int rbs;
    	int r1 = radius + 1;
    	int routsum, goutsum, boutsum;
    	int rinsum, ginsum, binsum;
    
    	for (y = 0; y < h; y++) {
    		rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
    		for (i = -radius; i <= radius; i++) {
    			p = yi + (MIN(wm, MAX(i, 0)));
    			sir = stack[i + radius];
    			sir[0] = pix[(p*comp)];
    			sir[1] = pix[(p*comp) + 1];
    			sir[2] = pix[(p*comp) + 2];
    
    			rbs = r1 - abs(i);
    			rsum += sir[0] * rbs;
    			gsum += sir[1] * rbs;
    			bsum += sir[2] * rbs;
    			if (i > 0) {
    				rinsum += sir[0];
    				ginsum += sir[1];
    				binsum += sir[2];
    			}
    			else {
    				routsum += sir[0];
    				goutsum += sir[1];
    				boutsum += sir[2];
    			}
    		}
    		stackpointer = radius;
    
    		for (x = 0; x < w; x++) {
    
    			r[yi] = dv[rsum];
    			g[yi] = dv[gsum];
    			b[yi] = dv[bsum];
    
    			rsum -= routsum;
    			gsum -= goutsum;
    			bsum -= boutsum;
    
    			stackstart = stackpointer - radius + div;
    			sir = stack[stackstart % div];
    
    			routsum -= sir[0];
    			goutsum -= sir[1];
    			boutsum -= sir[2];
    
    			if (y == 0) {
    				vmin[x] = MIN(x + radius + 1, wm);
    			}
    			p = yw + vmin[x];
    
    
    			sir[0] = pix[(p*comp)];
    			sir[1] = pix[(p*comp) + 1];
    			sir[2] = pix[(p*comp) + 2];
    			rinsum += sir[0];
    			ginsum += sir[1];
    			binsum += sir[2];
    
    			rsum += rinsum;
    			gsum += ginsum;
    			bsum += binsum;
    
    			stackpointer = (stackpointer + 1) % div;
    			sir = stack[(stackpointer) % div];
    
    			routsum += sir[0];
    			goutsum += sir[1];
    			boutsum += sir[2];
    
    			rinsum -= sir[0];
    			ginsum -= sir[1];
    			binsum -= sir[2];
    
    			yi++;
    		}
    		yw += w;
    	}
    	for (x = 0; x < w; x++) {
    		rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
    		yp = -radius * w;
    		for (i = -radius; i <= radius; i++) {
    			yi = MAX(0, yp) + x;
    
    			sir = stack[i + radius];
    
    			sir[0] = r[yi];
    			sir[1] = g[yi];
    			sir[2] = b[yi];
    
    			rbs = r1 - abs(i);
    
    			rsum += r[yi] * rbs;
    			gsum += g[yi] * rbs;
    			bsum += b[yi] * rbs;
    
    			if (i > 0) {
    				rinsum += sir[0];
    				ginsum += sir[1];
    				binsum += sir[2];
    			}
    			else {
    				routsum += sir[0];
    				goutsum += sir[1];
    				boutsum += sir[2];
    			}
    
    			if (i < hm) {
    				yp += w;
    			}
    		}
    		yi = x;
    		stackpointer = radius;
    		for (y = 0; y < h; y++) {
    
    			pix[(yi*comp)] = dv[rsum];
    			pix[(yi*comp) + 1] = dv[gsum];
    			pix[(yi*comp) + 2] = dv[bsum];
    			rsum -= routsum;
    			gsum -= goutsum;
    			bsum -= boutsum;
    
    			stackstart = stackpointer - radius + div;
    			sir = stack[stackstart % div];
    
    			routsum -= sir[0];
    			goutsum -= sir[1];
    			boutsum -= sir[2];
    
    			if (x == 0) {
    				vmin[y] = MIN(y + r1, hm) * w;
    			}
    			p = x + vmin[y];
    
    			sir[0] = r[p];
    			sir[1] = g[p];
    			sir[2] = b[p];
    
    			rinsum += sir[0];
    			ginsum += sir[1];
    			binsum += sir[2];
    
    			rsum += rinsum;
    			gsum += ginsum;
    			bsum += binsum;
    
    			stackpointer = (stackpointer + 1) % div;
    			sir = stack[stackpointer];
    
    			routsum += sir[0];
    			goutsum += sir[1];
    			boutsum += sir[2];
    
    			rinsum -= sir[0];
    			ginsum -= sir[1];
    			binsum -= sir[2];
    
    			yi += w;
    		}
    	}
    
    	free(rgb);
    	free(vmin);
    	free(dv);
    	free(stack);
    }
    

      在博主机子上测试一张5000x3000的图像,模糊半径为10的情况下,耗时1s.

  • 相关阅读:
    手机管理中的应用【6】——电源管理篇
    NYOJ 14 场地安排(它可以被视为一个经典问题)
    YUV格式转换RGB(基于opencv)
    互联网金融进入洗礼阶段,控制风险是制胜之道
    Uva 409-Excuses, Excuses!(串)
    MATLAB新手教程
    IE无法打开internet网站已终止操作的解决的方法
    关于SetCapture() 和 ReleaseCapture()的使用方法
    wxWidgets刚開始学习的人导引(2)——下载、安装wxWidgets
    MyReport报表引擎2.7.6.7新功能
  • 原文地址:https://www.cnblogs.com/cpuimage/p/4899724.html
Copyright © 2020-2023  润新知