今天给你们讲解一下,如何实现美颜相机中的高级柔焦效果,首先先看下美颜相机中这个功能的效果图:css
图1 原图(图片来自网络,若有侵权敬请告知)html
图2 美颜相机高级柔焦模版git
图3 马赛克效果算法
图4,动感模糊效果网络
以上图3和4是两种柔焦的效果,很不错,今天我将用C来实现这个算法。ide
这个算法的流程以下:学习
1,前景抠图(自动抠图或者手动抠图)测试
美颜相机使用的是先手动涂抹出前景目标区域,而后使用自动抠图将该区域准确抠图;spa
实际上,目前有不少基于深度学习的抠图算法,效果至关不错,好比最近比较火的实时视频抠图技术等等。这里,本人仍是给出一些方法的汇总以下:.net
《Interactive graph cuts for optimal boundary and region segmentation of objects in N-D images》
《Shared Sampling for Real-Time Alpha Matting》
《A Closed Form Solution to Natural Image Matting》
《A Bayesian Approach to Digital Matting》
《Learning Based Alpha Matting using Support Vector Regression》
《Natural Image Matting using Deep Convolutional Neural Networks》
《Deep Image Matting》
本文主要介绍方法,这里给出白百合测试图前景抠图的效果:
图5 白百合前景MASK
2,背景特效你们能够看到图3和图4的效果区别,主要是背景的区别,一个是马赛克,一个是放射模糊;
所以,咱们须要对背景图片进行相应的马赛克和放射模糊处理,本人效果图以下:
图6 马赛克效果
图7 放射模糊效果
这里能够参考本人博客里的各类滤镜特效,实际上均可以用来作背景处理,进而得出各类不一样的效果;
3,图像融合
有了前景背景以后,咱们能够根据前景的MASK(区域的二值MASK),对前景和背景进行alpha融合,公式以下:
Output = F*Mask+(255-Mask)*B
其中F表示前景,B表示背景,其中MASK中白色表示前景,黑色表示背景;
最后本人的效果图以下:
图8 马赛克柔焦效果图
图9 放射模糊柔焦效果图
以上三点就是柔焦效果的具体算法实现过程,最后,给出代码逻辑(我这里实现了四个柔焦的效果):
int f_Focus(unsigned char* srcData, int width, int height, int stride, unsigned char* mask, int intensity, int mode) { //background effects int ret = 0; int i, j; unsigned char* gaussData = (unsigned char*)malloc(sizeof(unsigned char) * stride * height); int radius = intensity * 20 / 100; switch(mode) { case 0://gauss blur effect ret = f_TFastestGaussFilter(srcData, width, height, stride, gaussData, radius); break; case 1://moscia effect memcpy(gaussData, srcData, sizeof(unsigned char) * stride * height); ret = f_TMosaic(gaussData, width, height, stride, intensity / 2); break; case 2://diffusion effect memcpy(gaussData, srcData, sizeof(unsigned char) * stride * height); ret = f_TDiffusion(gaussData, width, height, stride, intensity / 2); break; case 3://zoom blur effect memcpy(gaussData, srcData, sizeof(unsigned char) * stride * height); ret = f_TZoomBlur(gaussData, width, height, stride, width / 2, height / 2, 10, intensity); break; default: break; } //alpha blend unsigned char* pMask = mask; unsigned char* pSrc = srcData; unsigned char* pGauss = gaussData; int k, nk; for(j = 0; j < height; j++) { for(i = 0; i < width; i++) { k = pMask[0]; nk = 255 - k; pSrc[0] = CLIP3((pSrc[0] * k + pGauss[0] * nk) >> 8, 0, 255); pSrc[1] = CLIP3((pSrc[1] * k + pGauss[1] * nk) >> 8, 0, 255); pSrc[2] = CLIP3((pSrc[2] * k + pGauss[2] * nk) >> 8, 0, 255); pSrc += 4; pGauss += 4; pMask += 4; } } free(gaussData); return ret; }; int f_Test(unsigned char *srcData, int width, int height, int stride, unsigned char* mask, int intensity, int mode) { int ret = 0; //Process ret = f_Focus(srcData, width, height, stride, mask, intensity, mode); return ret; };
本人QQ1358009172,欢迎交流学习!