void WBDetectorImpl::train(
    const string& pos_samples_path,
    const string& neg_imgs_path)
{

    vector<Mat> pos_imgs = read_imgs(pos_samples_path);
    vector<Mat> neg_imgs = sample_patches(neg_imgs_path, 24, 24, pos_imgs.size() * 10);

    assert(pos_imgs.size());
    assert(neg_imgs.size());

    int n_features;
    Mat pos_data, neg_data;

    Ptr<CvFeatureEvaluator> eval = CvFeatureEvaluator::create();
    eval->init(CvFeatureParams::create(), 1, Size(24, 24));
    n_features = eval->getNumFeatures();

    const int stages[] = {64, 128, 256, 512, 1024};
    const int stage_count = sizeof(stages) / sizeof(*stages);
    const int stage_neg = (int)(pos_imgs.size() * 5);
    const int max_per_image = 100;

    const float scales_arr[] = {.3f, .4f, .5f, .6f, .7f, .8f, .9f, 1.0f};
    const vector<float> scales(scales_arr,
            scales_arr + sizeof(scales_arr) / sizeof(*scales_arr));

    vector<String> neg_filenames;
    glob(neg_imgs_path, neg_filenames);


    for (int i = 0; i < stage_count; ++i) {

        cerr << "compute features" << endl;

        pos_data = Mat1b(n_features, (int)pos_imgs.size());
        neg_data = Mat1b(n_features, (int)neg_imgs.size());

        for (size_t k = 0; k < pos_imgs.size(); ++k) {
            eval->setImage(pos_imgs[k], +1, 0, boost_.get_feature_indices());
            for (int j = 0; j < n_features; ++j) {
                pos_data.at<uchar>(j, (int)k) = (uchar)(*eval)(j);
            }
        }

        for (size_t k = 0; k < neg_imgs.size(); ++k) {
            eval->setImage(neg_imgs[k], 0, 0, boost_.get_feature_indices());
            for (int j = 0; j < n_features; ++j) {
                neg_data.at<uchar>(j, (int)k) = (uchar)(*eval)(j);
            }
        }


        boost_.reset(stages[i]);
        boost_.fit(pos_data, neg_data);

        if (i + 1 == stage_count) {
            break;
        }

        int bootstrap_count = 0;
        size_t img_i = 0;
        for (; img_i < neg_filenames.size(); ++img_i) {
            cerr << "win " << bootstrap_count << "/" << stage_neg
                 << " img " << (img_i + 1) << "/" << neg_filenames.size() << "\r";
            Mat img = imread(neg_filenames[img_i], CV_LOAD_IMAGE_GRAYSCALE);
            vector<Rect> bboxes;
            Mat1f confidences;
            boost_.detect(eval, img, scales, bboxes, confidences);

            if (confidences.rows > 0) {
                Mat1i indices;
                sortIdx(confidences, indices,
                        CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING);

                int win_count = min(max_per_image, confidences.rows);
                win_count = min(win_count, stage_neg - bootstrap_count);
                Mat window;
                for (int k = 0; k < win_count; ++k) {
                    resize(img(bboxes[indices(k, 0)]), window, Size(24, 24));
                    neg_imgs.push_back(window.clone());
                    bootstrap_count += 1;
                }
                if (bootstrap_count >= stage_neg) {
                    break;
                }
            }
        }
        cerr << "bootstrapped " << bootstrap_count << " windows from "
             << (img_i + 1) << " images" << endl;
    }
}
Beispiel #2
0
Mat skinDetector::detect(Mat captureframe, bool verboseSelect, Mat *skinMask)
{
	verboseOutput=verboseSelect;
	//if (argc>=1) frame = argv[1]);
	//if (argc>=2) singleRegionChoice = int(argv[2]);

	int step = 0;
	Mat3b frame;
	// Forcing resize to 640x480 -> all thresholds / pixel filters configured for this size.....
	// Note returned to original size at end...
    Size s = captureframe.size();
	resize(captureframe,captureframe,Size(640,480));

	
	// CHANGED HERE TO BGR
	//cvtColor(captureframe, captureframe, CV_RGB2BGR);
	if (verboseOutput)	imshow("Raw Image (A)",captureframe);
	/* THRESHOLD ON HSV*/
	// HSV data -> used to find skin
	cvtColor(captureframe, frame, CV_BGR2HSV);
	//cvtColor(captureframe, frame, CV_BGR2HLS);
	GaussianBlur(frame, frame, Size(imgBlurPixels,imgBlurPixels), 1, 1);
	//medianBlur(frame, frame, 15);
	for(int r=0; r<frame.rows; ++r){
		for(int c=0; c<frame.cols; ++c) 
			// 0<H<0.25  -   0.15<S<0.9    -    0.2<V<0.95   
			if( (frame(r,c)[0]>5) && (frame(r,c)[0] < 17) && (frame(r,c)[1]>38) && (frame(r,c)[1]<250) && (frame(r,c)[2]>51) && (frame(r,c)[2]<242) ); // do nothing
			else for(int i=0; i<3; ++i)	frame(r,c)[i] = 0;
	}

	if (verboseOutput)	imshow("Skin HSV (B)",frame);
	/* BGR CONVERSION AND THRESHOLD */
	Mat1b frame_gray;
	cvtColor(frame, frame, CV_HSV2BGR);
	cvtColor(frame, frame_gray, CV_BGR2GRAY);
				
				
	// Adaptive thresholding technique
	// 1. Threshold data to find main areas of skin
	adaptiveThreshold(frame_gray,frame_gray,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY_INV,9,1);
	if (verboseOutput)	imshow("Adaptive_threshold (D1)",frame_gray);
	// 2. Fill in thresholded areas
	morphologyEx(frame_gray, frame_gray, CV_MOP_CLOSE, Mat1b(imgMorphPixels,imgMorphPixels,1), Point(-1, -1), 2);
	
	
	//GaussianBlur(frame_gray, frame_gray, Size((imgBlurPixels*2)+1,(imgBlurPixels*2)+1), 1, 1);
	GaussianBlur(frame_gray, frame_gray, Size(imgBlurPixels,imgBlurPixels), 1, 1);
	// Select single largest region from image, if singleRegionChoice is selected (1)
	
	if (singleRegionChoice)
	{
		*skinMask = cannySegmentation(frame_gray, -1);
	}
	else // Detect each separate block and remove blobs smaller than a few pixels
	{
		*skinMask = cannySegmentation(frame_gray, minPixelSize);
	}


	// Just return skin
	Mat frame_skin;
	captureframe.copyTo(frame_skin,*skinMask);  // Copy captureframe data to frame_skin, using mask from frame_ttt
	// Resize image to original before return
	resize(frame_skin,frame_skin,s);
	if (verboseOutput)	imshow("Skin segmented",frame_skin);
	return frame_skin;	
	waitKey(1);
}
Beispiel #3
0
Mat visionUtils::skinDetect(Mat captureframe, Mat3b *skinDetectHSV, Mat *skinMask, std::vector<int> adaptiveHSV, int minPixelSize, int imgBlurPixels, int imgMorphPixels, int singleRegionChoice, bool displayFaces)
{

    if (adaptiveHSV.size()!=6 || adaptiveHSV.empty())
    {
        adaptiveHSV.clear();
        adaptiveHSV.push_back(5);
        adaptiveHSV.push_back(38);
        adaptiveHSV.push_back(51);
        adaptiveHSV.push_back(17);
        adaptiveHSV.push_back(250);
        adaptiveHSV.push_back(242);
    }


    //int step = 0;
    Mat3b frameTemp;
    Mat3b frame;
    // Forcing resize to 640x480 -> all thresholds / pixel filters configured for this size.....
    // Note returned to original size at end...
    Size s = captureframe.size();
    cv::resize(captureframe,captureframe,Size(640,480));



    if (useGPU)
    {
        GpuMat imgGPU, imgGPUHSV;
        imgGPU.upload(captureframe);
        cv::cvtColor(imgGPU, imgGPUHSV, CV_BGR2HSV);
        GaussianBlur(imgGPUHSV, imgGPUHSV, Size(imgBlurPixels,imgBlurPixels), 1, 1);
        imgGPUHSV.download(frameTemp);
    }
    else
    {
        cv::cvtColor(captureframe, frameTemp, CV_BGR2HSV);
        GaussianBlur(frameTemp, frameTemp, Size(imgBlurPixels,imgBlurPixels), 1, 1);
    }

    // Potential FASTER VERSION using inRange
    Mat frameThreshold = Mat::zeros(frameTemp.rows,frameTemp.cols, CV_8UC1);
    Mat hsvMin = (Mat_<int>(1,3) << adaptiveHSV[0], adaptiveHSV[1],adaptiveHSV[2] );
    Mat hsvMax = (Mat_<int>(1,3) << adaptiveHSV[3], adaptiveHSV[4],adaptiveHSV[5] );
    inRange(frameTemp,hsvMin ,hsvMax, frameThreshold);
    frameTemp.copyTo(frame,frameThreshold);

    /* BGR CONVERSION AND THRESHOLD */
    Mat1b frame_gray;

    // send HSV to skinDetectHSV for return
    *skinDetectHSV=frame.clone();

    cv::cvtColor(frame, frame_gray, CV_BGR2GRAY);


    // Adaptive thresholding technique
    // 1. Threshold data to find main areas of skin
    adaptiveThreshold(frame_gray,frame_gray,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY_INV,9,1);


    if (useGPU)
    {
        GpuMat imgGPU;
        imgGPU.upload(frame_gray);
        // 2. Fill in thresholded areas
#if CV_MAJOR_VERSION == 2
        gpu::morphologyEx(imgGPU, imgGPU, CV_MOP_CLOSE, Mat1b(imgMorphPixels,imgMorphPixels,1), Point(-1, -1), 2);
        gpu::GaussianBlur(imgGPU, imgGPU, Size(imgBlurPixels,imgBlurPixels), 1, 1);
#elif CV_MAJOR_VERSION == 3
        //TODO: Check if that's correct
        Mat element = getStructuringElement(MORPH_RECT, Size(imgMorphPixels, imgMorphPixels), Point(-1, -1));
        Ptr<cuda::Filter> closeFilter = cuda::createMorphologyFilter(MORPH_CLOSE, imgGPU.type(), element, Point(-1, -1), 2);
        closeFilter->apply(imgGPU, imgGPU);
        cv::Ptr<cv::cuda::Filter> gaussianFilter = cv::cuda::createGaussianFilter(imgGPU.type(), imgGPU.type(), Size(imgMorphPixels, imgMorphPixels), 1, 1);
        gaussianFilter->apply(imgGPU, imgGPU);
#endif

        imgGPU.download(frame_gray);
    }
    else
    {
        // 2. Fill in thresholded areas
        morphologyEx(frame_gray, frame_gray, CV_MOP_CLOSE, Mat1b(imgMorphPixels,imgMorphPixels,1), Point(-1, -1), 2);
        GaussianBlur(frame_gray, frame_gray, Size(imgBlurPixels,imgBlurPixels), 1, 1);
        // Select single largest region from image, if singleRegionChoice is selected (1)
    }


    if (singleRegionChoice)
    {
        *skinMask = cannySegmentation(frame_gray, -1, displayFaces);
    }
    else // Detect each separate block and remove blobs smaller than a few pixels
    {
        *skinMask = cannySegmentation(frame_gray, minPixelSize, displayFaces);
    }

    // Just return skin
    Mat frame_skin;
    captureframe.copyTo(frame_skin,*skinMask);  // Copy captureframe data to frame_skin, using mask from frame_ttt
    // Resize image to original before return
    cv::resize(frame_skin,frame_skin,s);

    if (displayFaces)
    {
        imshow("Skin HSV (B)",frame);
        imshow("Adaptive_threshold (D1)",frame_gray);
        imshow("Skin segmented",frame_skin);
    }

    return frame_skin;
    waitKey(1);
}