快速高斯模糊[剪裁版]

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

函数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);
}

一下是剪裁效果图:

快速高斯模糊[剪裁版]

时间: 2024-10-27 17:52:34

快速高斯模糊[剪裁版]的相关文章

最新win7系统32位和64位电脑城快速装机稳定版 V2016年1月

最新win7系统32位电脑城快速装机稳定版 V2016年1月 全能装机版 V2016.1(32位)与之前的系统相比,更注重智能性,在安装方式上也更加精简,操作步骤简便,更适合不会COMS设置和GHOST的用户. 最新更新的win7系统地址http://www.xitongma.com/Windows7/ 下载地址: 百度网盘:http://pan.baidu.com/s/1i3O8MHZ 360网盘地址:http://yunpan.cn/cuQwfqYaXjDWp  访问密码 2435 win7

Log4j快速使用精简版

Log4j快速使用精简版 1.导入log4j-1.2.17.jar包 2.在src根目录下创建log4j.properties文件 log4j.rootLogger=INFO, CONSOLE, FILE ## console 配置文件输出的目的地 (控制台)log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppenderlog4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayoutlog4j

angularjs学习总结(快速预览版)

对html标签的增强 -> 指令 指令的本质是什么 声明的方式调用相应的脚本,实现一些操作,声明的所在的dom就是脚本的执行上下文? 自定义标签 -- 标签指令自定义属性 -- 属性指令特定格式注释 -- 注释指令 概念模板 视图 模型 模块 指令 依赖注入 路由 > MVVM其他MVC框架 backbone emberjsAngular不依赖其他任何框架AngularJs重新定义了前端应用的开发方式,AngularJs特别适合开发单页面应用(SPA) > AngularJs的特性1.

jenkins+docker+gitlab+harbor+pipeline快速部署发版流程

介绍随着业务的增长,需求也开始增多,每个需求的大小,开发周期,发布时间都不一致.基于微服务的系统架构,功能的叠加,对应的服务的数量也在增加,大小功能的快速迭代,更加要求部署的快速化,智能化.因此,传统的人工部署已经心有余而力不足.持续集成,持续部署,持续交互对于微服务开发来说,是提高团队整体效率不可或缺的一环.合理的使用CI,CD能够极大的提高了生产效率,也提高了产品的交互质量.流程梳理: 1.开发人员对上线版本在gitLab上打了一个tag2.jenkins获取tag版本.3.编写pipeli

ldap快速搭建步骤版

步骤版: ==================================服务器的设置======================================= yum install -y openldap openldap-servers openldap-clients openldap-devel cp /usr/share/openldap-servers/slapd.conf.obsolete /etc/openldap/slapd.conf && cp /usr/sh

快速高斯模糊

以前写过两篇关于快速高斯滤波的文章,但是代码都没写完整. 算法来源及介绍请参考博主Imageshop的博文http://www.cnblogs.com/Imageshop/archive/2013/01/07/2849782.html. 为了避免需要的朋友在看我的文章时过于浪费时间,所以删除前两篇文章,重写此篇目的为需要的朋友提供有用的信息. 下面给出的是功能完整的 c代码,下面代码无论是格式还是速度都可以进一步优化,请自行处理 /********************************

使用Chrome Headless 快速实现java版数据的抓取

参考<使用Chrome快速实现数据的抓取(一)--概述>和<使用Chrome快速实现数据的抓取(二)--协议>. 各协议客户端实现参考:https://github.com/ChromeDevTools/awesome-chrome-devtools#chrome-devtools-protocol. Java: cdp4j - Java library for CDP,使用这个类库实现. 地址:https://github.com/webfolderio/cdp4j maven引

Maven快速入门--Idea版

目录 1.web项目的基本知识 1.1 项目构建 1.1.1传统的构建过程如下: 1.1.2 mavn构建项目 1.2 maven构建项目的优点: 2. 依赖管理 2.1 传统依赖管理 2.1.1 手工拷贝jar到工程存在的问题: 2.2 maven项目依赖管理 2.2.1 maven依赖管理的好处: 2.2 使用maven的好处 2.2.1 其他项目构建方式 3. Maven的下载和安装 3.1 环境变量的配置 4.Maven仓库repository 4.1 maven仓库的作用 4.1.1

ASP.NET--QQ快速登录--SDK版

C#网站实现QQ第三方登陆 说起在网站上面可以直接使用QQ登录功能大家并不陌生.但翻其官方提供的SDK包中却没有C#方向的. 但是我们有个牛人叫张善友,做了一个民间SDK.下面我们就是用他所写的SDK,进行网站添加第三方qq登录的功能. SDK开源地址:http://opensns.codeplex.com/ 一.申请账号 1.申请地址:http://connect.qq.com/.申请完毕之后会得到一个APP ID和App Key.这两个字符串会在以后配置的时候用到. 在配置文件web.con