基於像素的皮膚檢測技術java
介紹一種基於顏色空間的皮膚檢測技術,能夠檢測亞洲人種與白人的皮膚,皮膚檢測算法
人臉識別的基礎,也是不少人像識別技術的基礎操做,在實際應用中仍是很是有用的。ide
基於像素的皮膚檢測主要是尋找正確的顏色空間幾何,圖像處理中,常見的顏色空間url
有以下幾種spa
1. RGB色彩空間 – R表明單色紅,G表明單色綠,B表明單色藍.net
2. HSV色彩空間 – H 表明色彩, S表明飽和度,V表明強度值orm
3. YCbCr色彩空間 – 是數字電視的色彩空間blog
RGB轉換爲HSV的Java代碼以下:ip
- public static float[] rgbToHSV(int tr, int tg, int tb) {
- float min, max, delta;
- float hue, satur, value;
- min = Math.min(tr, Math.min(tg, tb));
- max = Math.max(tr, Math.max(tg, tb));
- value = max;
- delta = max - min;
- if(max != 0) {
- satur = delta/max;
- } else {
- satur = 0;
- hue = -1;
- }
-
- if(tr == max) {
- hue = (tg - tb)/delta;
- }
- else if(tg == max) {
- hue = 2 + (tb-tr)/delta;
- } else {
- hue = 4 + (tr-tg)/delta;
- }
- hue = hue * 60.0f;
- if(hue < 0) {
- hue = hue + 360;
- }
- return new float[]{hue, satur, value};
- }
RGB轉換爲YCbCr的Java代碼以下:ci
- public static int[] rgbToYcrCb(int tr, int tg, int tb) {
- double sum = tr + tg + tb;
- double r = ((double)tr)/sum;
- double g = ((double)tg)/sum;
- double b = ((double)tb)/sum;
- double y = 65.481 * r + 128.553 * g + 24.966 * b + 16.0d;
- double Cr = -37.7745 * r - 74.1592 * g + 111.9337 * b + 128.0d;
- double Cb = 111.9581 * r -93.7509 * g -18.2072 * b + 128.0d;
- return new int[]{(int)y, (int)Cr, (int)Cb};
- }
一個簡單的基於RGB顏色空間的皮膚算法以下:
(R, G, B) is classified as skin if
R > 95 and G > 40 and B > 20and max{R, G, B} – min{R, G, B} > 15 and |R-G| > 15
and R > G and R > B
實現代碼以下:
- public boolean isSkin(int tr, int tg, int tb) {
- int max = Math.max(tr, Math.max(tg, tb));
- int min = Math.min(tr, Math.min(tg, tb));
- int rg = Math.abs(tr - tg);
- if(tr > 95 && tg > 40 && tb > 20 && rg > 15 &&
- (max - min) > 15 && tr > tg && tr > tb) {
- return true;
- } else {
- return false;
- }
- }
一個簡單的基於HSV顏色空間的皮膚算法以下:
(H, S, V) will be classified as skin if
H > 0 and H < 50 and S > 0.23 andS < 0.68
實現代碼以下:
- public boolean isSkin(int tr, int tg, int tb) {
- float[] HSV = ColorUtil.rgbToHSV(tr, tg, tb);
- if((HSV[0] > 0.0f && HSV[0] < 50.0f ) && (HSV[1] > 0.23f && HSV[1] < 0.68f)){
- return true;
- } else {
- return false;
- }
- }
一個簡單的基於YCbCr顏色空間的皮膚算法以下:
(Y, Cb, Cr) will be classified as skin if:
Y > 80 and 85<Cb < 135 and 135 <Cr < 180, and (Y,Cb,Cr)= [0,255]
對於的Java代碼以下:
- public boolean isSkin(int tr, int tg, int tb) {
- int y = (int)(tr * 0.299 + tg * 0.587 + tb * 0.114);
- int Cr = tr - y;
- int Cb = tb - y;
- if(y> 80 && y < 255 && Cr > 133 && Cr < 173 && 77 < Cb && Cb < 127) {
- return true;
- }
- return false;
- }
基於上述三個算法實現的皮膚檢測的效果以下:
![](http://static.javashuo.com/static/loading.gif)
皮膚檢測濾鏡的源代碼以下:
- package com.process.blur.study;
-
- import java.awt.Color;
- import java.awt.image.BufferedImage;
-
- import com.gloomyfish.skin.dection.DefaultSkinDetection;
- import com.gloomyfish.skin.dection.FastSkinDetection;
- import com.gloomyfish.skin.dection.GaussianSkinDetection;
- import com.gloomyfish.skin.dection.HSVSkinDetection;
- import com.gloomyfish.skin.dection.ISkinDetection;
-
- public class SkinFilter extends AbstractBufferedImageOp {
- private ISkinDetection skinDetector;
-
- public SkinFilter(int type) {
- if(type == 2) {
- skinDetector = new FastSkinDetection();
- } else if(type == 4) {
- skinDetector = new HSVSkinDetection();
- } else if(type == 8) {
- skinDetector = new GaussianSkinDetection();
- } else {
- skinDetector = new DefaultSkinDetection();
- }
- }
-
- @Override
- public BufferedImage filter(BufferedImage src, BufferedImage dst) {
- int width = src.getWidth();
- int height = src.getHeight();
-
- if ( dst == null )
- dst = createCompatibleDestImage( src, null );
-
- int[] inPixels = new int[width*height];
- int[] outPixels = new int[width*height];
- getRGB( src, 0, 0, width, height, inPixels );
- if(skinDetector instanceof GaussianSkinDetection) {
- ((GaussianSkinDetection)skinDetector).setDispSample(getDispersion(src));
- }
- int index = 0;
- for(int row=0; row<height; row++) {
- int ta = 0, tr = 0, tg = 0, tb = 0;
- for(int col=0; col<width; col++) {
- index = row * width + col;
- ta = (inPixels[index] >> 24) & 0xff;
- tr = (inPixels[index] >> 16) & 0xff;
- tg = (inPixels[index] >> 8) & 0xff;
- tb = inPixels[index] & 0xff;
- if(skinDetector.isSkin(tr, tg, tb)) {
- outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;
- } else {
- tr = tg = tb = 0;
- outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;
- }
- }
- }
- setRGB( dst, 0, 0, width, height, outPixels );
- return dst;
- }
-
- public Color getDispersion(BufferedImage image) {
-
- int index = 0;
- int height = image.getHeight();
- int width = image.getWidth();
- int[] inPixels = new int[width*height];
- getRGB(image, 0, 0, width, height, inPixels );
- double redSum = 0, greenSum = 0, blueSum = 0;
- Color meanColor = getMean(image);
- double redmeans = meanColor.getRed();
- double greenmeans = meanColor.getGreen();
- double bluemeans = meanColor.getBlue();
- double total = height * width;
- for(int row=0; row<height; row++) {
- int ta = 0, tr = 0, tg = 0, tb = 0;
- for(int col=0; col<width; col++) {
- index = row * width + col;
- ta = (inPixels[index] >> 24) & 0xff;
- tr = (inPixels[index] >> 16) & 0xff;
- tg = (inPixels[index] >> 8) & 0xff;
- tb = inPixels[index] & 0xff;
- double rd = (tr - redmeans);
- double gd = (tg - greenmeans);
- double bd = (tb - bluemeans);
- redSum += rd * rd;
- greenSum += gd * gd;
- blueSum += bd * bd;
- }
- }
- int reddiff = (int)Math.sqrt((redSum / total));
- int greendiff = (int)Math.sqrt((greenSum / total));
- int bluediff = (int)Math.sqrt(blueSum / total);
- System.out.println(" red dispersion value = " + reddiff);
- System.out.println(" green dispersion value = " + greendiff);
- System.out.println(" blue dispersion value = " + bluediff);
- return new Color(reddiff, greendiff, bluediff);
- }
-
- public Color getMean(BufferedImage image) {
-
- int index = 0;
- int height = image.getHeight();
- int width = image.getWidth();
- int[] inPixels = new int[width*height];
- getRGB(image, 0, 0, width, height, inPixels );
- double redSum = 0, greenSum = 0, blueSum = 0;
- double total = height * width;
- for(int row=0; row<height; row++) {
- int ta = 0, tr = 0, tg = 0, tb = 0;
- for(int col=0; col<width; col++) {
- index = row * width + col;
- ta = (inPixels[index] >> 24) & 0xff;
- tr = (inPixels[index] >> 16) & 0xff;
- tg = (inPixels[index] >> 8) & 0xff;
- tb = inPixels[index] & 0xff;
- redSum += tr;
- greenSum += tg;
- blueSum +=tb;
- }
- }
- int redmeans = (int)(redSum / total);
- int greenmeans = (int)(greenSum / total);
- int bluemeans = (int)(blueSum / total);
- System.out.println(" red average value = " + redmeans);
- System.out.println(" green average value = " + greenmeans);
- System.out.println(" blue average value = " + bluemeans);
- return new Color(redmeans, greenmeans, bluemeans);
- }
- }
討論:
皮膚檢測中的後續處理很是重要,能夠除去噪聲,平滑圖像,是皮膚檢測的結果
更加的準確,輸出的更容易接受。