我的第一个任务是实现美颜功能,网上找了一大堆资料,总的来说美颜的实现的步骤是:
1.用具有保边效果的滤波算法对图像进行模糊处理
2.用肤色检测算法保护非皮肤区域
3.将模糊后的图像和原图进行图像融合
4.对融合后的图像进行锐化处理
对于步骤一,该滤波算法可以选择双边滤波,导向滤波,表面模糊等,只要能保边缘就行,高斯模糊是不行的,色斑逗逗就是在这一步磨掉的哈哈,这一步运算速度将直接影响到最后美颜的效率,这也是可以各显神通的地方。
对于步骤二,第一次听说肤色检测好像很高大上,但是它的算法非常简单,就是根据像素的rgb值去判断而已
对于步骤三,可以采用基于alpha通道的图像融合,这一步的作用是为了增加皮肤的质感,因为第一步一般都把皮肤磨得跟娃娃一样了感觉很假。
对于步骤四,在步骤三处理后,会发现图像还是有点朦胧感,还是第一步的副作用,锐化可以强化边缘,让图像看起来更清晰,关于锐化的算法网上有不同的实现算法
下面就贴出我自己做的美颜源代码:
package com.zhangsutao.utils;
import android.graphics.Bitmap;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* Created by zhangsutao on 2016/3/30.
*/
public class BeautifyMultiThread {
/**
*核心函数,请不要再主线程调用
*params:bit原图,sigma美颜程度建议范围(1-20)
*return 美颜后的图片
*/
public Bitmap beautifyImg(Bitmap bit, int sigma){
final int width=bit.getWidth();
final int height=bit.getHeight();
//原图
int[] src_pixels=new int[width*height];
//结果图
int[] res_pixels=new int[width*height];
bit.getPixels(src_pixels, 0, width, 0, 0, width, height);
int div=height/5;
int radius=(int)(Math.max(width,height)*0.02);
CyclicBarrier barrier=new CyclicBarrier(5);
Thread t1=new Thread(new FilterTask(barrier,src_pixels,res_pixels,width,height,radius,sigma,50,0,div));
Thread t2=new Thread(new FilterTask(barrier,src_pixels,res_pixels,width,height,radius,sigma,50,div+1,2*div));
Thread t3=new Thread(new FilterTask(barrier,src_pixels,res_pixels,width,height,radius,sigma,50,2*div+1,3*div));
Thread t4=new Thread(new FilterTask(barrier,src_pixels,res_pixels,width,height,radius,sigma,50,3*div+1,4*div));
Thread t5=new Thread(new FilterTask(barrier,src_pixels,res_pixels,width,height,radius,sigma,50,4*div+1,height-1));
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Bitmap resImg=Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
resImg.setPixels(src_pixels, 0, width, 0, 0, width, height);
return resImg;
}
public boolean isSkin(int r,int g,int b){
if(r>95&&g>40&&b>20&&r>g&&r>b&&(max(r,g,b)-min(r,g,b)>15)&&Math.abs(r-g)>15){
return true;
}else{
return false;
}
}
public int min(int a,int b,int c){
if(a>b)
a=b;
if(a>c)
a=c;
return a;
}
public int max(int a,int b,int c){
if(a<b)
a=b;
if(a<c)
a=c;
return a;
}
public class FilterTask implements Runnable{
int[] src, res;
int width,height,radius, sigma, startRaw, endRaw,alpha;
CyclicBarrier barrier;
public FilterTask(CyclicBarrie