皮肤检测及对检测到皮肤单独校色 (基于自动白平衡)
来源:互联网 发布:少爷的喜欢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
- 皮肤检测及对检测到皮肤单独校色 (基于自动白平衡)
- 皮肤检测
- 基于opencv的皮肤检测
- 基于像素的皮肤检测技术
- 基于像素的皮肤检测技术
- 基于像素的皮肤检测技术
- 图像皮肤检测算法
- 皮肤检测椭圆轮廓
- 图像处理------基于像素的皮肤检测技术
- 皮肤检测算法三种
- OpenCV:皮肤检测类CvAdaptiveSkinDetector
- OpenCv皮肤检测-HSV分离
- 基于白点检测的数码相机自动白平衡算法实现(Opencv+vs)
- 皮肤水分检测原理及测量电路分析
- 肤色检测算法 - 基于不同颜色空间简单区域划分的皮肤检测算法
- 肤色检测算法 - 基于不同颜色空间简单区域划分的皮肤检测算法
- 一个简单有趣的皮肤检测代码
- Opencv之简单皮肤检测代码
- HTTP Status 500 - Unable to instantiate Action
- Rust之开始入门<1>
- armlinux内核启动--内存初始化管理
- Android 让GridView的高度为Wrap_content根据内容自适应高度
- STL学习----入门(1)[queue]
- 皮肤检测及对检测到皮肤单独校色 (基于自动白平衡)
- OnCreate&&OnInitDialog、Onclose&&OnDestroy
- 搜狗新人流程规范
- linux下pip安装mysql-python的错误解决方法
- 正则表达式识别ip
- 【读书笔记】iOS-简单的数据驱动程序
- linux系统进程的内存布局
- Ugly Number II
- linux下core文件设置与查看