自己做的一個膚色檢測模型

膚色檢測

在人像美化中,膚色檢測有助於防止磨掉頭髮、鬍子等需要保持細節的部分,也可以使美白算法僅作用於皮膚,不對人像周邊環境產生影響。
網上找了一下膚色檢測模型,效果都太差,換了一種思維,找個訓練集,自己做一個。
訓練結果,正確率大概85%,運行起來,確實還是比網上找的公式好,勉強可用了。

模型

算法最終反映爲 opengl 的一個片斷着色器,直接看shader代碼吧。

varying vec2 textureCoordinate;

uniform sampler2D inputImageTexture;
const vec3 CbC = vec3(0.5,-0.4187,-0.0813);
const vec3 CrC = vec3(-0.1687,-0.3313,0.5);

void main()
{
    vec3 color = texture2D(inputImageTexture, textureCoordinate).rgb;
    float x0 = color.r;
    float x1 = color.g;
    float x2 = color.b;
    float x3 = dot(CbC, color);
    float x4 = dot(CrC, color);
    float pos = 0.0;
    pos = float(x4 <=-0.0615369 ? (x3 <=0.0678488 ? (x3 <=0.0352417 ? 0 : (x2 <=0.686631 ? 0 : 1)) : (x3 <=0.185183 ? 1 : 0)) : (x4 <=-0.029597 ? (x3 <=0.0434402 ? 0 : (x1 <=0.168271 ? 0 : 1)) : 0));
    gl_FragColor = vec4(pos);
}

膚色檢測結果

這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述
這裏寫圖片描述

訓練方法

準備數據集

找到這個網站:
http://blog.csdn.net/wangkr111/article/details/44514097
下載了一組膚色檢測的數據,用python腳本將其轉換爲機器學習所需的矩陣數據。提取 r、g、b、y、cb、cr分量值。

訓練

機器學習庫

機器學習算法庫是自己造的輪子,使用C++開發,特別重視Cache命中率,部分地方引入OpenCL加速,性能可以說是一流的。
使用的代碼如下:

#include "learn/ALLearnFactory.h"
#include "core/ALExpanderFactory.h"
#include "core/ALILabeldMethod.h"
#include "core/ALLabeldMethodFactory.h"
#include "learn/ALDecisionTree.h"
#include "loader/ALStandardLoader.h"
#include "learn/ALLogicalRegress.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <math.h>
#include "learn/ALRegressor.h"
using namespace std;
int main()
{
    ALSp<ALFloatDataChain> c = ALStandardLoader::load("../../Data/Face_Dataset/train.data");
    ALSp<ALFloatMatrix> X;
    ALSp<ALFloatMatrix> Y;
    ALStandardLoader::divide(c.get(), X, Y, 0);
    //ALSp<ALISuperviseLearner> learner = new ALLogicalRegress(10000, 1.0);
    ALSp<ALISuperviseLearner> learner = new ALDecisionTree(10, 0.01, 3);//決策樹深限制爲3
    //ALSp<ALISuperviseLearner> learner = new ALRegressor;
    ALSp<ALIMatrixPredictor> detected = learner->vLearn(X.get(),Y.get());
    ALSp<ALFloatMatrix> YP = ALFloatMatrix::create(Y->width(), Y->height());
    detected->vPredict(X.get(), YP.get());
    size_t po = 0;
    size_t pp = 0;
    size_t fo = 0;
    size_t fp = 0;
    /*驗證正確率*/
    for (size_t i=0; i<YP->height(); ++i)
    {
        auto y = *(Y->vGetAddr(0, i));
        auto yp = *(YP->vGetAddr(0, i));
        if (yp > 0.5 && y > 0.5)
        {
            pp++;
        }
        if (yp <=0.5 && y <=0.5)
        {
            fp++;
        }
        if (y > 0.5)
        {
            po++;
        }
        else
        {
            fo++;
        }
    }
    printf("PP/PO: %ld/%ld, %f, FP/FO: %ld/%ld, %f\n", pp, po, (double)pp/(double)po, fp, fo, (double)fp/(double)fo);
    ofstream of("model_logical");
    /*打印模型*/
    detected->vPrint(of);

    return 0;
}

模型選擇

一開始本來用的是邏輯迴歸,因爲這個出來的預測公式很簡單,shader上運行速度快,但它的效果實在不行。後面改用了決策樹,限制樹深,以免模型太大。
至於爲什麼不用SVM:SVM出來的模型在shader上根本沒法運行啊。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章