皮肤检测及对检测到皮肤单独校色 (基于自动白平衡)

来源:互联网 发布:少爷的喜欢lofter乐乎 编辑:程序博客网 时间:2024/05/16 00:47

原理见前几篇博客,修改修改可以做美颜的程序直接贴代码:

/*对照片中的皮肤单独进行较色,然后塞进原始图片作为输出*//*包含皮肤的检测、皮肤的校正两步*//*单张照片测试效果不错,但对于一百多张照片,结果还是有偏差,这种单独校正然后再用于贴图的方法 行不通*//*时间:2015.8.24*/#include <opencv2/core/core.hpp>  #include <opencv2/highgui/highgui.hpp>  #include <opencv2/face.hpp>#include <opencv2/imgproc/imgproc.hpp>  #include <iostream>  #include <vector>    using namespace std;  using namespace cv;  double baidianave(Mat frame,int n){      int a[256];    for (int i=0;i<256;i++)    {        a[i]=0;    }    double sum=0;    double ave;    for (int i=0;i<n;i++)    {        int d=frame.at<double>(0,i);        a[d]++;    }    int n0=255;    for (int k=255;k>0;k--)    {        sum+=a[k];        if (sum>frame.rows*frame.cols/25)        {            break;        }        n0--;    }    sum=0;    for (int i=n0;i<256;i++)    {        sum+=a[i]*i;    }    ave=sum/(frame.rows*frame.cols/25);    return ave;}double baidianave(Mat frame){     int a[256];//cvZero(a);    for (int i=0;i<256;i++)    {        a[i]=0;    }    double sum=0;    double ave;    for (int i=0;i<frame.rows;i++)    {        for (int j=0;j<frame.cols;j++)        {            int d=(int)frame.at<uchar>(i,j);            a[d]++;        }    }    int n0=255;    for (int k=255;k>0;k--)    {        sum+=a[k];        if (sum>frame.rows*frame.cols/25)        {            break;        }        n0--;    }    sum=0;    for (int i=n0;i<256;i++)    {        sum+=a[i]*i;    }    ave=sum/(frame.rows*frame.cols/25);    return ave;}Mat input_image;  Mat output_mask;  Mat output_image;  Mat mask;    int main(int argc,char *argv[])  {      if (2 != argc)     {        cout << "Please enter the image list!" <<endl;        return -1;    }    vector<string>  file_names;    FILE *file_list =  fopen(argv[1],"r");    char buf[255];    memset(&buf,0,sizeof(buf));    while(fgets(buf,255,file_list))    {        if(buf[strlen(buf)-1] == '\n')             buf[strlen(buf)-1] = '\0';        file_names.push_back(string(buf));    }        fclose(file_list);    int count = file_names.size();        Mat skinCrCbHist = Mat::zeros(Size(256, 256), CV_8UC1);      ellipse(skinCrCbHist, Point(113, 155.6), Size(25,12), -20, 0.0, 360.0, Scalar(255, 255, 255), -1);        Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1) );      for(int  i=0; i<count; i++)    {          string img_nm = file_names[i];        string img_mask = "mask" + img_nm;        int pos = img_nm.rfind('.');        string img_fmt = img_nm.substr(pos+1);        if("jpg" != img_fmt)        {          cout << "Unknown format: " << img_fmt << endl;          continue;        }        input_image=imread(img_nm,1);          if(input_image.empty())              return 0;            Mat ycrcb_image;          output_mask = Mat::zeros(input_image.size(), CV_8UC1);          cvtColor(input_image, ycrcb_image, CV_BGR2YCrCb);         CvScalar s;        s.val[0]=0;        s.val[1]=0;        s.val[2]=255;        for(int i = 0; i < input_image.rows; i++)         {              uchar* p = (uchar*)output_mask.ptr<uchar>(i);              Vec3b* ycrcb = (Vec3b*)ycrcb_image.ptr<Vec3b>(i);              for(int j = 0; j < input_image.cols; j++)              {                  if(skinCrCbHist.at<uchar>(ycrcb[j][1], ycrcb[j][2]) > 0)                  {                    // input_image.at<Vec3b>(i,j)[2]=255;                    p[j] = 255;                  }            }          }             // imwrite("test.jpg",input_image);        morphologyEx(output_mask,output_mask,MORPH_CLOSE,element);           vector< vector<Point> > contours;           vector< vector<Point> > filterContours;         vector< Vec4i > hierarchy;           contours.clear();            hierarchy.clear();           filterContours.clear();            findContours(output_mask, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);            for (size_t i = 0; i < contours.size(); i++)           {               if (fabs(contourArea(Mat(contours[i]))) > 2000&&fabs(arcLength(Mat(contours[i]),true))>500)                  filterContours.push_back(contours[i]);          }          output_mask.setTo(0);          drawContours(output_mask, filterContours, -1, Scalar(255,0,0), CV_FILLED);             input_image.copyTo(output_image, output_mask);          Mat tempimage=Mat::zeros(input_image.size(), CV_8UC3);         threshold(output_mask,output_mask,20, 255, THRESH_BINARY);        cvtColor(output_mask,output_mask,CV_GRAY2BGR);        Mat frame=Mat::zeros(input_image.size(), CV_8UC3);         output_image.copyTo(frame);        // imshow("frame",frame);        // waitKey(0);        //cout<<frame.rows<<"  "<<frame.cols<<endl;        // cvShowImage("处理前图像",frame);        int heightyiban=frame.rows;        int widthyiban=frame.cols;        double Ysum=0;//Y的总和        double Cbsum[4]={0,0,0.0};//图像分成四部分,每部分Cb的总和        double Crsum[4]={0,0,0,0};//图像分成四部分,每部分Cr的总和        double Mb[4],Db[4];//图像分成四部分,每部分Cb的均值和均方差        double Mr[4],Dr[3];//Cr的均值和均方差          Mat imageYCrCb =  Mat::zeros(frame.size(), CV_8UC3);        Mat imageCb = Mat::zeros(frame.size(), CV_8UC1);        Mat imageCr = Mat::zeros(frame.size(), CV_8UC1);        Mat imageY = Mat::zeros(frame.size(), CV_8UC1);        // imageYCrCb = cvCreateImage(cvGetSize(frame),8,3);           // imageCb = cvCreateImage(cvGetSize(frame),8,1);          // imageCr = cvCreateImage(cvGetSize(frame),8,1);         // imageY = cvCreateImage(cvGetSize(frame),8,1);         cvtColor(frame,imageYCrCb,CV_BGR2YCrCb);         std::vector<cv::Mat>ybr(imageYCrCb.channels());        split(imageYCrCb,ybr);        // namedWindow("test",0);        // imshow("test",ybr[2]);        // waitKey(0);        //分成三个通道,,,        // imageY,imageCr,imageCb        Mat imageb=Mat::zeros(frame.size(), CV_8UC1);        Mat imagec=Mat::zeros(frame.size(), CV_8UC1);        ybr[1].copyTo(imageb);        ybr[2].copyTo(imagec);        Mat  savg,sfangcha;//全局scalar 变量用来放平均值和方差        meanStdDev(ybr[2],savg,sfangcha);        // cvAvgSdv(imageb,&savg,&sfangcha,NULL);        // cout<<savg.at<double>(0)<<endl;        // cout<<sfangcha.at<double>(0)<<endl;        Mb[0]=savg.at<double>(0);         cout<<"Mb:  "<<Mb[0]<<endl;        Db[0]=sfangcha.at<double>(0);//求出第一部分cb的均值和均方差         cout<<"Db:  "<<Db[0]<<endl;        // cvAvgSdv(imagec,&savg,&sfangcha,NULL);        meanStdDev(ybr[1],savg,sfangcha);        Mr[0]=savg.at<double>(0);        cout<<"Mr:  "<<Mr[0]<<endl;        Dr[0]=sfangcha.at<double>(0);;//求出第一部分cr的均值和均方差         cout<<"Dr:  "<<Dr[0]<<endl;        double b[4],c[4];        for (int i=0;i<1;i++)        {            if (Mb[i]<0)//计算mb+db*sign(mb)            {                 b[i]=Mb[i]+Db[i]*(-1);            }            else                b[i]=Mb[i]+Db[i];        }        for (int i=0;i<4;i++)        {            if (Mr[i]<0)//计算1.5*mr+dr*sign(mb);            {                c[i]=1.5*Mr[i]+Dr[i]*(-1);            }            else                c[i]=1.5*Mr[i]+Dr[i];        }        double Ymax=baidianave(ybr[0]);        //下面是对第一部分进行白点的选择        Mat Bbaidian=Mat::zeros(1,6000000,CV_64FC1);        Mat Gbaidian=Mat::zeros(1,6000000,CV_64FC1);        Mat Rbaidian=Mat::zeros(1,6000000,CV_64FC1);        //CvScalar s1;        int n1=0;        cout<<"b[0]:   "<<b[0]<<"  c[0]:  "<<c[0]<<endl;        for (int i=0;i<heightyiban;i++)        {            for (int j=0;j<widthyiban;j++)            {                 // input_image.at<Vec3b>(i,j)[2]=255                if (((ybr[2].at<uchar>(i,j)-b[0])<(1.5*Db[0]))&&((ybr[1].at<uchar>(i,j)-c[0])<(1.5*Dr[0])))                {                                double d1=frame.at<Vec3b>(i,j)[0];                    Bbaidian.at<double>(0,n1)=d1;                                        double d2=frame.at<Vec3b>(i,j)[1];                    Gbaidian.at<double>(0,n1)=d2;                                    double d3=frame.at<Vec3b>(i,j)[2];                    Rbaidian.at<double>(0,n1)=d3;                    n1++;                }            }        }        // cout<<"n1:  "<<n1<<endl;        double Bave1=baidianave(Bbaidian,n1);        double Gave1=baidianave(Gbaidian,n1);        double Rave1=baidianave(Rbaidian,n1);        cout<<"Bave1:  "<<Bave1<<"    Gave1:  "<<Gave1<<"      Rave1:   "<<Rave1<<"  Ymax:  "<<Ymax<<endl;        Ymax=Ymax;        double Bgain1=Ymax/(Bave1);        double Ggain1=Ymax/(Gave1);        double Rgain1=Ymax/(Rave1);            // CvScalar s1;        // cout<<Bgain1<<"  "<<Ggain1<<"  "<<Rgain1<<endl;         // int count_out=0;        for (int i=0;i<heightyiban;i++)        {            for (int j=0;j<widthyiban;j++)            {                int tb=Bgain1*frame.at<Vec3b>(i,j)[0];                int tg=Ggain1*frame.at<Vec3b>(i,j)[1];                int tr=Rgain1*frame.at<Vec3b>(i,j)[2];                if (tb>255)                {                    tb=255;                    // count_out++;                }                if (tg>255)                {                    tg=255;                    // count_out++;                }                if (tr>255)                {                    tr=255;                    // count_out++;                }                frame.at<Vec3b>(i,j)[0]=tb;                frame.at<Vec3b>(i,j)[1]=tg;                frame.at<Vec3b>(i,j)[2]=tr;            }        }        // cout<<count_out<<endl;         imwrite("frame.jpg",frame);                // cout<<"Finish!"<<endl;        imwrite("img_nm1.jpg",input_image);             for(int i = 0; i < input_image.rows; i++)         {              uchar* p = (uchar*)output_mask.ptr<uchar>(i);              uchar* p2 = (uchar*)input_image.ptr<uchar>(i);              uchar* p3 = (uchar*)frame.ptr<uchar>(i);              for(int j = 0; j < 3*input_image.cols; )              {                  if(p[j] != 0)                  {                    // cout<<"p:  "<<i<<"   "<<j<<"  "<<float(p[j])<<endl;                    // input_image.at<Vec3b>(i,j)[2]=255;                    p2[j]=0;                    p2[j] = p3[j++];                      // cout<<"B:   "<<int (p2[j-1])<<"  ";                    p2[j]=0;                    p2[j] = p3[j++];                      // cout<<"G:  "<<int (p2[j-1])<<"  ";                    p2[j]=0;                    p2[j] = p3[j++];                      // cout<<"R:  "<<int (p2[j-1])<<endl;;                     // cout<<"p2:  "<<i<<"   "<<j<<"  "<<float(p2[j])<<endl;                }                else                    j++;            }          }        // Mat tempimage=Mat::zeros(input_image.size(), CV_8UC3);         // cvtColor(output_mask,tempimage,CV_GRAY2BGR);        // imwrite("output_mask.jpg",output_mask);         // imwrite("tempimage.jpg",tempimage);             imwrite(img_nm,input_image);             imwrite(img_mask,output_image);        // imwrite(img_mask,output_mask);        // namedWindow("input image",0);        // // namedWindow("output mask",0);        // namedWindow("output image",0);        // imshow("input image", input_image);          // imshow("output image", output_image);          cout<<"Finish!"<<endl;        // output_image.setTo(0);          // waitKey(0);            }      return 0;  } 


0 0
原创粉丝点击