zoukankan      html  css  js  c++  java
  • 【OpenCV】贝叶斯之肤色分割模型

    利用公开肤色数据集训练了一个肤色分类器,OpenCV中有现成的方法,拿来即用。在实际项目中应用,自制数据样本会更有效。

    Talk is cheap. Show you the code.

    
    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/ml/ml.hpp>
    
    #include <fstream>
    #include <iostream>
    
    #ifdef _DEBUG
    #pragma comment(lib,"opencv_core249d.lib")
    #pragma comment(lib,"opencv_highgui249d.lib")
    #pragma comment(lib,"opencv_imgproc249d.lib")
    #pragma comment(lib,"opencv_ml249d.lib")
    #else
    #pragma comment(lib,"opencv_core249.lib")
    #pragma comment(lib,"opencv_highgui249.lib")
    #pragma comment(lib,"opencv_imgproc249.lib")
    #pragma comment(lib,"opencv_ml249.lib")
    #endif
    
    using namespace std;
    using namespace cv;
    // split the data & label
    bool changeDataType(vector<Vec4i> source, Mat & data, Mat & labels )
    {
        int nsample = source.size();
    
        Mat bgr_data = Mat(nsample,1,CV_8UC3);
        Mat tmp_labels = Mat(nsample,1,CV_32F);
    
        for (int i = 0; i < nsample; i++ )
        {
            // BGR
            bgr_data.ptr<uchar>(i)[0] = source[i][0];
            bgr_data.ptr<uchar>(i)[1] = source[i][1];
            bgr_data.ptr<uchar>(i)[2] = source[i][2];
            // label
            tmp_labels.ptr<float>(i)[0] = source[i][3];
        }
    
        Mat ycrcb_data;
        cvtColor(bgr_data,ycrcb_data,CV_BGR2YCrCb);
    
        Mat tmp_ycrcb_data = ycrcb_data.reshape(1,nsample);
        tmp_ycrcb_data.convertTo(data,CV_32F);
    
        tmp_labels.copyTo(labels);
    
        return true;
    }
    // select crcb channel
    bool ycrcb2crcb(Mat& ycrcb, Mat& crcb )
    {
        assert(ycrcb.type() == CV_32F);
    
        if(!crcb.empty())
            crcb.release();
        int n =  ycrcb.rows;
        crcb = Mat(n,2,CV_32F);
    
        for (int i =0 ; i < n; i++)
        {
            crcb.ptr<float>(i)[0] = ycrcb.ptr<float>(i)[1];
            crcb.ptr<float>(i)[1] = ycrcb.ptr<float>(i)[2];
        }
    
        return true;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
        //////////////////////////////////////////////////////////////////////////
        // load train data
    
        string datafile = "skin_dataset/Skin_NonSkin.txt";
    
        ifstream fp(datafile);
    
        if(!fp.is_open()) return -1;
    
        vector<Vec4i> total_data_labels;
    
        while(!fp.eof())
        {
            int R = 0 ,G = 0 ,B = 0 ;
            int label = 0;
            fp >> B>>G>>R>> label;
            if(label != 1 && label != 2 )
                continue;
            total_data_labels.push_back(Vec4i(B,G,R,label));
    
        }
    
        int nsample = total_data_labels.size();
        cout<<"Load "<<nsample<<" samples: "<<endl;
    
        //////////////////////////////////////////////////////////////////////////
        // split training data and test samples
        random_shuffle(total_data_labels.begin(),total_data_labels.end());
        int train_n = 0.9*nsample;
    
        vector<Vec4i> train_data_labels,test_data_labels;
        for (int i = 0 ; i < nsample; i++)
        {
            if(i < train_n)
                train_data_labels.push_back(total_data_labels[i]);
            else
                test_data_labels.push_back(total_data_labels[i]);
        }
        cout<<" split: "<< train_n<<endl;
        cout<<" train samples: "<<train_data_labels.size()<<" "<<test_data_labels.size()<<endl;
        cout<<"======================"<<endl;
        // change data type
        Mat train_data,train_labels;
        changeDataType(train_data_labels,train_data,train_labels);
        Mat train_crcb_data;
        ycrcb2crcb(train_data,train_crcb_data);
        //////////////////////////////////////////////////////////////////////////
        // BayesClassifier
        cout<<"Bayes training: "<<endl;
        NormalBayesClassifier *bayes = new NormalBayesClassifier();
        bayes->train(train_crcb_data,train_labels,Mat(),Mat());
        cout<<"======================"<<endl;
        //////////////////////////////////////////////////////////////////////////
        // test sample predict
        cout<<"Test sample predict: "<<endl;
        Mat test_data,test_labels;
        changeDataType(test_data_labels,test_data,test_labels);
    
        Mat test_crcb_data;
        ycrcb2crcb(test_data,test_crcb_data);
    
        Mat result(test_data.rows, test_data.cols, CV_32F);
        bayes->predict(test_crcb_data,&result);
    
        int err = 0;
        for (int i = 0; i < test_data.rows; i++){
            int trueRes = test_labels.ptr<float>(i)[0];
            float predictRes = result.ptr<float>(i)[0];
            if (fabs(trueRes - predictRes) >= FLT_EPSILON){
                err++;
            }
        }
        cout <<"    error No.:"<< err << " precision: "<< 100-err*1.f / test_data.rows * 100 << "% 
    ";
        //////////////////////////////////////////////////////////////////////////
        // test image
        cout<<"Test natural image: "<<endl;
    
        Mat source = imread("image/zdm.jpg",1);
        if(source.empty())
            return -1;
        Mat ycrcb_image;
        cvtColor(source,ycrcb_image,CV_BGR2YCrCb);
    
        int width = source.cols;
        int height = source.rows;
        Mat ycrcb_image_test_matrix = ycrcb_image.reshape(1,width*height);
        Mat ycrcb_image_test_matrix32f;
        ycrcb_image_test_matrix.convertTo(ycrcb_image_test_matrix32f,CV_32F);
    
        Mat crcb_image_test_matrix32f;
        ycrcb2crcb(ycrcb_image_test_matrix32f,crcb_image_test_matrix32f);
    
        double t1 = getTickCount();
        Mat output(ycrcb_image_test_matrix32f.rows, ycrcb_image_test_matrix32f.cols, CV_32F);
        bayes->predict(crcb_image_test_matrix32f,&output);
    
        Mat mask = Mat(height,width,CV_8U);
        for (int i = 0; i < height; i++)
            for(int j = 0 ; j < width; j++)
            {
                float predictRes = output.ptr<float>(i*width + j)[0];
                if(fabs(predictRes - 1) <= FLT_EPSILON)
                    mask.ptr<uchar>(i)[j] = 255;
                else
                    mask.ptr<uchar>(i)[j] = 0;
            }
    
        double t2 = getTickCount();
        cout<<"times: "<<(t2-t1)*1000/getTickFrequency()<<" ms"<<endl;
    
        //////////////////////////////////////////////////////////////////////////
        // dilate
        Mat element = getStructuringElement(MORPH_CROSS,Size(5,5));
        dilate( mask, mask, element );
        erode(mask,mask,element);
    
        Mat foot;
        source.copyTo(foot,mask);
        imwrite("zdm_crcb.jpg",mask);
        namedWindow("foot",0);
        imshow("foot",mask);
        waitKey();
    
        return 0;
    }
    
    
    >>>
    Load 245057 samples:
            split: 220551
            train samples: 220551 24506
    ======================
    Bayes training:
    ======================
    Test sample predict:
            error No.:103 precision: 99.5797%
    Test natural image:
    Input image size: 649824 3
    times: 243.396 ms
    
    
    

    测试结果:
    source:
    source
    output:
    out
















    额,该妹子是年轻时的妮可●基德曼!

  • 相关阅读:
    OO第二单元架构随笔
    OO第二单元小结
    OO第一单元小结
    OO第四单元总结
    oo第三单元总结
    OO第二单元总结
    OO第一单元总结
    OO第四单元及课程总结
    OO第三单元总结
    OO第二单元总结
  • 原文地址:https://www.cnblogs.com/brother-louie/p/13976558.html
Copyright © 2011-2022 走看看