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

当初做这个算法时,参考的是相机360中的卡通特效。实际查找资料时,我看很多资料也把这种效果称为矢量风格画,严格意义讲,我也说不上来到底该叫什么。找了些资料,也没有找到准确的定义。况且我做的效果,和矢量风格画以及卡通画还有些差距,说白了,并不是那么像。不过,虽然不像,但从效果上,我觉得各有千秋吧,实际对比发现,有些图片处理后,效果要优于相机360中的效果。
       计算过程主要在y通道进行。如果在rgb空间分三个通道处理,计算过程将会非常耗时,所以需要由rgb空间转换至yuv空间,单独对y通道进行处理,最后在变换回rgb空间进行显示、输出。下面把算法大体描述一下。rgb转yuv,得到y通道,单独对y通道做边缘检测,然后计算结构张量,得到整幅图像的矢量场,即计算每个像素点的水平分量及垂直分量。有了矢量场,就可以调用线积分卷积算法进行滤波,得到具有手绘风格的笔触效果。在由yuv空间转回rgb空间过程中,还可以根据不同需求,生成不同风格的结果图,比如黑白图,彩色图等。
       下面贴出算法整体调用逻辑代码,基本可以了解本文提出的卡通画特效算法思路。
[cpp]  view plain  copy
  1. void* ImageVectorStylizationThread(void *arg)  
  2. {  
  3.     VectorStylizationInfo *vecstylization_info = (VectorStylizationInfo *)arg;  
  4.     BMPINFO *pSrcBitmap = vecstylization_info->pSrcBitmap;  
  5.     int style_index = vecstylization_info->style_index;  
  6.     int color_index = vecstylization_info->color_index;  
  7.     int thread_id = vecstylization_info->thread_id;  
  8.   
  9.     int width = pSrcBitmap->lWidth;  
  10.     int height=  pSrcBitmap->lHeight;  
  11.     int size = width*height;  
  12.     int mem_size = size * sizeof(float);  
  13.     float *rdata = (float *)malloc(mem_size);  
  14.     float *gdata = (float *)malloc(mem_size);  
  15.     float *bdata = (float *)malloc(mem_size);  
  16.     float *ydata = (float *)malloc(mem_size);  
  17.     float *udata = (float *)malloc(mem_size);  
  18.     float *vdata = (float *)malloc(mem_size);  
  19.   
  20.     // 数据转换  
  21.     ConvertToFloat(pSrcBitmap, rdata, gdata, bdata);  
  22.   
  23.     // rgb转yuv  
  24.     for (int i = 0; i < size; i++)  
  25.     {  
  26.         Rgb2Yuv(rdata[i], gdata[i], bdata[i], &ydata[i], &udata[i], &vdata[i]);  
  27.     }  
  28.   
  29.     // 抽取边缘  
  30.     float *edgedata = (float *)malloc(mem_size);  
  31.     ExtractEdge(ydata, edgedata, width, height, 15.7f, 0.017f, 105.5f);  
  32.   
  33.     // 计算矢量场  
  34.     float *vec_x = (float *)malloc(size * sizeof(float));  
  35.     float *vec_y = (float *)malloc(size * sizeof(float));  
  36.     CalcVectorField(ydata, width, height, vec_x, vec_y, 1.5f);  
  37.       
  38.     // 线积分卷积  
  39.     LICFilter(edgedata, ydata, vec_x, vec_y, width, height);  
  40.   
  41.     free(vec_x);  
  42.     free(vec_y);  
  43.     vec_x = NULL;  
  44.     vec_y = NULL;  
  45.     free(edgedata);  
  46.     edgedata = NULL;  
  47.   
  48.     // 输出结果  
  49.     switch (style_index)  
  50.     {  
  51.     case 0:  
  52.         // 黑白  
  53.         memcpy(rdata, ydata, mem_size);  
  54.         memcpy(gdata, ydata, mem_size);  
  55.         memcpy(bdata, ydata, mem_size);  
  56.         ConvertToUchar(rdata, gdata, bdata, pSrcBitmap);  
  57.         ImageBlend(pSrcBitmap, 0, 0);  
  58.         break;  
  59.     case 1:  
  60.         // 单彩  
  61.         memcpy(rdata, ydata, mem_size);  
  62.         memcpy(gdata, ydata, mem_size);  
  63.         memcpy(bdata, ydata, mem_size);  
  64.         ConvertToUchar(rdata, gdata, bdata, pSrcBitmap);  
  65.         ImageBlend(pSrcBitmap, 0, 0);  
  66.         ImageBlend(pSrcBitmap, 1, color_index);  
  67.         break;  
  68.     case 2:  
  69.         // 多彩  
  70.         for (int i = 0; i < size; i++)  
  71.         {  
  72.             Yuv2Rgb(ydata[i], udata[i], vdata[i], &rdata[i], &gdata[i], &bdata[i]);  
  73.         }  
  74.         ConvertToUchar(rdata, gdata, bdata, pSrcBitmap);  
  75.         ImageAdjust(pSrcBitmap);  
  76.         break;  
  77.     default:  
  78.         break;  
  79.     }  
  80.       
  81.     free(ydata);  
  82.     free(udata);  
  83.     free(vdata);  
  84.     ydata = NULL;  
  85.     udata = NULL;  
  86.     vdata = NULL;  
  87.   
  88.     free(rdata);  
  89.     free(gdata);  
  90.     free(bdata);  
  91.     rdata = NULL;  
  92.     gdata = NULL;  
  93.     bdata = NULL;  
  94.   
  95.     return NULL;  
  96. }  
       同样,本算法也是有局限性的,对于背景与前景简单一些的图效果比较好,如果图像背景或者前景比较杂乱,生成的结果可能不太理想。下面是一些效果图:
             
                                                                  
                
                
                
                
                
                
                
                
                
       欢迎下载示例demo:http://download.csdn.net/detail/u013085897/9747177,另外本算法已经集成进我的安卓应用《铅笔画》, 大家有兴趣可以到360、安卓、安智等商店下载使用。

猜你喜欢

转载自blog.csdn.net/u010112268/article/details/80434738
今日推荐