快速高速模糊算法

刚才发现一份快速高速模糊的实现。

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

作者信息为: Fast Gaussian Blur v1.3
 by Mario Klingemann <http://incubator.quasimondo.com>
processing源码: http://incubator.quasimondo.com/processing/fastblur.pde效果图:


转为C语言实现版本。

代码如下:
// Fast Gaussian Blur v1.3
// by Mario Klingemann <http://incubator.quasimondo.com>
// C version updated and performance optimization by tntmonks(http://tntmonks.cnblogs.com)
// One of my first steps with Processing. I am a fan
// of blurring. Especially as you can use blurred images
// as a base for other effects. So this is something I
// might get back to in later experiments.
//
// What you see is an attempt to implement a Gaussian Blur algorithm
// which is exact but fast. I think that this one should be
// relatively fast because it uses a special trick by first
// making a horizontal blur on the original image and afterwards
// making a vertical blur on the pre-processed image. This
// is a mathematical correct thing to do and reduces the
// calculation a lot.
//
// In order to avoid the overhead of function calls I unrolled
// the whole convolution routine in one method. This may not
// look nice, but brings a huge performance boost.
//
//
// v1.1: I replaced some multiplications by additions
//       and added aome minor pre-caclulations.
//       Also add correct rounding for float->int conversion
//
// v1.2: I completely got rid of all floating point calculations
//       and speeded up the whole process by using a
//       precalculated multiplication table. Unfortunately
//       a precalculated division table was becoming too
//       huge. But maybe there is some way to even speed
//       up the divisions.
//
// v1.3: Fixed a bug that caused blurs that start at y>0
//	 to go wrong. Thanks to Jeroen Schellekens for
//       finding it!

//申请二维数组
template <typename T>
T** newArray2D(unsigned int width, unsigned int height)
{
	unsigned int size = sizeof(T);
	unsigned int point_size = sizeof(T*);

	T **arr = (T **)malloc(point_size * width + size * width * height);
	memset(arr, 0, point_size * width + size * width * height);
	if (arr != NULL)
	{
		T *head = (T*)((int)arr + point_size * width);
		for (unsigned int i = 0; i < width; ++i)
		{
			arr[i] = (T*)((int)head + i * height * size);
			for (unsigned int j = 0; j < height; ++j)
				new (&arr[i][j]) T;
		}
	}
	return (T**)arr;
}
//释放二维数组
template <typename T>
void deleteArray2D(T **arr, unsigned int width, unsigned int height)
{
	for (unsigned int i = 0; i < width; ++i)
		for (unsigned int j = 0; j < height; ++j)
			arr[i][j].~T();
	if (arr != NULL)
		free((void**)arr);
} 

void GaussianBlur(unsigned char* img, unsigned  int x, unsigned int y, unsigned int w, unsigned int h,unsigned int comp, unsigned int radius)
{
	unsigned int i, j;
	radius = min(max(1, radius), 248);

	unsigned int kernelSize = 1 + radius * 2;

	unsigned int* kernel = (unsigned int*)malloc(kernelSize* sizeof(unsigned int));
	memset(kernel, 0, kernelSize* sizeof(unsigned int));
	unsigned int** mult = newArray2D<unsigned int>(kernelSize, 256);

	unsigned	int sum = 0;
	for (i = 1; i < radius; i++){
		unsigned int szi = radius - i;
		kernel[radius + i] = kernel[szi] = szi*szi;
		sum += kernel[szi] + kernel[szi];
		for (j = 0; j < 256; j++){
			mult[radius + i][j] = mult[szi][j] = kernel[szi] * j;
		}
	}
	kernel[radius] = radius*radius;
	sum += kernel[radius];
	for (j = 0; j < 256; j++){
		mult[radius][j] = kernel[radius] * j;
	}

	unsigned int   cr, cg, cb;
	unsigned int   xl, yl, yi, ym, riw;
	int   read, ri;
	unsigned	int imgWidth =  w;
	unsigned	int imgHeight =  h;
	unsigned	int imageSize = imgWidth*imgHeight;
	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;
	unsigned char *	rgb2 = (unsigned char *)malloc(sizeof(unsigned char) * imageSize * 3);
	unsigned char *	r2 = rgb2;
	unsigned char *	g2 = rgb2 + imageSize;
	unsigned char *	b2 = rgb2 + imageSize * 2;
	for (size_t yh = 0; yh < imgHeight; ++yh) {
		for (size_t xw = 0; xw < imgWidth; ++xw) {
			unsigned int n = xw + yh* imgWidth;
			unsigned int p = n*comp;
			r[n] = img[p];
			g[n] = img[p + 1];
			b[n] = img[p + 2];
		}
	}
	unsigned int Zero = 0;
	//max(0, x);
	x = x ^ ((x ^ Zero) & -(x < Zero));
	//max(0, y);
	y = Zero ^ ((Zero ^ y) & -(Zero < y)); 

	w = x + w - max(0, (x + w) - imgWidth);
	h = y + h - max(0, (y + h) - imgHeight);
	yi = y*imgWidth;

	for (yl = y; yl < h; yl++){
		for (xl = x; xl < w; xl++){
			cb = cg = cr = sum = 0;
			ri = xl - radius;
			for (i = 0; i < kernelSize; i++){
				read = ri + i;
			 	if (read >= x && read < w)
				{
					read += yi;
					cr += mult[i][r[read]];
					cg += mult[i][g[read]];
					cb += mult[i][b[read]];
					sum += kernel[i];
				}
			}
			ri = yi + xl;
			r2[ri] = cr / sum;
			g2[ri] = cg / sum;
			b2[ri] = cb / sum;
		}
		yi += imgWidth;
	}
	yi = y*imgWidth;

	for (yl = y; yl < h; yl++){
		ym = yl - radius;
		riw = ym*imgWidth;
		for (xl = x; xl < w; xl++){
			cb = cg = cr = sum = 0;
			ri = ym;
			read = xl + riw;
			for (i = 0; i < kernelSize; i++){
				 	if (ri < h && ri >= y)
				{
					cr += mult[i][r2[read]];
					cg += mult[i][g2[read]];
					cb += mult[i][b2[read]];
					sum += kernel[i];
				}
				ri++;
				read += imgWidth;
			}
			unsigned int p = (xl + yi)*comp;
			img[p] = (unsigned char)(cr / sum);
			img[p + 1] = (unsigned char)(cg / sum);
			img[p + 2] = (unsigned char)(cb / sum);
		}
		yi += imgWidth;
	}

	free(rgb);
	free(rgb2);
	free(kernel);
	deleteArray2D(mult, 1 + radius * 2, 256);
}

  

  该代码,将二维数组进一步优化后可提升一定的速度。

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

				
时间: 2024-10-18 18:41:07

快速高速模糊算法的相关文章

快速堆栈模糊算法

上一篇快速高斯模糊的原作者也有另一个比较快速的模糊算法Stack Blur,字面意思为堆栈模糊. 源地址为:http://incubator.quasimondo.com/processing/fast_blur_deluxe.php 这个算法在多个平台上都有实现,安卓以及IOS,JS等. processing源码:http://incubator.quasimondo.com/processing/stackblur.pde 效果图: 转为C语言实现版本. 代码如下: // Stack Blu

快速模糊算法

前段时间在网上看到一个快速模糊算法,性能很不错. 源博客: http://www.lellansin.com/super-fast-blur-%E6%A8%A1%E7%B3%8A%E7%AE%97%E6%B3%95.html 博主对其进行了简单的bug修正以及性能优化. 在博主机子上使用该算法对一张5000x3000的图片进行模糊处理,仅需500-600毫秒,速度非常快. 代码如下: /* * Super Fast Blur v1.1+ * Original author: Mario Klin

最快速的“高斯”模糊算法(附Android源码)

? 这是一个外国人的算法,本人是搬运工.参考:http://blog.ivank.net/fastest-gaussian-blur.html ? 1:高斯模糊算法(参考:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html) 所谓的模糊算法就是当前像素点和周围像素点进行加权均值之后的结果替换当前像素值.因此均值模糊是最简单的,只要将周围的像素点相加取平均值即可. ????而高斯模糊则是将周围的像素点的权值按照高斯分布进行取值,即根据

具体解释Redis源代码中的部分高速排序算法(pqsort.c)

看标题.你可能会疑惑:咦?你这家伙.怎么不解说完整的快排,仅仅讲一部分快排---.- 哎,冤枉. "部分快排"是算法的名字.实际上本文相当具体呢.本文差点儿与普通快排无异.看懂了本文,你对普通的快排也会有更深的认识了. 高速排序算法(qsort)的原理我们大都应该了解.本文介绍的是部分高速排序算法. 事实上其算法本质是一样的,仅仅只是限定了排序的左右区间.也就是仅仅对一个数字序列的一部分进行排序.故称为"部分高速排序算法".简称:pqsort Redis项目中的pq

每日一小练——快速Fibonacci数算法

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:快速Fibonacci数算法 内容:先说说Fibonacci数列,它的定义是数列:f1,f2....fn有如下规律: 尝试寻找快速的求出fn的方法 我的解法:上来没多想,打开vs2013就敲了起来,问题果然很简单,分分钟就超神..奥,不对就解决了! 其实题目中就给出了这个算法的递归形式,所以首先我想到的是递归解法,不过因为求解快速方法在递归之前,我编写了一个非递归的算法 #include <iostream> usi

高速排序算法C++实现

//quick sort //STL中也有现成的高速排序算法.内部实现採用了下面技巧 //1)枢轴的选择採取三数取中的方式 //2)后半段採取循环的方式实现 //3)高速排序与插入排序结合 #include<vector> #include<iostream> #include<algorithm> using namespace std; //这一版本号是最简单实现版本号.对于高速排序的优化主要有下面几个方面: //1)枢轴的选择.若枢轴选取不全适.比方,若每次递归时

位运算之——按位与(&amp;)操作——(快速取模算法)

由于位运算直接对内存数据进行操作,不需要转成十进制,因此处理速度非常快. 按位与(Bitwise AND),运算符号为& a&b 的操作的结果:a.b中对应位同时为1,则对应结果位也为1. 例如: 10010001101000101011001111000 & 111111100000000 --------------------------------------------- 10101100000000 对10101100000000进行右移8位得到的是101011,这就得

移植StackBlur模糊算法至SDL

StackBlur是Android标配的模糊算法,这也在当时引起了一股毛玻璃热潮.IOS7就采用了此算法(这有抄袭Android之嫌,因为Android1.5就在标库中加入了此函数).算法效率很高,这也是能流畅运行在移动设备上的原因.但其只在Andorid上是标准库函数,移植版也只出现在Java上.本文带来一个在SDL上移植的StackBlur算法.运行效果基本如下图. 一眼就可以看出,毛玻璃效果与Radius有直接的关系.Radius在5时,效果与动态模糊相似,在10时,会有点马赛克的感觉,在

高速排序算法

高速排序算法 作者 July  二零一一年一月四日------------------------------------------ 写之前,先说点题外话.每写一篇文章,我都会遵循下面几点原则:一.保持版面的尽量清晰,力保排版良好.二.力争所写的东西,清晰易懂,图文并茂三.尽最大可能确保所写的东西精准,有实用价值. 由于,我认为,你既然要把你的文章,发布出来,那么你就一定要为你的读者负责.不然,就不要发表出来.一切,为读者服务. ok,闲不多说.接下来,咱们立马进入本文章的主题,排序算法.众所