卡通画(矢量风格画)特效生成算法

       当初做这个算法时,参考的是相机360中的卡通特效。实际查找资料时,我看很多资料也把这种效果称为矢量风格画,严格意义讲,我也说不上来到底该叫什么。找了些资料,也没有找到准确的定义。况且我做的效果,和矢量风格画以及卡通画还有些差距,说白了,并不是那么像。不过,虽然不像,但从效果上,我觉得各有千秋吧,实际对比发现,有些图片处理后,效果要优于相机360中的效果。
       计算过程主要在y通道进行。如果在rgb空间分三个通道处理,计算过程将会非常耗时,所以需要由rgb空间转换至yuv空间,单独对y通道进行处理,最后在变换回rgb空间进行显示、输出。下面把算法大体描述一下。rgb转yuv,得到y通道,单独对y通道做边缘检测,然后计算结构张量,得到整幅图像的矢量场,即计算每个像素点的水平分量及垂直分量。有了矢量场,就可以调用线积分卷积算法进行滤波,得到具有手绘风格的笔触效果。在由yuv空间转回rgb空间过程中,还可以根据不同需求,生成不同风格的结果图,比如黑白图,彩色图等。
       下面贴出算法整体调用逻辑代码,基本可以了解本文提出的卡通画特效算法思路。
void* ImageVectorStylizationThread(void *arg)
{
	VectorStylizationInfo *vecstylization_info = (VectorStylizationInfo *)arg;
	BMPINFO *pSrcBitmap = vecstylization_info->pSrcBitmap;
	int style_index = vecstylization_info->style_index;
	int color_index = vecstylization_info->color_index;
	int thread_id = vecstylization_info->thread_id;

	int width = pSrcBitmap->lWidth;
	int height=  pSrcBitmap->lHeight;
	int size = width*height;
	int mem_size = size * sizeof(float);
	float *rdata = (float *)malloc(mem_size);
	float *gdata = (float *)malloc(mem_size);
	float *bdata = (float *)malloc(mem_size);
	float *ydata = (float *)malloc(mem_size);
	float *udata = (float *)malloc(mem_size);
	float *vdata = (float *)malloc(mem_size);

	// 数据转换
	ConvertToFloat(pSrcBitmap, rdata, gdata, bdata);

	// rgb转yuv
	for (int i = 0; i < size; i++)
	{
		Rgb2Yuv(rdata[i], gdata[i], bdata[i], &ydata[i], &udata[i], &vdata[i]);
	}

	// 抽取边缘
	float *edgedata = (float *)malloc(mem_size);
	ExtractEdge(ydata, edgedata, width, height, 15.7f, 0.017f, 105.5f);

	// 计算矢量场
	float *vec_x = (float *)malloc(size * sizeof(float));
	float *vec_y = (float *)malloc(size * sizeof(float));
	CalcVectorField(ydata, width, height, vec_x, vec_y, 1.5f);
	
	// 线积分卷积
	LICFilter(edgedata, ydata, vec_x, vec_y, width, height);

	free(vec_x);
	free(vec_y);
	vec_x = NULL;
	vec_y = NULL;
	free(edgedata);
	edgedata = NULL;

	// 输出结果
	switch (style_index)
	{
	case 0:
		// 黑白
		memcpy(rdata, ydata, mem_size);
		memcpy(gdata, ydata, mem_size);
		memcpy(bdata, ydata, mem_size);
		ConvertToUchar(rdata, gdata, bdata, pSrcBitmap);
		ImageBlend(pSrcBitmap, 0, 0);
		break;
	case 1:
		// 单彩
		memcpy(rdata, ydata, mem_size);
		memcpy(gdata, ydata, mem_size);
		memcpy(bdata, ydata, mem_size);
		ConvertToUchar(rdata, gdata, bdata, pSrcBitmap);
		ImageBlend(pSrcBitmap, 0, 0);
		ImageBlend(pSrcBitmap, 1, color_index);
		break;
	case 2:
		// 多彩
		for (int i = 0; i < size; i++)
		{
			Yuv2Rgb(ydata[i], udata[i], vdata[i], &rdata[i], &gdata[i], &bdata[i]);
		}
		ConvertToUchar(rdata, gdata, bdata, pSrcBitmap);
		ImageAdjust(pSrcBitmap);
		break;
	default:
		break;
	}
	
	free(ydata);
	free(udata);
	free(vdata);
	ydata = NULL;
	udata = NULL;
	vdata = NULL;

	free(rdata);
	free(gdata);
	free(bdata);
	rdata = NULL;
	gdata = NULL;
	bdata = NULL;

	return NULL;
}
       同样,本算法也是有局限性的,对于背景与前景简单一些的图效果比较好,如果图像背景或者前景比较杂乱,生成的结果可能不太理想。下面是一些效果图:
          卡通画(矢量风格画)特效生成算法_第1张图片   卡通画(矢量风格画)特效生成算法_第2张图片
                                                                  卡通画(矢量风格画)特效生成算法_第3张图片
                卡通画(矢量风格画)特效生成算法_第4张图片
                卡通画(矢量风格画)特效生成算法_第5张图片
                卡通画(矢量风格画)特效生成算法_第6张图片
                卡通画(矢量风格画)特效生成算法_第7张图片
                卡通画(矢量风格画)特效生成算法_第8张图片
                卡通画(矢量风格画)特效生成算法_第9张图片
                卡通画(矢量风格画)特效生成算法_第10张图片
                卡通画(矢量风格画)特效生成算法_第11张图片
                卡通画(矢量风格画)特效生成算法_第12张图片
       欢迎下载示例demo:http://download.csdn.net/detail/u013085897/9747177,另外本算法已经集成进我的安卓应用《铅笔画》, 大家有兴趣可以到360、安卓、安智等商店下载使用。


你可能感兴趣的:(图像处理,/,特效,/,滤镜)