skin是用来提取肤色区域的,不加这段可以正常运行,加了就不行了
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
void Two_Pass(const cv::Mat& binImg, cv::Mat& lableImg) //两遍扫描法
{
if (binImg.empty() ||
binImg.type() != CV_8UC1)
{
cout<<"no picture"<<endl;
return;
}
// 第一个通路
lableImg.release();
binImg.convertTo(lableImg, CV_32SC1);
int label = 1;
std::vector labelSet;
labelSet.push_back(0);
labelSet.push_back(1);
int rows = binImg.rows - 1;
int cols = binImg.cols - 1;
for (int i = 1; i < rows; i++)
{
int* data_preRow = lableImg.ptr(i-1);
int* data_curRow = lableImg.ptr(i);
for (int j = 1; j < cols; j++)
{
if (data_curRow[j] == 1)
{
std::vector neighborLabels;
neighborLabels.reserve(2);
int leftPixel = data_curRow[j-1];
int upPixel = data_preRow[j];
if ( leftPixel > 1)
{
neighborLabels.push_back(leftPixel);
}
if (upPixel > 1)
{
neighborLabels.push_back(upPixel);
}
if (neighborLabels.empty())
{
labelSet.push_back(++label); // 不连通,标签+1
data_curRow[j] = label;
labelSet[label] = label;
}
else
{
std::sort(neighborLabels.begin(), neighborLabels.end());
int smallestLabel = neighborLabels[0];
data_curRow[j] = smallestLabel;
// 保存最小等价表
for (size_t k = 1; k < neighborLabels.size(); k++)
{
int tempLabel = neighborLabels[k];
int& oldSmallestLabel = labelSet[tempLabel];
if (oldSmallestLabel > smallestLabel)
{
labelSet[oldSmallestLabel] = smallestLabel;
oldSmallestLabel = smallestLabel;
}
else if (oldSmallestLabel < smallestLabel)
{
labelSet[smallestLabel] = oldSmallestLabel;
}
}
}
}
}
}
// 更新等价对列表
// 将最小标号给重复区域
cout<<labelSet.size();
for (size_t i = 2; i < labelSet.size(); i++)
{
int curLabel = labelSet[i];
int preLabel = labelSet[curLabel];
while (preLabel != curLabel)
{
curLabel = preLabel;
preLabel = labelSet[preLabel];
}
labelSet[i] = curLabel;
} ;
for (int i = 0; i < rows; i++)
{
int* data = lableImg.ptr(i);
for (int j = 0; j < cols; j++)
{
int& pixelLabel = data[j];
pixelLabel = labelSet[pixelLabel];
}
}
}
//彩色显示
cv::Scalar GetRandomColor()
{
uchar r = 255 * (rand()/(1.0 + RAND_MAX));
uchar g = 255 * (rand()/(1.0 + RAND_MAX));
uchar b = 255 * (rand()/(1.0 + RAND_MAX));
return cv::Scalar(b,g,r);
}
void LabelColor(const cv::Mat& labelImg, cv::Mat& colorLabelImg)
{
if (labelImg.empty() ||
labelImg.type() != CV_32SC1)
{
return;
}
std::map colors;
int rows = labelImg.rows;
int cols = labelImg.cols;
colorLabelImg.release();
colorLabelImg.create(rows, cols, CV_8UC3);
colorLabelImg = cv::Scalar::all(0);
for (int i = 0; i < rows; i++)
{
const int* data_src = (int*)labelImg.ptr(i);
uchar* data_dst = colorLabelImg.ptr(i);
for (int j = 0; j < cols; j++)
{
int pixelValue = data_src[j];
if (pixelValue > 1)
{
if (colors.count(pixelValue) <= 0)
{
colors[pixelValue] = GetRandomColor();
}
cv::Scalar color = colors[pixelValue];
*data_dst++ = color[0];
*data_dst++ = color[1];
*data_dst++ = color[2];
}
else
{
data_dst++;
data_dst++;
data_dst++;
}
}
}
}
Mat skin(Mat &img){
Mat out;
medianBlur( img, out, 15);
// GaussianBlur(image,out,Size(17,17),0,0);
//遍历图像得到符合肤色特征的像素点 记录于count
int count=0;
for(int i=0;i<out.rows;i++)
{
for(int j=0;j<out.cols;j++)
{
int r,g,b; //图像的R,G,B信息
b=out.at<Vec3b>(i,j)[0];
g=out.at<Vec3b>(i,j)[1];
r=out.at<Vec3b>(i,j)[2];
// if(i==100&&j==i)cout<<r<<","<<g<<","<<b<<endl;
double iYIQ,Cr,Cb; //YIQ,YCbCr颜色空间的I,Cr,Cb值,由转换公式获得
iYIQ = 0.596*(double)r - 0.275*(double)g - 0.321*(double)b;
Cb = -0.148*(double)r - 0.291*(double)g + 0.439*(double)b + 128;
Cr = 0.439*(double)r - 0.368*(double)g - 0.071*(double)b + 128;
// if(i==100&&j==i)cout<<iYIQ<<","<<Cb<<","<<Cr<<endl;
if((iYIQ<=85&&iYIQ>=15)&&(Cb>88&&Cb<133)&&(Cr>122&&Cr<169))count++;
//if(r>95 && g>40 && b>20 && r>g && r>b && max(r,g,b)-min(r,g,b)>15 && abs(r-g)>15)count++;
else {out.at<Vec3b>(i,j)[0]=0;out.at<Vec3b>(i,j)[1]=0;out.at<Vec3b>(i,j)[2]=0;}
}
}
return out;
}
int main()
{
cv::Mat binImage = cv::imread("F:\03.jpg");
Mat out=skin(binImage);
imshow("xixi",out);
waitKey(0);
Mat out1;
cv::cvtColor(out,out1,CV_BGR2GRAY);
imshow("xixi1",out1);
waitKey(0);
Mat out2;
cv::threshold(out1, out1, 1, 255, CV_THRESH_BINARY_INV);
if(out1.empty()==1)cout<<"no picture!!"<<endl;
imshow("xixi2",out1);
waitKey(0);
cv::Mat labelImg;
Two_Pass(out1, labelImg);
//Seed_Filling(binImage, labelImg);
//彩色显示
cv::Mat colorLabelImg;
LabelColor(labelImg, colorLabelImg);
cv::imshow("colorImg", colorLabelImg);
/* //灰度显示
cv::Mat grayImg;
labelImg *= 10;
labelImg.convertTo(grayImg, CV_8UC1);
cv::imshow("labelImg", grayImg);
*/
cv::waitKey(0);
return 0;
}