美颜能把一般般长相的人整的好看吗?

Python027

美颜能把一般般长相的人整的好看吗?,第1张

能,美颜能把一般般长相的人整的好看的。

拜各类技术和软件的发展所赐,当我们出现在镜头面前时,计算机算法就已经自动将采集到的人像进行了美颜处理。因此,镜头里的人总是那么“不真实”。

那么,这些软件背后需要用到什么程序算法?计算机是如何识别人的面部和身体,并对这些部位进行美化的呢?

其实,美颜和绘画有很多相似性,绘画首先是画线稿,确定人体基础结构,然后在线稿之上进行上色,逐步丰富细节,最后完成一幅作品。

我们拍摄的原始人体图像也是“画线稿”,手机收集原始数据,将图像上传到后台进行定位和识别。这一步的目的是确定人体的特征位置。

接下来开始“上色”,用算法和技术对五官或身体部位进行分析、处理、美化,最后得到美颜后的图像。

只不过完成一幅绘画作品需要较长的时间,而美颜却是瞬时的、即刻的,这背后需要有强大的计算机技术作为支撑。

人脸关键点定位技术识别五官

美颜技术有多强大?美颜技术原理与程序算法

如今的美颜相机,已经可以给眼睛画眼影、给嘴唇涂口红。那么,这些功能是怎么精准识别图像中人脸的特定部位的呢?

这其中利用的是人脸关键点检测技术,即通过寻找脸部特征点来确定五官的精准位置。一般来说,定位的关键点数量越多,最终的美颜效果越好。

目前主流的人脸关键点检测方法有两种:基于特征的人脸检测和基于图像的人脸检测。目前使用最多的是基于特征的人脸检测方法。

原始人脸数据被上传至后台后,人脸检测技术会对原始的图像帧进行识别。眼睛、眉毛、T型区(即眼睛+鼻子构成的区域)、嘴、下巴会被依次识别,识别的数据被放入人脸信息结构体中,之后再被应用到具体的美颜算法中,对特定部位进行美化。

图像平滑技术帮你磨皮

女生在化妆时会先涂一层粉底液,主要作用是美白和减少皮肤瑕疵。这其实就相当于美颜功能中的美白和磨皮。

美颜技术有多强大?美颜技术原理与程序算法

好的磨皮效果应该是怎样的?首先最重要的是让皮肤变光滑,同时还要尽量保留更多细节(如皮肤肌理),让五官轮廓清晰可见,这样的图片看起来更真实、更有质感。

磨皮利用的是图像平滑技术,因为在拍摄图像时会受到噪声干扰,使图像质量降低,因此要对噪声进行过滤。过滤后的图像将变得平滑,多余无用的信息会被剔除掉。

过滤图像噪声的工具是滤波器,一般常用的滤波器有中值滤波、边缘保持滤波、双边滤波(又称高斯双边滤波)等。中值滤波和边缘保持滤波的缺点是不能很好地保留图像的边缘信息;而双边滤波可以保留大量人脸细节且确保边界处不会被模糊掉,因此其应用最为普遍。

色彩模式切换美白皮肤

我们人眼的“像素”很高,能看见世界的色彩斑斓,那没有“眼睛”的计算机怎么识别颜色呢?

图像中的色彩一般用RGB模式表示,R、G、B分别代表红、绿、蓝,具体数值从0—255变化。R、G、B的数值越趋于0,图像越黑;相反,越接近255就越白。此外,还有HSV模式(H、S、V分别代表色彩、饱和度、明度),这两种色彩模式可以通过算法实现转换。

很多美白技术会将RGB模式转化为HSV模式后再进行调整:先用算法对皮肤像素的颜色数据进行大量统计,得到肤色像素的取值范围,然后再调节像素的各项数值大小,让图像中的皮肤变白、变亮。

美颜技术有多强大?美颜技术原理与程序算法

美颜技术有多强大?美颜技术原理与程序算法

模板与原图合成“定制”妆容

美颜相机里还能“定制”妆容,包括口红、腮红、眼妆等。这是因为相机软件里植入了预先设计的、不同风格的妆容模板,当人脸出现后,首先会基于人脸关键点检测技术,识别出特定部位,然后妆容模板会投射到人脸特定区域,最后妆容和原始图像进行高效合成,给图像里的人“化妆”。

以画眉为例,许多软件都提供了多套眉毛的图片模板,先检测出原始图像眉毛的关键点位置,眉毛的第一个关键点会作为贴合的起始位置;算法还会对眉毛模板的大小和范围作出调整,使模板和人的原始眉毛能更好地贴合;最后在原图上进行融合,得到自然、逼真的画眉效果。

这样一看,美颜果然是个“技术活”。

//没听懂你的需求,能更清楚一些吗?

我以前的一个程序使用BufferedImage读取图像像素点的RGB值,例子在下面。

你从例子中了解一下用一个整数表示RGB颜色的方法。然后用setRGB方法满足你的要求。

方法:

java.awt.image.BufferedImage

public int getRGB(int x,int y)

返回默认 RGB 颜色模型 (TYPE_INT_ARGB) 和默认 sRGB 颜色空间中的整数像素。如果此默认模型与该图像的 ColorModel 不匹配,则发生颜色转换。在使用此方法所返回的数据中,每个颜色分量只有 8 位精度。

public void setRGB(int x, int y,int rgb)

将此 BufferedImage 中的像素设置为指定的 RGB 值。假定该像素使用默认 RGB 颜色模型、TYPE_INT_ARGB 和默认 sRGB 颜色空间。对于具有 IndexColorModel 的图像,则选择最接近的颜色的索引。

参数:

x - 要设置的像素的 X 坐标

y - 要设置的像素的 Y 坐标

rgb - RGB 值

例子:(获取RGB值)---了解一下用一个整数表示RGB颜色的方法

import java.awt.image.BufferedImage

import javax.imageio.ImageIO

import java.io.*

public class Test{

public static void main(String args[]) {

int[] rgb = new int[3]

File file = new File("a.bmp")

BufferedImage bi=null

try{

bi = ImageIO.read(file)

}catch(Exception e){

e.printStackTrace()

}

int width=bi.getWidth()

int height=bi.getHeight()

int minx=bi.getMinX()

int miny=bi.getMinY()

System.out.println("width="+width+",height="+height+".")

System.out.println("minx="+minx+",miniy="+miny+".")

for(int i=minxi<widthi++){

for(int j=minyj<heightj++){

//System.out.print(bi.getRGB(jw, ih))

int pixel=bi.getRGB(i, j)

rgb[0] = (pixel &0xff0000 ) >>16

rgb[1] = (pixel &0xff00 ) >>8

rgb[2] = (pixel &0xff )

System.out.println("i="+i+",j="+j+":("+rgb[0]+","+rgb[1]+","+rgb[2]+")")

}

}

}

}

     前些时候做毕业设计 用java做的数字图像处理方面的东西 这方面的资料ms比较少 发点东西上来大家共享一下 主要就是些算法 有自己写的 有人家的 还有改人家的 有的算法写的不好 大家不要见笑

一 读取bmp图片数据

//  获取待检测图像  数据保存在数组 nData[] nB[]  nG[]  nR[]中

public  void getBMPImage(String source) throws Exception {                    clearNData()                        //清除数据保存区         FileInputStream fs = null               try {            fs = new FileInputStream(source)            int bfLen =             byte bf[] = new byte[bfLen]            fs read(bf bfLen)// 读取 字节BMP文件头            int biLen =             byte bi[] = new byte[biLen]            fs read(bi biLen)// 读取 字节BMP信息头

// 源图宽度            nWidth = (((int) bi[ ] &xff) <<)                    | (((int) bi[ ] &xff) <<)                    | (((int) bi[ ] &xff) <<) | (int) bi[ ] &xff

// 源图高度            nHeight = (((int) bi[ ] &xff) <<)                    | (((int) bi[ ] &xff) <<)                    | (((int) bi[ ] &xff) <<) | (int) bi[ ] &xff

// 位数            nBitCount = (((int) bi[ ] &xff) <<) | (int) bi[ ] &xff

// 源图大小            int nSizeImage = (((int) bi[ ] &xff) <<)                    | (((int) bi[ ] &xff) <<)                    | (((int) bi[ ] &xff) <<) | (int) bi[ ] &xff

// 对 位BMP进行解析            if (nBitCount == ){                int nPad = (nSizeImage / nHeight) nWidth *                 nData = new int[nHeight * nWidth]                nB=new int[nHeight * nWidth]                nR=new int[nHeight * nWidth]                nG=new int[nHeight * nWidth]                byte bRGB[] = new byte[(nWidth + nPad) * * nHeight]                fs read(bRGB (nWidth + nPad) * * nHeight)                int nIndex =                 for (int j = j <nHeightj++){                    for (int i = i <nWidthi++) {                        nData[nWidth * (nHeight j ) + i] = ( &xff) <<                                | (((int) bRGB[nIndex + ] &xff) <<)                                 | (((int) bRGB[nIndex + ] &xff) <<)                                | (int) bRGB[nIndex] &xff                                              nB[nWidth * (nHeight j ) + i]=(int) bRGB[nIndex]&xff                        nG[nWidth * (nHeight j ) + i]=(int) bRGB[nIndex+ ]&xff                        nR[nWidth * (nHeight j ) + i]=(int) bRGB[nIndex+ ]&xff                        nIndex +=                     }                    nIndex += nPad                } //               Toolkit kit = Toolkit getDefaultToolkit() //               image = kit createImage(new MemoryImageSource(nWidth nHeight  //                       nData nWidth))

/*               //调试数据的读取

FileWriter fw = new FileWriter( C:\\Documents and Settings\\Administrator\\My Documents\\nDataRaw txt )//创建新文件                PrintWriter out = new PrintWriter(fw)                for(int j= j<nHeightj++){                 for(int i= i<nWidthi++){                  out print(( * +nData[nWidth * (nHeight j ) + i])+ _                     +nR[nWidth * (nHeight j ) + i]+ _                     +nG[nWidth * (nHeight j ) + i]+ _                     +nB[nWidth * (nHeight j ) + i]+ )                                   }                 out println( )                }                out close()*/                      }        }        catch (Exception e) {            e printStackTrace()            throw new Exception(e)        }         finally {            if (fs != null) {                fs close()            }        }     //   return image    }

二 由r g b 获取灰度数组

    public  int[] getBrightnessData(int rData[] int gData[] int bData[]){          int brightnessData[]=new int[rData length]     if(rData length!=gData length || rData length!=bData length       || bData length!=gData length){      return brightnessData     }     else {      for(int i= i<bData lengthi++){       double temp= *rData[i]+ *gData[i]+ *bData[i]       brightnessData[i]=(int)(temp)+((temp (int)(temp))>? : )      }      return brightnessData     }          } 

三 直方图均衡化

    public int [] equilibrateGray(int[] PixelsGray int width int height)     {                  int gray         int length=PixelsGray length         int FrequenceGray[]=new int[length]         int SumGray[]=new int[ ]         int ImageDestination[]=new int[length]         for(int i = i <length i++)         {            gray=PixelsGray[i]              FrequenceGray[gray]++        }           //    灰度均衡化          SumGray[ ]=FrequenceGray[ ]         for(int i= i<i++){               SumGray[i]=SumGray[i ]+FrequenceGray[i]           }         for(int i= i<i++) {               SumGray[i]=(int)(SumGray[i]* /length)           }         for(int i= i<heighti++)          {                for(int j= j<widthj++)               {                   int k=i*width+j                  ImageDestination[k]= xFF | ((SumGray[PixelsGray[k]]<<                            ) | (SumGray[PixelsGray[k]]<<) | SumGray[PixelsGray[k]])               }           }         return ImageDestination      } 

四 laplace 阶滤波 增强边缘 图像锐化

    public int[] laplace DFileter(int []data int width int height){         int filterData[]=new int[data length]     int min=      int max=      for(int i= i<heighti++){      for(int j= j<widthj++){       if(i== || i==height || j== || j==width )               filterData[i*width+j]=data[i*width+j]       else        filterData[i*width+j]= *data[i*width+j] data[i*width+j ] data[i*width+j+ ]                             data[(i )*width+j] data[(i )*width+j ] data[(i )*width+j+ ]                             data[(i+ )*width+j] data[(i+ )*width+j ] data[(i+ )*width+j+ ]              if(filterData[i*width+j]<min)        min=filterData[i*width+j]       if(filterData[i*width+j]>max)        max=filterData[i*width+j]      }       }//     System out println( max: +max)//     System out println( min: +min)          for(int i= i<width*heighti++){      filterData[i]=(filterData[i] min)* /(max min)     }     return filterData    } 

五 laplace 阶增强滤波 增强边缘 增强系数delt

    public int[] laplaceHigh DFileter(int []data int width int height double delt){          int filterData[]=new int[data length]     int min=      int max=      for(int i= i<heighti++){      for(int j= j<widthj++){       if(i== || i==height || j== || j==width )               filterData[i*width+j]=(int)(( +delt)*data[i*width+j])       else        filterData[i*width+j]=(int)(( +delt)*data[i*width+j] data[i*width+j ]) data[i*width+j+ ]                             data[(i )*width+j] data[(i )*width+j ] data[(i )*width+j+ ]                             data[(i+ )*width+j] data[(i+ )*width+j ] data[(i+ )*width+j+ ]              if(filterData[i*width+j]<min)        min=filterData[i*width+j]       if(filterData[i*width+j]>max)        max=filterData[i*width+j]      }       }     for(int i= i<width*heighti++){      filterData[i]=(filterData[i] min)* /(max min)     }     return filterData    }  六 局部阈值处理 值化

    //   局部阈值处理 值化 niblack s   method    /*原理             T(x y)=m(x y)   +   k*s(x y)            取一个宽度为w的矩形框 (x y)为这个框的中心          统计框内数据 T(x y)为阈值 m(x y)为均值 s(x y)为均方差 k为参数(推荐 )计算出t再对(x y)进行切割 /             这个算法的优点是     速度快 效果好             缺点是     niblack s   method会产生一定的噪声        */        public int[] localThresholdProcess(int []data int width int height int w int h double coefficients double gate){     int[] processData=new int[data length]     for(int i= i<data lengthi++){      processData[i]=      }          if(data length!=width*height)      return processData          int wNum=width/w     int hNum=height/h     int delt[]=new int[w*h]          //System out println( w+w+   h: +h+   wNum: +wNum+ hNum: +hNum)          for(int j= j<hNumj++){      for(int i= i<wNumi++){     //for(int j= j<j++){     // for(int i= i<i++){         for(int n= n<hn++)               for(int k= k<wk++){                delt[n*w+k]=data[(j*h+n)*width+i*w+k]                //System out print( delt[ +(n*w+k)+ ]: +delt[n*w+k]+ )               }        //System out println()        /*        for(int n= n<hn++)               for(int k= k<wk++){                System out print( data[ +((j*h+n)*width+i*w+k)+ ]: +data[(j*h+n)*width+i*w+k]+ )               }        System out println()        */        delt=thresholdProcess(delt w h coefficients gate)        for(int n= n<hn++)               for(int k= k<wk++){                processData[(j*h+n)*width+i*w+k]=delt[n*w+k]               // System out print( delt[ +(n*w+k)+ ]: +delt[n*w+k]+ )               }        //System out println()        /*        for(int n= n<hn++)               for(int k= k<wk++){                System out print( processData[ +((j*h+n)*width+i*w+k)+ ]: +processData[(j*h+n)*width+i*w+k]+ )               }        System out println()        */      }      }          return processData    } 

七 全局阈值处理 值化

    public int[] thresholdProcess(int []data int width int height double coefficients double gate){     int [] processData=new int[data length]     if(data length!=width*height)      return processData     else{      double sum=       double average=       double variance=       double threshold            if( gate!= ){       threshold=gate       }      else{            for(int i= i<width*heighti++){            sum+=data[i]            }            average=sum/(width*height)                  for(int i= i<width*heighti++){              variance+=(data[i] average)*(data[i] average)            }            variance=Math sqrt(variance)            threshold=average coefficients*variance      }               for(int i= i<width*heighti++){          if(data[i]>threshold)             processData[i]=           else                 processData[i]=          }               return processData       }    } 

八  垂直边缘检测 sobel算子

    public int[] verticleEdgeCheck(int []data int width int height int sobelCoefficients) throws Exception{     int filterData[]=new int[data length]     int min=      int max=      if(data length!=width*height)      return filterData          try{            for(int i= i<heighti++){       for(int j= j<widthj++){        if(i== || i== || i==height || i==height            ||j== || j== || j==width || j==width ){               filterData[i*width+j]=data[i*width+j]         }         else{          double average            //中心的九个像素点             //average=data[i*width+j] Math sqrt( )*data[i*width+j ]+Math sqrt( )*data[i*width+j+ ]          average=data[i*width+j] sobelCoefficients*data[i*width+j ]+sobelCoefficients*data[i*width+j+ ]                         data[(i )*width+j ]+data[(i )*width+j+ ]                     data[(i+ )*width+j ]+data[(i+ )*width+j+ ]             filterData[i*width+j]=(int)(average)         }               if(filterData[i*width+j]<min)         min=filterData[i*width+j]         if(filterData[i*width+j]>max)         max=filterData[i*width+j]        }        }       for(int i= i<width*heighti++){        filterData[i]=(filterData[i] min)* /(max min)         }          }     catch (Exception e)      {            e printStackTrace()            throw new Exception(e)        }            return filterData    } 

九  图像平滑 * 掩模处理(平均处理) 降低噪声

lishixinzhi/Article/program/Java/hx/201311/26286