示例#1
0
void compareRange(InputArray src, OutputArray destMask, const double validMin, const double validMax)
{
    Mat gray;
    if (src.channels() == 1) gray = src.getMat();
    else cvtColor(src, gray, COLOR_BGR2GRAY);

    Mat mask1;
    Mat mask2;
    compare(gray, validMin, mask1, cv::CMP_GE);
    compare(gray, validMax, mask2, cv::CMP_LE);
    bitwise_and(mask1, mask2, destMask);
}
示例#2
0
int maskGray(Mat img, Mat& retVal)
{
    if (!img.data || !retVal.data)
    {
        printf("Invalid input image\n");
        return 0;
    }

    if (img.channels() != 1)
    {
        printf("Input image is not a gray image\n");
        return 0;
    }

    if (retVal.channels() == 1)
    {
        bitwise_and(img, retVal, retVal);
        if (retVal.size() != img.size())
        {
            return 0;
        }
        return 1;
    }

    Mat grayMerge;
    vector<Mat> gray;

    gray.push_back(img);
    gray.push_back(img);
    gray.push_back(img);
    merge(gray, grayMerge);

    bitwise_and(grayMerge, retVal, retVal);

    if (retVal.size() != img.size())
    {
        return 0;
    }
    return 1;
}
示例#3
0
int ns__bitwiseAnd(  struct soap *soap, char *src1,
				char *src2,
				char **OutputMatFilename)
{
    double start, end;
    start = omp_get_wtime();

	Mat matSrc1;
    if(!readMat(src1, matSrc1))
    {
        cerr << "And :: src1 can not read bin file" << endl;
        return soap_receiver_fault(soap, "And :: src1 can not read bin file", NULL);
    }

    Mat matSrc2;
    if(!readMat(src2, matSrc2))
    {
        cerr << "And :: src2 can not read bin file" << endl;
        return soap_receiver_fault(soap, "And :: src2 can not read bin file", NULL);
    }

    int cols = matSrc1.cols ;
    int srcType1 = matSrc1.type();
    int srcType2 = matSrc2.type();

    if(srcType1 != srcType2 )
    {
        matSrc2.convertTo(matSrc2, srcType1);
	}

    Mat dst;
    bitwise_and(matSrc1, matSrc2, dst);

    /* generate output file name */
    *OutputMatFilename = (char*)soap_malloc(soap, 60);
    getOutputFilename(OutputMatFilename,"_bitwiseAnd");

    /* save to bin */
    if(!saveMat(*OutputMatFilename, dst))
    {
        cerr << "And:: save mat to binary file" << endl;
        return soap_receiver_fault(soap, "And :: save mat to binary file", NULL);
    }

    matSrc1.release();
    matSrc2.release();
    dst.release();

    end = omp_get_wtime();
    cerr<<"ns__And time elapsed "<<end-start<<endl;
    return SOAP_OK;
}
static void colorExtraction(const cv::Mat& src, // input HSV image
                            cv::Mat*       dst, // specified color extracted binarized image
                            const double   hue_lower, const double hue_upper, // hue thresholds
                            const double   sat_lower, const double sat_upper, // satulation thresholds
                            const double   val_lower, const double val_upper) // value thresholds
{
  /* create imput image copy */
  cv::Mat input_img = src.clone();

  *dst = cv::Scalar::all(0);

  /*
    ref:
    http://qiita.com/crakaC/items/65fab9d0b0ac29e68ab6
   */

  /* create LookUp Table */
  cv::Mat lut(256, 1, CV_8UC3);
  for (int i=0; i<256; i++)
    {
	  lut.at<cv::Vec3b>(i)[0] = (IsRange(hue_lower, hue_upper, Actual_Hue(i))) ? 255 : 0;
	  lut.at<cv::Vec3b>(i)[1] = (IsRange(sat_lower, sat_upper, Actual_Sat(i))) ? 255 : 0;
	  lut.at<cv::Vec3b>(i)[2] = (IsRange(val_lower, val_upper, Actual_Val(i))) ? 255 : 0;
    }

  /* apply LUT to input image */
  cv::Mat extracted(input_img.rows, input_img.cols, CV_8UC3);
  LUT(input_img, lut, extracted);

  /* divide image into each channel */
  std::vector<cv::Mat> channels;
  split(extracted, channels);

  /* create mask */
  bitwise_and(channels[0], channels[1], *dst);
  bitwise_and(*dst, channels[2], *dst);


} /* static void colorExtraction() */
示例#5
0
void SetCard::DetectColor(void)
{
    Mat M;
    Mat C;
    Mat HSV;
    bitwise_and(mCutBW, mCutMask, M);
    //bitwise_and(mCutImg, mCutImg, C, M);
    bitwise_and(mCutNormColors, mCutNormColors, C, M);

    cvtColor(C, HSV, mOptions->mColor2HSV);
    vector<Mat> CHNL(3);
    split(HSV, CHNL);

    vector<int> nGPR(3);
    nGPR[0] = CountNonZeroInRage(CHNL[0],  25, 90);  // green
    nGPR[1] = CountNonZeroInRage(CHNL[0], 140, 170); // purple
    nGPR[2] = CountNonZeroInRage(CHNL[0], 170, 255); // red
    double maxV;
    int i;
    minMaxIdx(Mat(nGPR), NULL, &maxV, NULL, &i);
    mCardProperties.mColor = (CARD_COLORS)i;
}
void AdaptiveManifoldFilterN::computeClusters(Mat1b& cluster, Mat1b& cluster_minus, Mat1b& cluster_plus)
{
    
    Mat1f difOreientation;
    if (jointCnNum > 1)
    {
        Mat1f initVec(1, jointCnNum);
        if (useRNG)
        {
            rnd.fill(initVec, RNG::UNIFORM, -0.5, 0.5);
        }
        else
        {
            for (int i = 0; i < (int)initVec.total(); i++)
                initVec(0, i) = (i % 2 == 0) ? 0.5f : -0.5f;
        }

        vector<Mat> difEtaSrc(jointCnNum);
        for (int i = 0; i < jointCnNum; i++)
            subtract(jointCn[i], etaFull[i], difEtaSrc[i]);

        Mat1f eigenVec(1, jointCnNum);
        computeEigenVector(difEtaSrc, cluster, eigenVec, num_pca_iterations_, initVec);

        computeOrientation(difEtaSrc, eigenVec, difOreientation);
        CV_DbgAssert(difOreientation.size() == srcSize);
    }
    else
    {
        subtract(jointCn[0], etaFull[0], difOreientation);
    }

    compare(difOreientation, 0, cluster_minus, CMP_LT);
    bitwise_and(cluster_minus, cluster, cluster_minus);

    compare(difOreientation, 0, cluster_plus, CMP_GE);
    bitwise_and(cluster_plus, cluster, cluster_plus);
}
void AdaptiveManifoldFilterN::computeClusters(Mat1b& cluster, Mat1b& cluster_minus, Mat1b& cluster_plus)
{
    Mat difEtaSrc;
    {
        vector<Mat> eta_difCn(jointCnNum);
        for (int i = 0; i < jointCnNum; i++)
            subtract(jointCn[i], etaFull[i], eta_difCn[i]);

        merge(eta_difCn, difEtaSrc);
        difEtaSrc = difEtaSrc.reshape(1, (int)difEtaSrc.total());
        CV_DbgAssert(difEtaSrc.cols == jointCnNum);
    }

    Mat1f initVec(1, jointCnNum);
    if (useRNG)
    {
        rnd.fill(initVec, RNG::UNIFORM, -0.5, 0.5);
    }
    else
    {
        for (int i = 0; i < (int)initVec.total(); i++)
            initVec(0, i) = (i % 2 == 0) ? 0.5f : -0.5f;
    }

    Mat1f eigenVec(1, jointCnNum);
    computeEigenVector(difEtaSrc, cluster, eigenVec, num_pca_iterations_, initVec);

    Mat1f difOreientation;
    gemm(difEtaSrc, eigenVec, 1, noArray(), 0, difOreientation, GEMM_2_T);
    difOreientation = difOreientation.reshape(1, srcSize.height);
    CV_DbgAssert(difOreientation.size() == srcSize);

    compare(difOreientation, 0, cluster_minus, CMP_LT);
    bitwise_and(cluster_minus, cluster, cluster_minus);

    compare(difOreientation, 0, cluster_plus, CMP_GE);
    bitwise_and(cluster_plus, cluster, cluster_plus);
}
示例#8
0
std::vector< bool > CharacterAnalysis::filterByOuterMask(vector< vector< Point > > contours, vector< Vec4i > hierarchy, std::vector< bool > goodIndices)
{
    float MINIMUM_PERCENT_LEFT_AFTER_MASK = 0.1;
    float MINIMUM_PERCENT_OF_CHARS_INSIDE_PLATE_MASK = 0.6;

    if (hasPlateMask == false)
        return goodIndices;


    vector<bool> passingIndices;
    for (int i = 0; i < goodIndices.size(); i++)
        passingIndices.push_back(false);

    Mat tempMaskedContour = Mat::zeros(plateMask.size(), CV_8U);
    Mat tempFullContour = Mat::zeros(plateMask.size(), CV_8U);

    int charsInsideMask = 0;
    int totalChars = 0;

    for (int i=0; i < goodIndices.size(); i++)
    {
        if (goodIndices[i] == false)
            continue;

        totalChars++;

        drawContours(tempFullContour, contours, i, Scalar(255,255,255), CV_FILLED, 8, hierarchy);
        bitwise_and(tempFullContour, plateMask, tempMaskedContour);

        float beforeMaskWhiteness = mean(tempFullContour)[0];
        float afterMaskWhiteness = mean(tempMaskedContour)[0];

        if (afterMaskWhiteness / beforeMaskWhiteness > MINIMUM_PERCENT_LEFT_AFTER_MASK)
        {
            charsInsideMask++;
            passingIndices[i] = true;
        }
    }

    if (totalChars == 0)
        return goodIndices;

    // Check to make sure that this is a valid box.  If the box is too small (e.g., 1 char is inside, and 3 are outside)
    // then don't use this to filter.
    float percentCharsInsideMask = ((float) charsInsideMask) / ((float) totalChars);
    if (percentCharsInsideMask < MINIMUM_PERCENT_OF_CHARS_INSIDE_PLATE_MASK)
        return goodIndices;

    return passingIndices;
}
void Saliency::Evaluate(const string& resultW, const string &gtImgW, vecD &precision, vecD &recall)
{
	vecS names;
	string inDir;
	int imgNum = CmFile::GetNames(resultW, names, inDir);
	int COLOR_NUM = 256;
	precision.resize(COLOR_NUM, 0);
	recall.resize(COLOR_NUM, 0);

	string truthDir = CmFile::GetFolder(gtImgW);
	size_t pathSize = gtImgW.size(), nPos = gtImgW.find_last_of('.');
	string ext = gtImgW.substr(nPos, pathSize - nPos);

	for (int i = 0; i < imgNum; i++)
	{
		CmLog::LogProgress("Processing %-40s\r", names[i].c_str());
		Mat resS = imread(inDir + names[i], CV_LOAD_IMAGE_GRAYSCALE);
		CV_Assert_(resS.data != NULL, ("Can't load saliency map: %s\n", names[i].c_str()));
		names[i].resize(names[i].find_last_of("_"));
		Mat truM = imread(truthDir + CmFile::GetNameNE(names[i]) + ext, CV_LOAD_IMAGE_GRAYSCALE);
		compare(truM, 128, truM, CMP_GE);
		if (truM.data == NULL)
		{
			CmLog::LogLine("Evaluation stopped due to missing ground truth results\n");
			exit(1);
		}
		CV_Assert_(resS.size() == truM.size(), ("Saliency map and ground truth image size mismatch\n"));

		double groundTruth = sum(truM).val[0];
#pragma omp parallel for
		for (int thr = 0; thr < COLOR_NUM; thr++)
		{
			Mat resM;
			compare(resS, thr, resM, CMP_GE);
			double res = sum(resM).val[0];
			bitwise_and(resM, truM, resM);
			double common = sum(resM).val[0];

			precision[thr] += common/(res + 1e-8);
			recall[thr] += common/(groundTruth + 1e-8);
		}
	}

	for (int thr = 0; thr < COLOR_NUM; thr++)
	{
		precision[thr] /= imgNum;
		recall[thr] /= imgNum;
	}
}
示例#10
0
/*
Mat bwareaopen(Mat& img, int size)
 {
     CBlobResult blobs;
     blobs = CBlobResult( img ,Mat(),4);
     blobs.Filter( blobs, B_INCLUDE, CBlobGetLength(), B_GREATER, size );

     Mat newimg(img.size(),img.type());
     newimg.setTo(0);
     for(int i=0;i<blobs.GetNumBlobs();i++)
     {
         blobs.GetBlob(i)->FillBlob(newimg,CV_RGB(255,255,255),0,0,true);
     }
     return newimg;
 }

Mat removeUseless(Mat& img, int low, int hight)
 {
     CBlobResult blobs;
     blobs = CBlobResult( img ,Mat(),4);
	 blobs.Filter( blobs, B_OUTSIDE, CBlobGetLength(), low, hight );

     Mat newimg(img.size(),img.type());
     newimg.setTo(0);
     for(int i=0;i<blobs.GetNumBlobs();i++)
     {
         blobs.GetBlob(i)->FillBlob(newimg,CV_RGB(255,255,255),0,0,true);
     }
     return newimg;
 }
 */
Mat computeWhiteMaskLight(Mat& input){
	Mat img, gray;
	input.clone().convertTo(img,CV_64F);
	Mat BGRbands[3] = {Mat::zeros(img.size(), CV_64F), Mat::zeros(img.size(), CV_64F),Mat::zeros(img.size(), CV_64F)};  
	Mat I1 = Mat::zeros(img.size(), CV_64F);
	Mat I2 = Mat::zeros(img.size(), CV_64F);
	Mat I3 = Mat::zeros(img.size(), CV_64F);
	Mat Id1 = Mat::zeros(img.size(), CV_64F);
	Mat Id2 = Mat::zeros(img.size(), CV_64F);
	Mat Id3 = Mat::zeros(img.size(), CV_64F);
	Mat I = Mat::zeros(img.size(), CV_64F);
	Mat mask = Mat::zeros(img.size(), CV_8U);
	vector< vector<Point> > contours;
	Mat mask2 = Mat::zeros(img.size(), CV_8U);
	split(img,BGRbands);
	I1 = BGRbands[0]-BGRbands[1];
	I1 = I1.mul(I1);
	I2 = BGRbands[0]-BGRbands[2];
	I2 = I2.mul(I2);
	I3 = BGRbands[1]-BGRbands[2];
	I3 = I3.mul(I3);
	Id1 = I1-I2;
	Id2 = I1-I3;
	Id3 = I3-I2;
	Id1 = Id1.mul(Id1);
	Id2 = Id2.mul(Id2);
	Id3 = Id3.mul(Id3);
	I = Id1+Id2+Id3;
	sqrt(I,I);
	sqrt(I,I);
	I.convertTo(mask,CV_8U);
	threshold(mask,mask,50,255,THRESH_BINARY_INV);
	Mat d = detectShadows(input);
	bitwise_and(mask,d,mask);
	cvtColor(input,gray,CV_BGR2GRAY);
	threshold(gray,mask2,160,255,THRESH_BINARY);
	mask = mask+mask2;
	medianBlur(mask,mask,9);
	findContours(mask, contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
	vector<double> areas = computeArea(contours);
	for(int j = areas.size()-1; j>=0; j--){
		if(areas.at(j)>MAX_AREA || areas.at(j)<MIN_AREA ) // 10000 400
			contours.erase(contours.begin()+j);
	}
	Mat out = Mat::zeros(Size(img.cols,img.rows), CV_8U);
	for (int idx = 0; idx < contours.size(); idx++)
		drawContours(out, contours, idx, Scalar(255,255,255), CV_FILLED, 8);
	return out;
}
示例#11
0
// Main Real-Time Loop
DetectedObject Sample_Detector::run( Mat& image, 
				     Mat& maskOutput,
				     const char* fname)
{
  DetectedObject object;
  object.state = HIDDEN;

  Mat hsvMask = Mat::zeros(image.size(), CV_8UC3);
  Mat grayMask = Mat::zeros(image.size(), CV_8UC3);
  vector<RotatedRect> hsv_tracked_objects = hsv_method(image, hsvMask);
  vector<RotatedRect> gray_tracked_objects = grayscale_method(image, grayMask);
  vector<RotatedRect> tracked_objects;

  if ( hsv_tracked_objects.size() > 0 && gray_tracked_objects.size() > 0 )
    {
      Mat AND_image;
      bitwise_and(hsv_filtered_image, grayscale_filtered_image, AND_image);
      cv::imwrite("Sample-07-Bitwise-AND-Filtered.png", AND_image);

      Mat bitwise_and_tracked;
      tracked_objects = obj_tracker.track(image, AND_image, maskOutput);
      cv::imwrite("Sample-08-Bitwise-AND-Tracked.png", maskOutput);
      std::cout << "OBJECT FOUND!!!!!" << std::endl;
    } else if ( hsv_tracked_objects.size() > 0 )
    {
      tracked_objects = hsv_tracked_objects;
      maskOutput = hsvMask;
    } else if ( gray_tracked_objects.size() > 0 )
    {
      tracked_objects = gray_tracked_objects;
      maskOutput = grayMask;
    }

  if ( tracked_objects.size() > 0 )
    {
      object.state = DETECTED;
      object.x = tracked_objects[0].center.x;
      object.y = tracked_objects[0].center.y;
      object.angle = tracked_objects[0].angle;
      Size objSize = tracked_objects[0].size;
      if ( objSize.height > objSize.width )
	{
	  object.angle += 90.0f;
	}
    }

  return object;
}
示例#12
0
void CmEvaluation::EvalueMask(CStr gtW, CStr &maskDir, vecS &des, CStr resFile, double betaSqr, bool alertNul, CStr suffix)
{
	vecS namesNS; 
	string gtDir, gtExt;
	int imgNum = CmFile::GetNamesNE(gtW, namesNS, gtDir, gtExt);
	int methodNum = (int)des.size();
	vecD pr(methodNum), rec(methodNum), count(methodNum), fm(methodNum);
	for (int i = 0; i < imgNum; i++){
		Mat truM = imread(gtDir + namesNS[i] + gtExt, CV_LOAD_IMAGE_GRAYSCALE);
		for (int m = 0; m < methodNum; m++)	{
			string mapName = maskDir + namesNS[i] + "_" + des[m];
			mapName += suffix.empty() ? ".png" : "_" + suffix + ".png";
			Mat res = imread(mapName, CV_LOAD_IMAGE_GRAYSCALE);
			if (truM.data == NULL || res.data == NULL || truM.size != res.size){
				if (alertNul)
					printf("Truth(%d, %d), Res(%d, %d): %s\n", truM.cols, truM.rows, res.cols, res.rows, _S(mapName));
				continue;
			}
			compare(truM, 128, truM, CMP_GE);
			compare(res, 128, res, CMP_GE);
			Mat commMat;
			bitwise_and(truM, res, commMat);
			double commV = sum(commMat).val[0];
			double p = commV/(sum(res).val[0] + EPS);
			double r = commV/(sum(truM).val[0] + EPS);
			pr[m] += p;
			rec[m] += r;
			count[m]++;
		}
	}

	for (int m = 0; m < methodNum; m++){
		pr[m] /= count[m], rec[m] /= count[m];
		fm[m] = (1 + betaSqr) * pr[m] * rec[m] / (betaSqr * pr[m] + rec[m] + EPS);
	}

	FILE *f; 
	fopen_s(&f, _S(resFile), "a");
	CV_Assert(f != NULL);
	CmEvaluation::PrintVector(f, pr, "PrecisionMask" + suffix);
	CmEvaluation::PrintVector(f, rec, "RecallMask" + suffix);
	CmEvaluation::PrintVector(f, fm, "FMeasureMask" + suffix);
	fprintf(f, "bar([%s]');\ntitle('%s');\ngrid on\n", _S("PrecisionMask" + suffix + "; RecallMask" + suffix + "; FMeasureMask" + suffix), _S("Segmentation" + suffix));
	fclose(f);

	if (des.size() == 1)
		printf("Precision = %g, recall = %g, F-Measure = %g\n", pr[0], rec[0], fm[0]);
}
Mat TemporalImage::CalculateAnd()
{
    Mat img(videoInputFormat.nHeight, videoInputFormat.nWidth, CV_8UC1, Scalar(255));

    for (tUInt i = 0; i < bufferSize; ++i)
    {
        // skip buffered image if empty
        if (0 == buffer[i].rows)
        {
            continue;
        }

        bitwise_and(img, buffer[i], img);
    }

    return img;
}
void ASiftDetector::detectAndCompute(const Mat& img, std::vector< KeyPoint >& keypoints, Mat& descriptors)
{
    keypoints.clear();
    descriptors = Mat(0, 128, CV_32F);
    for(int tl = 1; tl < 6; tl++)
    {
        double t = pow(2, 0.5*tl);
        for(int phi = 0; phi < 180; phi += 72.0/t)
        {
            std::vector<KeyPoint> kps;
            Mat desc;

            Mat timg, mask, Ai;
            img.copyTo(timg);

            affineSkew(t, phi, timg, mask, Ai);

#if 0
            Mat img_disp;
            bitwise_and(mask, timg, img_disp);
            namedWindow( "Skew", WINDOW_AUTOSIZE );// Create a window for display.
            imshow( "Skew", img_disp );
            waitKey(0);
#endif

            SiftFeatureDetector detector;
            detector.detect(timg, kps, mask);

            SiftDescriptorExtractor extractor;
            extractor.compute(timg, kps, desc);

            for(unsigned int i = 0; i < kps.size(); i++)
            {
                Point3f kpt(kps[i].pt.x, kps[i].pt.y, 1);
                Mat kpt_t = Ai*Mat(kpt);
                kps[i].pt.x = kpt_t.at<float>(0,0);
                kps[i].pt.y = kpt_t.at<float>(1,0);
            }
            keypoints.insert(keypoints.end(), kps.begin(), kps.end());
            descriptors.push_back(desc);
        }
    }
}
示例#15
0
int maskImage(Mat img, Mat& retVal)
{
    if (!img.data || !retVal.data)
    {
        printf("Invalid input image\n");
        return 0;
    }

    if (img.channels() != retVal.channels())
    {
        pritnf("Number of channels should be same\n");
        return 0;
    }

    bitwise_and(img, retVal, retVal);
    if (retVal.size() != img.size())
    {
        return 0;
    }
    return 1;
}
示例#16
0
void mattingMethod::getFBimg(Mat& img)
{
	Mat tmp;
	Mat fmask;
	Mat bmask;
	Mat fimg;
	Mat bimg;

	GaussianBlur(trimap,tmp,Size(1,1),1.5);

	compare(tmp,255*((double)th_FB/100.0),fmask,CMP_GT);
	trimap.setTo(255,fmask);
	compare(tmp,255.0*(1.0-th_FB/100.0),bmask,CMP_LT);
	trimap.setTo(0,bmask);

	int d = 2*r_Wgauss+1;
	weightedGaussianFilter(img,fmask,fimg,Size(d,d),sigma_Wgauss);
	weightedGaussianFilter(img,bmask,bimg,Size(d,d),sigma_Wgauss);

	Mat gb,gf;
	cvtColor(bimg,gb,CV_BGR2GRAY);
	cvtColor(fimg,gf,CV_BGR2GRAY);
	Mat fmask2,bmask2;
	compare(gb,0,bmask2,CMP_NE);
	compare(gf,0,fmask2,CMP_NE);
	bitwise_and(bmask2,fmask2,tmp);

	img.copyTo(bimg,~tmp);
	img.copyTo(fimg,~tmp);
	bitwise_or(fmask,bmask,tmp);
	img.copyTo(fimg,tmp);
	img.copyTo(bimg,tmp);

	fimg.copyTo(f,~trimask);
	bimg.copyTo(b);
	trimap.setTo(128,trimask);
	trimap.copyTo(a,~trimask);

}
示例#17
0
Mat TableObjectDetector::getClosestPoints(Mat depthWorld, double depthLimit) {
    Mat ltLimit = depthWorld < depthLimit;
    Mat gtZero = depthWorld > 0.0;
    Mat depthToConsider;
    bitwise_and(ltLimit, gtZero, depthToConsider);
    int Nconsider = sum(depthToConsider)[2]/255;
        
    int vind = 0;
    Mat P(Nconsider, 3, CV_64FC1);
    for (int x=0; x<depthWorld.cols; x++) {
        for (int y=0; y<depthWorld.rows; y++) {
            double z = depthWorld.at<Vec3d>(y, x)[2];
            if (z > 0.0 && z < depthLimit) {
                P.at<double>(vind, 0) = depthWorld.at<Vec3d>(y, x)[0];
                P.at<double>(vind, 1) = depthWorld.at<Vec3d>(y, x)[1];
                P.at<double>(vind, 2) = depthWorld.at<Vec3d>(y, x)[2];
                
                vind++;
            }
        }
    }
    
    return P;
}
示例#18
0
void SetCard::DetectShading(void)
{
	Mat S;
	Mat E;
    bitwise_and(mCutBW, mCutMask, S);
	Canny(S, E, 90, 200, 3);
	int nzE = countNonZero(E);
    int nzM = countNonZero(mCutMask);
    //show(mCutBW);
    //show(mCutMask);
    //show(S);
    //show(E);
	float dEM = float(nzE)/float(nzM);
    if (dEM < mOptions->mShadingLow){
        mCardProperties.mShading = CARD_SHADING_SOLID;
    } else if (dEM > mOptions->mShadingHigh){
        mCardProperties.mShading = CARD_SHADING_STRIPED;
	} else {
        mCardProperties.mShading = CARD_SHADING_OPEN;
	}

    mCardProperties.mShadingProp = dEM;

}
示例#19
0
void Detector::doPutSpectaclesOnFace(const Rect face, vector<Rect>::const_iterator eye )
{
    //assumption: spectacles should be larger than detected eyes, and approximately as wide as a face
    int left = face.x;
    int right = left+face.width;
    int scaledHeight = spectacles.rows*(right-left)*1./spectacles.cols;
    int top = (*eye).y +((*eye).height/2) - scaledHeight/2;
    if (top<0) top=1;
    int bottom = top+scaledHeight;

    //resize spectacles and the copy mask
    Mat scaledSpecs(bottom-top, right-left, CV_8UC1);
    Mat scaledSpecsMask(scaledSpecs.size(), CV_8UC1);
    resize(spectacles, scaledSpecs,scaledSpecs.size() );
    doThreshold(scaledSpecs, scaledSpecsMask, 160, 255, CV_THRESH_BINARY_INV);
    //resize(specMask,scaledSpecsMask, scaledSpecs.size());

    //put on target
    const Rect dstRect(left, top, right-left, bottom-top);
    Mat target(image,dstRect );
    bitwise_and(image(dstRect), scaledSpecs, target, scaledSpecsMask);
    bitwise_or(image(dstRect), scaledSpecs, target, scaledSpecsMask);

 }
示例#20
0
  // Gets the hue/sat/val for areas that we believe are license plate characters
  // Then uses that to filter the whole image and provide a mask.
  void ColorFilter::findCharColors()
  {
    int MINIMUM_SATURATION = 45;

    if (this->debug)
      cout << "ColorFilter::findCharColors" << endl;

    //charMask.copyTo(this->colorMask);
    this->colorMask = Mat::zeros(charMask.size(), CV_8U);
    bitwise_not(this->colorMask, this->colorMask);

    Mat erodedCharMask(charMask.size(), CV_8U);
    Mat element = getStructuringElement( 1,
                                         Size( 2 + 1, 2+1 ),
                                         Point( 1, 1 ) );
    erode(charMask, erodedCharMask, element);

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

    vector<float> hMeans, sMeans, vMeans;
    vector<float> hStdDevs, sStdDevs, vStdDevs;

    for (unsigned int i = 0; i < contours.size(); i++)
    {
      if (hierarchy[i][3] != -1)
        continue;

      Mat singleCharMask = Mat::zeros(hsv.size(), CV_8U);

      drawContours(singleCharMask, contours,
                   i, // draw this contour
                   cv::Scalar(255,255,255), // in
                   CV_FILLED,
                   8,
                   hierarchy
                  );

      // get rid of the outline by drawing a 1 pixel width black line
      drawContours(singleCharMask, contours,
                   i, // draw this contour
                   cv::Scalar(0,0,0), // in
                   1,
                   8,
                   hierarchy
                  );

      //drawAndWait(&singleCharMask);

      Scalar mean;
      Scalar stddev;
      meanStdDev(hsv, mean, stddev, singleCharMask);

      if (this->debug)
      {
        cout << "ColorFilter " << setw(3) << i << ". Mean:  h: " << setw(7) << mean[0] << " s: " << setw(7) <<mean[1] << " v: " << setw(7) << mean[2]
             << " | Std: h: " << setw(7) <<stddev[0] << " s: " << setw(7) <<stddev[1] << " v: " << stddev[2] << endl;
      }

      if (mean[0] == 0 && mean[1] == 0 && mean[2] == 0)
        continue;

      hMeans.push_back(mean[0]);
      sMeans.push_back(mean[1]);
      vMeans.push_back(mean[2]);
      hStdDevs.push_back(stddev[0]);
      sStdDevs.push_back(stddev[1]);
      vStdDevs.push_back(stddev[2]);
    }

    if (hMeans.size() == 0)
      return;

    int bestHueIndex = this->getMajorityOpinion(hMeans, .65, 30);
    int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35);
    int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30);

    if (sMeans[bestSatIndex] < MINIMUM_SATURATION)
      return;

    bool doHueFilter = false, doSatFilter = false, doValFilter = false;
    float hueMin, hueMax;
    float satMin, satMax;
    float valMin, valMax;

    if (this->debug)
      cout << "ColorFilter Winning indices:" << endl;
    if (bestHueIndex != -1)
    {
      doHueFilter = true;
      hueMin = hMeans[bestHueIndex] - (2 * hStdDevs[bestHueIndex]);
      hueMax = hMeans[bestHueIndex] + (2 * hStdDevs[bestHueIndex]);

      if (abs(hueMin - hueMax) < 20)
      {
        hueMin = hMeans[bestHueIndex] - 20;
        hueMax = hMeans[bestHueIndex] + 20;
      }

      if (hueMin < 0)
        hueMin = 0;
      if (hueMax > 180)
        hueMax = 180;

      if (this->debug)
        cout << "ColorFilter Hue: " << bestHueIndex << " : " << setw(7) << hMeans[bestHueIndex] << " -- " << hueMin << "-" << hueMax << endl;
    }
    if (bestSatIndex != -1)
    {
      doSatFilter = true;

      satMin = sMeans[bestSatIndex] - (2 * sStdDevs[bestSatIndex]);
      satMax = sMeans[bestSatIndex] + (2 * sStdDevs[bestSatIndex]);

      if (abs(satMin - satMax) < 20)
      {
        satMin = sMeans[bestSatIndex] - 20;
        satMax = sMeans[bestSatIndex] + 20;
      }

      if (satMin < 0)
        satMin = 0;
      if (satMax > 255)
        satMax = 255;

      if (this->debug)
        cout << "ColorFilter Sat: " << bestSatIndex << " : " << setw(7) << sMeans[bestSatIndex] << " -- " << satMin << "-" << satMax << endl;
    }
    if (bestValIndex != -1)
    {
      doValFilter = true;

      valMin = vMeans[bestValIndex] - (1.5 * vStdDevs[bestValIndex]);
      valMax = vMeans[bestValIndex] + (1.5 * vStdDevs[bestValIndex]);

      if (abs(valMin - valMax) < 20)
      {
        valMin = vMeans[bestValIndex] - 20;
        valMax = vMeans[bestValIndex] + 20;
      }

      if (valMin < 0)
        valMin = 0;
      if (valMax > 255)
        valMax = 255;

      if (this->debug)
        cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax  << endl;
    }

    Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type());
    Mat imgDebug = Mat::zeros(hsv.size(), hsv.type());
    Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U);
    Mat debugMask = Mat::zeros(hsv.size(), CV_8U);
    bitwise_not(debugMask, debugMask);

    for (int row = 0; row < charMask.rows; row++)
    {
      for (int col = 0; col < charMask.cols; col++)
      {
        int h = (int) hsv.at<Vec3b>(row, col)[0];
        int s = (int) hsv.at<Vec3b>(row, col)[1];
        int v = (int) hsv.at<Vec3b>(row, col)[2];

        bool hPasses = true;
        bool sPasses = true;
        bool vPasses = true;

        int vDistance = abs(v - vMeans[bestValIndex]);

        imgDebugHueOnly.at<Vec3b>(row, col)[0] = h;
        imgDebugHueOnly.at<Vec3b>(row, col)[1] = 255;
        imgDebugHueOnly.at<Vec3b>(row, col)[2] = 255;

        imgDebug.at<Vec3b>(row, col)[0] = 255;
        imgDebug.at<Vec3b>(row, col)[1] = 255;
        imgDebug.at<Vec3b>(row, col)[2] = 255;

        if (doHueFilter && (h < hueMin || h > hueMax))
        {
          hPasses = false;
          imgDebug.at<Vec3b>(row, col)[0] = 0;
          debugMask.at<uchar>(row, col) = 0;
        }
        if (doSatFilter && (s < satMin || s > satMax))
        {
          sPasses = false;
          imgDebug.at<Vec3b>(row, col)[1] = 0;
        }
        if (doValFilter && (v < valMin || v > valMax))
        {
          vPasses = false;
          imgDebug.at<Vec3b>(row, col)[2] = 0;
        }

        //if (pixelPasses)
        //  colorMask.at<uchar>(row, col) = 255;
        //else
        //imgDebug.at<Vec3b>(row, col)[0] = hPasses & 255;
        //imgDebug.at<Vec3b>(row, col)[1] = sPasses & 255;
        //imgDebug.at<Vec3b>(row, col)[2] = vPasses & 255;

        if ((hPasses) ||  (hPasses && sPasses))//(hPasses && vPasses) || (sPasses && vPasses) ||
          this->colorMask.at<uchar>(row, col) = 255;
        else
          this->colorMask.at<uchar>(row, col) = 0;

        if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses))
        {
          vDistance = pow(vDistance, 0.9);
        }
        else
        {
          vDistance = pow(vDistance, 1.1);
        }
        if (vDistance > 255)
          vDistance = 255;
        imgDistanceFromCenter.at<uchar>(row, col) = vDistance;
      }
    }

    vector<Mat> debugImagesSet;

    if (this->debug)
    {
      debugImagesSet.push_back(addLabel(charMask, "Charecter mask"));
      //debugImagesSet1.push_back(erodedCharMask);
      Mat maskCopy(colorMask.size(), colorMask.type());
      colorMask.copyTo(maskCopy);
      debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before"));
    }

    Mat bigElement = getStructuringElement( 1,
                                            Size( 3 + 1, 3+1 ),
                                            Point( 1, 1 ) );

    Mat smallElement = getStructuringElement( 1,
                       Size( 1 + 1, 1+1 ),
                       Point( 1, 1 ) );

    morphologyEx(this->colorMask, this->colorMask, MORPH_CLOSE, bigElement);
    //dilate(this->colorMask, this->colorMask, bigElement);

    Mat combined(charMask.size(), charMask.type());
    bitwise_and(charMask, colorMask, combined);

    if (this->debug)
    {
      debugImagesSet.push_back(addLabel(colorMask, "Color Mask After"));

      debugImagesSet.push_back(addLabel(combined, "Combined"));

      //displayImage(config, "COLOR filter Mask", colorMask);
      debugImagesSet.push_back(addLabel(imgDebug, "Color filter Debug"));

      cvtColor(imgDebugHueOnly, imgDebugHueOnly, CV_HSV2BGR);
      debugImagesSet.push_back(addLabel(imgDebugHueOnly, "Color Filter Hue"));

      equalizeHist(imgDistanceFromCenter, imgDistanceFromCenter);
      debugImagesSet.push_back(addLabel(imgDistanceFromCenter, "COLOR filter Distance"));

      debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off"));

      Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3);
      displayImage(config, "Color Filter Images", dashboard);
    }
  }
示例#21
0
void CharacterSegmenter::filterEdgeBoxes(vector<Mat> thresholds, const vector<Rect> charRegions, float avgCharWidth, float avgCharHeight)
{
  const float MIN_ANGLE_FOR_ROTATION = 0.4;
  int MIN_CONNECTED_EDGE_PIXELS = (avgCharHeight * 1.5);
  
  // Sometimes the rectangle won't be very tall, making it impossible to detect an edge
  // Adjust for this here.
  int alternate = thresholds[0].rows * 0.92;
  if (alternate < MIN_CONNECTED_EDGE_PIXELS && alternate > avgCharHeight)
    MIN_CONNECTED_EDGE_PIXELS = alternate;
  
  // 
  // Pay special attention to the edge boxes.  If it's a skinny box, and the vertical height extends above our bounds... remove it.
  //while (charBoxes.size() > 0 && charBoxes[charBoxes.size() - 1].width < MIN_SEGMENT_WIDTH_EDGES)
  //  charBoxes.erase(charBoxes.begin() + charBoxes.size() - 1);
  // Now filter the "edge" boxes.  We don't want to include skinny boxes on the edges, since these could be plate boundaries
  //while (charBoxes.size() > 0 && charBoxes[0].width < MIN_SEGMENT_WIDTH_EDGES)
  //  charBoxes.erase(charBoxes.begin() + 0);  
  
    
  // TECHNIQUE #1
  // Check for long vertical lines.  Once the line is too long, mask the whole region
  
  if (charRegions.size() <= 1)
    return;
  
  // Check both sides to see where the edges are
  // The first starts at the right edge of the leftmost char region and works its way left
  // The second starts at the left edge of the rightmost char region and works its way right.
  // We start by rotating the threshold image to the correct angle
  // then check each column 1 by 1.
    
  vector<int> leftEdges;
  vector<int> rightEdges;
  
  for (int i = 0; i < thresholds.size(); i++)
  {
    Mat rotated;
    
    if (top.angle > MIN_ANGLE_FOR_ROTATION)
    {
      // Rotate image:
      rotated = Mat(thresholds[i].size(), thresholds[i].type());
      Mat rot_mat( 2, 3, CV_32FC1 );
      Point center = Point( thresholds[i].cols/2, thresholds[i].rows/2 );
      
      rot_mat = getRotationMatrix2D( center, top.angle, 1.0 );
      warpAffine( thresholds[i], rotated, rot_mat, thresholds[i].size() );
    }
    else
    {
	rotated = thresholds[i];
    }

    int leftEdgeX = 0;
    int rightEdgeX = rotated.cols;
    // Do the left side
    int col = charRegions[0].x + charRegions[0].width;
    while (col >= 0)
    {
      
      int rowLength = getLongestBlobLengthBetweenLines(rotated, col);
      
      if (rowLength > MIN_CONNECTED_EDGE_PIXELS)
      {
	leftEdgeX = col;
	break;
      }
      
      col--;
    }
    
    col = charRegions[charRegions.size() - 1].x;
    while (col < rotated.cols)
    {
      
      int rowLength = getLongestBlobLengthBetweenLines(rotated, col);
      
      if (rowLength > MIN_CONNECTED_EDGE_PIXELS)
      {
	rightEdgeX = col;
	break;
      }
      col++;
    }
    
    
    if (leftEdgeX != 0)
      leftEdges.push_back(leftEdgeX);
    if (rightEdgeX != thresholds[i].cols)
      rightEdges.push_back(rightEdgeX);
    
  }
  
  int leftEdge = 0;
  int rightEdge = thresholds[0].cols;
  
  // Assign the edge values to the SECOND closest value
  if (leftEdges.size() > 1)
  {
    sort (leftEdges.begin(), leftEdges.begin()+leftEdges.size());
    leftEdge = leftEdges[leftEdges.size() - 2] + 1;
  }
  if (rightEdges.size() > 1)
  {
    sort (rightEdges.begin(), rightEdges.begin()+rightEdges.size());
    rightEdge = rightEdges[1] - 1;
  }
  
  if (leftEdge != 0 || rightEdge != thresholds[0].cols)
  {
    Mat mask = Mat::zeros(thresholds[0].size(), CV_8U);
    rectangle(mask, Point(leftEdge, 0), Point(rightEdge, thresholds[0].rows), Scalar(255,255,255), -1);
    
    if (top.angle > MIN_ANGLE_FOR_ROTATION)
    {
      // Rotate mask:
      Mat rot_mat( 2, 3, CV_32FC1 );
      Point center = Point( mask.cols/2, mask.rows/2 );
      
      rot_mat = getRotationMatrix2D( center, top.angle * -1, 1.0 );
      warpAffine( mask, mask, rot_mat, mask.size() );
    }

    
    // If our edge mask covers more than x% of the char region, mask the whole thing...
    const float MAX_COVERAGE_PERCENT = 0.6;
    int leftCoveragePx = leftEdge - charRegions[0].x;
    float leftCoveragePercent = ((float) leftCoveragePx) / ((float) charRegions[0].width);
    float rightCoveragePx = (charRegions[charRegions.size() -1].x + charRegions[charRegions.size() -1].width) - rightEdge;
    float rightCoveragePercent = ((float) rightCoveragePx) / ((float) charRegions[charRegions.size() -1].width);
    if ((leftCoveragePercent > MAX_COVERAGE_PERCENT) ||
      (charRegions[0].width - leftCoveragePx < config->segmentationMinBoxWidthPx))
    {
      rectangle(mask, charRegions[0], Scalar(0,0,0), -1);	// Mask the whole region
      if (this->config->debugCharSegmenter)
	cout << "Edge Filter: Entire left region is erased" << endl;
    }
    if ((rightCoveragePercent > MAX_COVERAGE_PERCENT) ||
      (charRegions[charRegions.size() -1].width - rightCoveragePx < config->segmentationMinBoxWidthPx))
    {
      rectangle(mask, charRegions[charRegions.size() -1], Scalar(0,0,0), -1);
      if (this->config->debugCharSegmenter)
	cout << "Edge Filter: Entire right region is erased" << endl;
    }
    
    for (int i = 0; i < thresholds.size(); i++)
    {
      bitwise_and(thresholds[i], mask, thresholds[i]);
    }
    
    
    if (this->config->debugCharSegmenter)
    {
      cout << "Edge Filter: left=" << leftEdge << " right=" << rightEdge << endl;  
      Mat bordered = addLabel(mask, "Edge Filter #1");
      imgDbgGeneral.push_back(bordered);
      
      Mat invertedMask(mask.size(), mask.type());
      bitwise_not(mask, invertedMask);
      for (int z = 0; z < imgDbgCleanStages.size(); z++)
	fillMask(imgDbgCleanStages[z], invertedMask, Scalar(0,0,255));
    }
  }
  
  // TECHNIQUE #2
  // Check for tall skinny blobs on the edge boxes.  If they're too long and skinny, maks the whole char region
  /*
   * 
  float MIN_EDGE_CONTOUR_HEIGHT = avgCharHeight * 0.7;
  float MIN_EDGE_CONTOUR_AREA_PCT = avgCharHeight * 0.1;
   
  for (int i = 0; i < thresholds.size(); i++)
  {
      // Just check the first and last char box.  If the contour extends too far above/below the line.  Drop it.
      
      for (int boxidx = 0; boxidx < charRegions.size(); boxidx++)
      {
	if (boxidx != 0 || boxidx != charRegions.size() -1)
	{
	  // This is a middle box.  we never want to filter these here.
	  continue;
	}
	
	vector<vector<Point> > contours;
	Mat mask = Mat::zeros(thresholds[i].size(),CV_8U);
	rectangle(mask, charRegions[boxidx], Scalar(255,255,255), CV_FILLED);
	
	bitwise_and(thresholds[i], mask, mask);
	findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
	//int tallContourIndex = isSkinnyLineInsideBox(thresholds[i], charRegions[boxidx], allContours[i], hierarchy[i], avgCharWidth, avgCharHeight);
	float tallestContourHeight = 0;
	float fattestContourWidth = 0;
	float biggestContourArea = 0;
	for (int c = 0; c < contours.size(); c++)
	{
	    Rect r = boundingRect(contours[c]);
	    if (r.height > tallestContourHeight)
	      tallestContourHeight = r.height;
	    if (r.width > fattestContourWidth)
	      fattestContourWidth = r.width;
	    float a = r.area();
	    if (a > biggestContourArea)
	      biggestContourArea = a;
	}
	
	float minArea = charRegions[boxidx].area() * MIN_EDGE_CONTOUR_AREA_PCT;
	if ((fattestContourWidth < MIN_BOX_WIDTH_PX) || 
	  (tallestContourHeight < MIN_EDGE_CONTOUR_HEIGHT) ||
	  (biggestContourArea < minArea)
	)
	{
	  // Find a good place to MASK this contour.
	  // for now, just mask the whole thing
	  if (this->debug)
	  {
	    
	    rectangle(imgDbgCleanStages[i], charRegions[boxidx], COLOR_DEBUG_EDGE, 2);
	    cout << "Edge Filter: threshold " << i << " box " << boxidx << endl;
	  }
	  rectangle(thresholds[i], charRegions[boxidx], Scalar(0,0,0), -1);
	}
	else
	{
	  filteredCharRegions.push_back(charRegions[boxidx]);  
	}
      }
  }
  */
  
}
示例#22
0
/* Find cell soma */
bool findCellSoma( std::vector<cv::Point> nucleus_contour, 
                   cv::Mat cell_mask, 
                   cv::Mat *intersection, 
                   std::vector<cv::Point> *soma_contour ) {

    bool status = false;

    // Calculate radius and center of the nucleus
    cv::Moments mu = moments(nucleus_contour, true);
    cv::Point2f mc = cv::Point2f(   static_cast<float>(mu.m10/mu.m00), 
                                    static_cast<float>(mu.m01/mu.m00)   );
    // Nucleus' region of influence
    cv::Mat roi_mask = cv::Mat::zeros(cell_mask.size(), CV_8UC1);
    float roi_radius = (float) (SOMA_FACTOR * DAPI_MASK_RADIUS);
    cv::circle(roi_mask, mc, roi_radius, 255, -1, 8);
    cv::circle(roi_mask, mc, DAPI_MASK_RADIUS, 0, -1, 8);
    int circle_score = countNonZero(roi_mask);

    // Soma present in ROI
    bitwise_and(roi_mask, cell_mask, *intersection);
    int intersection_score = countNonZero(*intersection);

    // Add the dapi contour to intersection region
    cv::circle(*intersection, mc, DAPI_MASK_RADIUS, 255, -1, 8);

    // Add to the soma mask if coverage area exceeds a certain threshold
    float ratio = ((float) intersection_score) / circle_score;
    if (ratio >= COVERAGE_RATIO) {

        // Segment
        cv::Mat soma_segmented;
        std::vector<std::vector<cv::Point>> contours_soma;
        std::vector<cv::Vec4i> hierarchy_soma;
        std::vector<HierarchyType> soma_contour_mask;
        std::vector<double> soma_contour_area;
        contourCalc(    *intersection, 
                        ChannelType::DAPI, 
                        1.0, 
                        &soma_segmented, 
                        &contours_soma, 
                        &hierarchy_soma, 
                        &soma_contour_mask, 
                        &soma_contour_area
                   );

        double max_area  = 0.0;
        for (size_t i = 0; i < contours_soma.size(); i++) {
            if (soma_contour_mask[i] != HierarchyType::PARENT_CNTR) continue;
            if (contours_soma[i].size() < 5) continue;
            if (soma_contour_area[i] < MIN_SOMA_SIZE) continue;

            // Find the largest permissible contour
            if (soma_contour_area[i] > max_area) {
                max_area = soma_contour_area[i];
                *soma_contour = contours_soma[i];
                status = true;
            }
        }
    }
    return status;
}
示例#23
0
/* Process the images inside each directory */
bool processDir(std::string path, std::string image_name, std::string metrics_file) {

    /** Create the initial data collection skeleton **/

    // Open the metrics file
    std::ofstream data_stream;
    data_stream.open(metrics_file, std::ios::app);
    if (!data_stream.is_open()) {
        std::cerr << "Could not open the data output file." << std::endl;
        return false;
    }

    // Create the output image directory
    std::string out_directory = path + "result/";
    struct stat st = {0};
    if (stat(out_directory.c_str(), &st) == -1) {
        mkdir(out_directory.c_str(), 0700);
    }

    // Analyzed image name
    std::string analyzed_image_name = image_name;
    std::size_t found = analyzed_image_name.find("dapi");
    analyzed_image_name.replace(found, 4, "merge");
    data_stream << analyzed_image_name << ",";

    /** Extract the dapi, gfp and rfp streams for each input image **/

    // DAPI
    std::string in_filename = path + "jpg/" + image_name;
    cv::Mat dapi = cv::imread(in_filename.c_str(), -1);
    if (dapi.empty()) return false;

    // GFP
    std::string gfp_image_name = image_name;
    found = gfp_image_name.find("dapi");
    gfp_image_name.replace(found, 4, "gfp");
    in_filename = path + "jpg/" + gfp_image_name;
    cv::Mat gfp = cv::imread(in_filename.c_str(), -1);
    if (gfp.empty()) return false;

    // RFP
    std::string rfp_image_name = image_name;
    found = rfp_image_name.find("dapi");
    rfp_image_name.replace(found, 4, "rfp");
    in_filename = path + "jpg/" + rfp_image_name;
    cv::Mat rfp = cv::imread(in_filename.c_str(), -1);
    if (rfp.empty()) return false;


    /** Gather information needed for feature extraction **/

    /* DAPI image */
    // Enhance
    cv::Mat dapi_normalized, dapi_enhanced;
    if (!enhanceImage(  dapi, 
                        ChannelType::DAPI, 
                        &dapi_normalized, 
                        &dapi_enhanced  )) {
        return false;
    }

    // Segment
    cv::Mat dapi_segmented;
    std::vector<std::vector<cv::Point>> contours_dapi;
    std::vector<cv::Vec4i> hierarchy_dapi;
    std::vector<HierarchyType> dapi_contour_mask;
    std::vector<double> dapi_contour_area;
    contourCalc(dapi_enhanced, ChannelType::DAPI, 1.0, 
                &dapi_segmented, &contours_dapi, 
                &hierarchy_dapi, &dapi_contour_mask, 
                &dapi_contour_area);

    // Filter the dapi contours
    std::vector<std::vector<cv::Point>> contours_dapi_filtered;
    filterCells(dapi_enhanced, contours_dapi, dapi_contour_mask, &contours_dapi_filtered);


    /* GFP image */
    cv::Mat gfp_normalized, gfp_enhanced;
    if (!enhanceImage(  gfp, 
                        ChannelType::GFP, 
                        &gfp_normalized, 
                        &gfp_enhanced   )) {
        return false;
    }

    // GFP Low
    cv::Mat gfp_low_normalized, gfp_low_enhanced;
    if (!enhanceImage(  gfp, 
                        ChannelType::GFP_LOW, 
                        &gfp_low_normalized, 
                        &gfp_low_enhanced   )) {
        return false;
    }
    cv::Mat gfp_low_segmented;
    std::vector<std::vector<cv::Point>> contours_gfp_low;
    std::vector<cv::Vec4i> hierarchy_gfp_low;
    std::vector<HierarchyType> gfp_low_contour_mask;
    std::vector<double> gfp_low_contour_area;
    contourCalc(gfp_low_enhanced, ChannelType::GFP_LOW, 1.0, 
                &gfp_low_segmented, &contours_gfp_low, 
                &hierarchy_gfp_low, &gfp_low_contour_mask, 
                &gfp_low_contour_area);

    // GFP Medium
    cv::Mat gfp_medium_normalized, gfp_medium_enhanced;
    if (!enhanceImage(  gfp, 
                        ChannelType::GFP_MEDIUM, 
                        &gfp_medium_normalized, 
                        &gfp_medium_enhanced   )) {
        return false;
    }
    cv::Mat gfp_medium_segmented;
    std::vector<std::vector<cv::Point>> contours_gfp_medium;
    std::vector<cv::Vec4i> hierarchy_gfp_medium;
    std::vector<HierarchyType> gfp_medium_contour_mask;
    std::vector<double> gfp_medium_contour_area;
    contourCalc(gfp_medium_enhanced, ChannelType::GFP_MEDIUM, 1.0, 
                &gfp_medium_segmented, &contours_gfp_medium, 
                &hierarchy_gfp_medium, &gfp_medium_contour_mask, 
                &gfp_medium_contour_area);

    // GFP High
    cv::Mat gfp_high_normalized, gfp_high_enhanced;
    if (!enhanceImage(  gfp, 
                        ChannelType::GFP_HIGH, 
                        &gfp_high_normalized, 
                        &gfp_high_enhanced   )) {
        return false;
    }
    cv::Mat gfp_high_segmented;
    std::vector<std::vector<cv::Point>> contours_gfp_high;
    std::vector<cv::Vec4i> hierarchy_gfp_high;
    std::vector<HierarchyType> gfp_high_contour_mask;
    std::vector<double> gfp_high_contour_area;
    contourCalc(gfp_high_enhanced, ChannelType::GFP_HIGH, 1.0, 
                &gfp_high_segmented, &contours_gfp_high, 
                &hierarchy_gfp_high, &gfp_high_contour_mask, 
                &gfp_high_contour_area);

    /* RFP image */
    cv::Mat rfp_normalized, rfp_enhanced_type1;
    if (!enhanceImage(  rfp, 
                        ChannelType::RFP_TYPE1, 
                        &rfp_normalized, 
                        &rfp_enhanced_type1 )) {
        return false;
    }
    cv::Mat rfp_enhanced_type2;
    if (!enhanceImage(  rfp, 
                        ChannelType::RFP_TYPE2, 
                        &rfp_normalized, 
                        &rfp_enhanced_type2 )) {
        return false;
    }
    cv::Mat rfp_segmented;
    std::vector<std::vector<cv::Point>> contours_rfp_vec;
    std::vector<cv::Vec4i> hierarchy_rfp;
    std::vector<HierarchyType> rfp_contour_mask;
    std::vector<double> rfp_contour_area;
    contourCalc(rfp_enhanced_type2, ChannelType::RFP_TYPE2, 1.0, 
                &rfp_segmented, &contours_rfp_vec, 
                &hierarchy_rfp, &rfp_contour_mask, 
                &rfp_contour_area);

    /* RFP Scatter plot */
    // Determine whether the image is Control or SZ
    bool is_control = false;
    std::string sample_id = image_name.substr(0, 4);
    // Control - 3440, 3651, 4506, 9319, 9429, BJ2E, BJ3E
    if (    (sample_id == "3440") ||
            (sample_id == "3651") ||
            (sample_id == "4506") ||
            (sample_id == "9319") ||
            (sample_id == "9429") ||
            (sample_id == "BJ2E") ||
            (sample_id == "BJ3E")  ) {
        is_control = true;
    }
    // Note: Do nothing for SZ - 1792, 1835, 2038, 2497

    scatterPlot(    path + PLOTS_DIR_NAME,
                    is_control,
                    rfp_normalized,
                    contours_rfp_vec,
                    rfp_contour_mask    );


    /** Classify the cell soma **/

    std::vector<std::vector<cv::Point>> contours_gfp, contours_rfp;
    cv::Mat gfp_intersection = cv::Mat::zeros(gfp_enhanced.size(), CV_8UC1);
    cv::Mat rfp_intersection = cv::Mat::zeros(rfp_enhanced_type1.size(), CV_8UC1);
    for (size_t i = 0; i < contours_dapi_filtered.size(); i++) {

        // Find DAPI-GFP Cell Soma
        std::vector<cv::Point> gfp_contour;
        cv::Mat temp;
        if (findCellSoma( contours_dapi_filtered[i], gfp_enhanced, &temp, &gfp_contour )) {
            contours_gfp.push_back(gfp_contour);
            bitwise_or(gfp_intersection, temp, gfp_intersection);
            cv::Mat temp_not;
            bitwise_not(temp, temp_not);
            bitwise_and(gfp_enhanced, temp_not, gfp_enhanced);
        }

        // Find DAPI-RFP Cell Soma
        std::vector<cv::Point> rfp_contour;
        if (findCellSoma( contours_dapi_filtered[i], rfp_enhanced_type1, &temp, &rfp_contour )) {
            contours_rfp.push_back(rfp_contour);
            bitwise_or(rfp_intersection, temp, rfp_intersection);
            cv::Mat temp_not;
            bitwise_not(temp, temp_not);
            bitwise_and(rfp_enhanced_type1, temp_not, rfp_enhanced_type1);
        }
    }


    /** Collect the metrics **/

    // Separation metrics for dapi-gfp cells
    float mean_dia = 0.0, stddev_dia = 0.0;
    float mean_aspect_ratio = 0.0, stddev_aspect_ratio = 0.0;
    float mean_error_ratio = 0.0, stddev_error_ratio = 0.0;
    separationMetrics(  contours_gfp, 
                        &mean_dia, 
                        &stddev_dia, 
                        &mean_aspect_ratio, 
                        &stddev_aspect_ratio, 
                        &mean_error_ratio, 
                        &stddev_error_ratio
                     );
    data_stream << contours_gfp.size() << "," 
                << mean_dia << "," 
                << stddev_dia << "," 
                << mean_aspect_ratio << "," 
                << stddev_aspect_ratio << "," 
                << mean_error_ratio << "," 
                << stddev_error_ratio << ",";

    // Separation metrics for dapi-rfp cells
    mean_dia = 0.0;
    stddev_dia = 0.0;
    mean_aspect_ratio = 0.0;
    stddev_aspect_ratio = 0.0;
    mean_error_ratio = 0.0;
    stddev_error_ratio = 0.0;
    separationMetrics(  contours_rfp, 
                        &mean_dia, 
                        &stddev_dia, 
                        &mean_aspect_ratio, 
                        &stddev_aspect_ratio, 
                        &mean_error_ratio, 
                        &stddev_error_ratio
                     );
    data_stream << contours_rfp.size() << "," 
                << mean_dia << "," 
                << stddev_dia << "," 
                << mean_aspect_ratio << "," 
                << stddev_aspect_ratio << "," 
                << mean_error_ratio << "," 
                << stddev_error_ratio << ",";


    /* Characterize the gfp channel */
    // Gfp low
    std::string gfp_low_output;
    binArea(gfp_low_contour_mask, gfp_low_contour_area, &gfp_low_output);
    data_stream << gfp_low_output << ",";

    // Gfp medium
    std::string gfp_medium_output;
    binArea(gfp_medium_contour_mask, gfp_medium_contour_area, &gfp_medium_output);
    data_stream << gfp_medium_output << ",";

    // Gfp high
    std::string gfp_high_output;
    binArea(gfp_high_contour_mask, gfp_high_contour_area, &gfp_high_output);
    data_stream << gfp_high_output << ",";


    // End of entry
    data_stream << std::endl;
    data_stream.close();


    /** Display the debug image **/

    if (DEBUG_FLAG) {
        // Initialize
        cv::Mat drawing_blue_debug = cv::Mat::zeros(dapi_enhanced.size(), CV_8UC1);
        //cv::Mat drawing_blue_debug  = 2*dapi_normalized;
        //cv::Mat drawing_green_debug = cv::Mat::zeros(gfp_enhanced.size(), CV_8UC1);
        cv::Mat drawing_green_debug = gfp_intersection;
        cv::Mat drawing_red_debug   = cv::Mat::zeros(rfp_enhanced_type1.size(), CV_8UC1);
        //cv::Mat drawing_red_debug = rfp_intersection;

        // Draw DAPI bondaries
        for (size_t i = 0; i < contours_dapi_filtered.size(); i++) {
            cv::Moments mu = moments(contours_dapi_filtered[i], true);
            cv::Point2f mc = cv::Point2f(   static_cast<float>(mu.m10/mu.m00), 
                                            static_cast<float>(mu.m01/mu.m00)   );
            cv::circle(drawing_blue_debug, mc, DAPI_MASK_RADIUS, 255, 1, 8);
            cv::circle(drawing_green_debug, mc, DAPI_MASK_RADIUS, 255, 1, 8);
            cv::circle(drawing_red_debug, mc, DAPI_MASK_RADIUS, 255, 1, 8);
        }

        // Merge the modified red, blue and green layers
        std::vector<cv::Mat> merge_debug;
        merge_debug.push_back(drawing_blue_debug);
        merge_debug.push_back(drawing_green_debug);
        merge_debug.push_back(drawing_red_debug);
        cv::Mat color_debug;
        cv::merge(merge_debug, color_debug);

        // Draw the debug image
        std::string out_debug = out_directory + analyzed_image_name;
        out_debug.insert(out_debug.find_last_of("."), "_debug", 6);
        cv::imwrite(out_debug.c_str(), color_debug);
    }


    /** Display the analyzed <dapi,gfp,rfp> image set **/

    // Initialize
    cv::Mat drawing_blue  = 2*dapi_normalized;
    cv::Mat drawing_green = gfp_normalized;
    cv::Mat drawing_red   = rfp_normalized;

    // Draw GFP bondaries
    for (size_t i = 0; i < contours_gfp.size(); i++) {
        //cv::RotatedRect min_ellipse = fitEllipse(cv::Mat(contours_gfp[i]));
        //ellipse(drawing_blue, min_ellipse, 255, 1, 8);
        //ellipse(drawing_green, min_ellipse, 255, 1, 8);
        //ellipse(drawing_red, min_ellipse, 0, 1, 8);
        drawContours(drawing_blue, contours_gfp, i, 255, 1, 8);
        drawContours(drawing_green, contours_gfp, i, 255, 1, 8);
        drawContours(drawing_red, contours_gfp, i, 0, 1, 8);
    }

    // Draw RFP bondaries
    for (size_t i = 0; i < contours_rfp.size(); i++) {
        //cv::RotatedRect min_ellipse = fitEllipse(cv::Mat(contours_rfp[i]));
        //ellipse(drawing_blue, min_ellipse, 255, 1, 8);
        //ellipse(drawing_green, min_ellipse, 0, 1, 8);
        //ellipse(drawing_red, min_ellipse, 255, 1, 8);
        drawContours(drawing_blue, contours_rfp, i, 255, 1, 8);
        drawContours(drawing_green, contours_rfp, i, 0, 1, 8);
        drawContours(drawing_red, contours_rfp, i, 255, 1, 8);
    }

    // Merge the modified red, blue and green layers
    std::vector<cv::Mat> merge_analyzed;
    merge_analyzed.push_back(drawing_blue);
    merge_analyzed.push_back(drawing_green);
    merge_analyzed.push_back(drawing_red);
    cv::Mat color_analyzed;
    cv::merge(merge_analyzed, color_analyzed);

    // Draw the analyzed image
    std::string out_analyzed = out_directory + analyzed_image_name;
    cv::imwrite(out_analyzed.c_str(), color_analyzed);


    return true;
}
示例#24
0
void Check_Copter(Copter& copter)
{
    bool Flag_1 = false;
    bool Flag_2 = false;
    Mat YUV;
    Mat color1(copter.height , copter.width , CV_8UC1);
    Mat color2(copter.height , copter.width , CV_8UC1);
    Mat color3(copter.height , copter.width , CV_8UC1);
    
    Mat color1_2(copter.height , copter.width , CV_8UC1);
    Mat color1_3(copter.height , copter.width , CV_8UC1);
    
    Mat color2_2(copter.height , copter.width , CV_8UC1);
    Mat color2_3(copter.height , copter.width , CV_8UC1);
    



	Mat Temp_roi;

    vector<vector<Point> > contours1;
    vector<vector<Point> > contours2;
    vector<vector<Point> > contours3;

    vector<Vec4i> hierarchy1;
    vector<Vec4i> hierarchy2;
    vector<Vec4i> hierarchy3;
    
    Rect copter_box1;
    Rect copter_box2;
    Rect copter_box3;
    Rect copter_box4;

    int max_contour1=0;
    int max_contour2=0;
    int max_contour3=0;

    int min_num1 =0x7fffff;
    int min_num2 =0x7fffff;
    int min_num3 =0x7fffff;
    int x1, x2, y1, y2;
    int min_diff =0x7fffff;
    int min_diff2 =0x7fffff; 
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
	double start,end,t1;
	
	pthread_mutex_lock(&mutex);
	cvtColor(copter.Copter_Layer,YUV,CV_RGB2YCrCb);
	pthread_mutex_unlock(&mutex);
	
	vector<Mat> yuv;
	split(YUV,yuv);

//	start=(double)cvGetTickCount();
	
	threshold(yuv[0],yuv[0],copter.Y_MAX,255,THRESH_TOZERO_INV);
	threshold(yuv[0],(color1),copter.Y_MIN,255,THRESH_BINARY);
	threshold(yuv[1],yuv[1],copter.Cb_MAX,255,THRESH_TOZERO_INV);
	threshold(yuv[1],(color1_2),copter.Cb_MIN,255,THRESH_BINARY);
	threshold(yuv[2],yuv[2],copter.Cr_MAX,255,THRESH_TOZERO_INV);
	threshold(yuv[2],(color1_3),copter.Cr_MIN,255,THRESH_BINARY);
	
	bitwise_and(color1,color1_2,color1_2);
	bitwise_and(color1_2,color1_3,color1);

	split(YUV,yuv);
	
	threshold(yuv[0],yuv[0],copter.Y_MAX2,255,THRESH_TOZERO_INV);
	threshold(yuv[0],(color2),copter.Y_MIN2,255,THRESH_BINARY);
	threshold(yuv[1],yuv[1],copter.Cb_MAX2,255,THRESH_TOZERO_INV);
	threshold(yuv[1],(color2_2),copter.Cb_MIN2,255,THRESH_BINARY);
	threshold(yuv[2],yuv[2],copter.Cr_MAX2,255,THRESH_TOZERO_INV);
	threshold(yuv[2],(color2_3),copter.Cr_MIN2,255,THRESH_BINARY);

	bitwise_and(color2,color2_2,color2_2);
	bitwise_and(color2_2,color2_3,color3);
	
//    end=(double)cvGetTickCount();
//	t1 = (end-start)/((double)cvGetTickFrequency()*1000.);
//	printf("Threshold : %g ms\n",t1);
#if DEBUG	
	start=(double)cvGetTickCount();
#endif
	findContours(color1, contours1, hierarchy1, RETR_CCOMP, CHAIN_APPROX_TC89_KCOS);

    if(contours1.size() == 0 ) { cout <<copter.number <<":  no color1 ! " << endl;
    }

    for(size_t idx = 0; idx < contours1.size(); idx++)
    {
        drawContours(color1,contours1,idx,Scalar(255,255,255),CV_FILLED,8);
    }
    bitwise_and(color1,color3,color2);
    
    findContours(color2, contours2,hierarchy2, RETR_CCOMP, CHAIN_APPROX_TC89_KCOS);
    if(contours2.size() == 0 ) { cout <<copter.number << ":  no color2 ! " << endl;
	}
#if DEBUG
    end=(double)cvGetTickCount();
	t1 = (end-start)/((double)cvGetTickFrequency()*1000.);
	printf("findcountours : %g ms\n",t1);

	start=(double)cvGetTickCount();
#endif
	for(int m=0; m<contours1.size(); m++)
    {
        for(int n=0; n<contours2.size(); n++)
        {//
            copter_box1 = boundingRect(contours1[m]);
            copter_box2 = boundingRect(contours2[n]);
            Point box2_center = Point(copter_box2.x+(copter_box2.width/2),copter_box2.y+(copter_box2.height/2));
            if(box2_center.x >=copter_box1.x-copter_box1.width && box2_center.x <= copter_box1.x+copter_box1.width*2 && box2_center.y >=copter_box1.y-copter_box1.height && box2_center.y <=copter_box1.y+(copter_box1.height)*2)
            {

            	int diff = abs(copter_box2.x+(copter_box2.width/2) - copter_box1.x+(copter_box1.width/2)) + abs(copter_box2.y+(copter_box2.height/2) - copter_box1.y+(copter_box1.height/2));
            	if(diff < min_diff){
                	min_diff = diff;
                	min_num1 = m;
                	min_num2 = n;
            	}

            }

        }//
    }
	absdiff(color3,color2,color3);
	findContours(color3, contours3, hierarchy3, RETR_CCOMP, CHAIN_APPROX_TC89_KCOS);
	if(contours1.size()>0 && contours3.size()>0 && min_num1 < contours1.size())
	{
    copter_box4 = boundingRect(contours1[min_num1]);
    int centerof_box4_x = copter_box4.x + (copter_box4.width/2);
    int centerof_box4_y = copter_box4.y + (copter_box4.height/2);
    int centerof_box3_x=0;
    int centerof_box3_y=0;
    for(int t=0; t<contours3.size(); t++)
    {
        bool check_exception=true;
        copter_box3 = boundingRect(contours3[t]);
        centerof_box3_x = copter_box3.x + (copter_box3.width/2);
        centerof_box3_y = copter_box3.y + (copter_box3.height/2);
        if(centerof_box3_x >= copter_box4.x && centerof_box3_x <= copter_box4.x+copter_box4.width && centerof_box3_y >= copter_box4.y && centerof_box3_y <= copter_box4.y+copter_box4.height)
        {
            check_exception = false;
        }
        if(check_exception  && contours3[t].size() < contours1[min_num1].size() && t != min_num2 )
        {
            int diff = abs(centerof_box4_x - centerof_box3_x) + abs(centerof_box4_y - centerof_box3_y);
            if(diff<min_diff2){
                min_diff2 = diff;
                min_num3 = t;
            }        
        }
    }
    if(min_num3 <contours3.size())
    {
        copter_box3 = boundingRect(contours3[min_num3]);
        copter.Head_vector =  Return_HeadWay(copter_box3, copter_box4);
    }
	}
#if DEBUG
    cout << "Copter.Head_Vector : " << copter.Head_vector << endl;
#endif


#if DEBUG
    end=(double)cvGetTickCount();
	t1 = (end-start)/((double)cvGetTickFrequency()*1000.);
	printf("for loop : %g ms\n",t1);

	start =(double)cvGetTickCount();
#endif
	if(min_diff > 10000) {
        copter.not_found_count++;	
		switch(copter.vector)
		{
				case 1 : copter.width += (copter.width>>1); 
						 //cout << copter.number << " :   1 " << endl;
						 break;
				case 2 : copter.width += (copter.width>>1);
						 copter.y -= (copter.height>>1); 
						 copter.height += (copter.height>>1); 
						 //cout << copter.number << " :   2 " << endl;
						 break;
				case 3 : copter.y -= (copter.height>>1); 
						 copter.height += (copter.height>>1); 
						 //cout << copter.number << " :   3 "<< endl;
						 break;
				case 4 : copter.x -= (copter.width>>1);
						 copter.width +=(copter.width>>1);
						 copter.y -= (copter.height>>1);
						 copter.height += (copter.height>>1);
						 //cout << copter.number << " :   4 "<< endl;
						 break;
				case 5 : copter.x -= (copter.width>>1);
						 copter.width += (copter.width>>1);
						 //cout << copter.number << " :   5 "<< endl;
						 break;
				case 6 : copter.x -= (copter.width>>1);
						 copter.width += (copter.width>>1);
						 copter.height += (copter.height>>1); 
						 //cout << copter.number << " :   6 "<< endl;
						 break;
				case 7 : copter.height += (copter.height>>1); 
						 //cout << copter.number << " :   7 "<< endl;
						 break;
				case 8 : copter.height += (copter.height>>1);
						 copter.width += (copter.width>>1); 
						 //cout << copter.number << " :   8 "<< endl;
						 break;
				default : break;
		}
		Reposition_minus(copter);
        if(copter.not_found_count >=FIND_THRESHOLD)
        { 
            copter.not_found_count = 0 ;
            copter.Flag = false; 
        }
        return;
    }//확인요망
///Level 1
void CColor::setALLBoardColorPosition()
{
    Scalar colorContours;
    imgFHSVBoard = Frame2HSV(imgSharp, CColorsType::NOTWHITE);
    ///setColorPosition2Board(CColorsType::RED);
    imgFHSV = Frame2HSV(imgSharp, CColorsType::RED);
    bitwise_and(imgFHSVBoard, imgFHSV, imgFComper); //sumar a figura imgFHSVBoard com imgFHSV para obter só a cor
    Canny(imgFComper, imgCanny, 180, 120);
    findContours(imgCanny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    drawingContours = Mat::zeros(imgCanny.size(), CV_8UC3);
    for (size_t i = 0; i< contours.size(); i++) {
        approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);// 5, true); //
        if(fabs(contourArea(approx)) > 1000 && approx.size() == 4)
        {
            if(fig.isSquare(approx)) {
                poscenter.ChooseSaveBoardColorCenter( CColorsType::RED, contours[i]);

                colorContours = CV_RGB(255, 0, 0);
                drawContours(drawingContours, contours, (int)i, colorContours, 2, /*CV_AA*/8, hierarchy, 0, Point());
            }
        }
    }

    ///setColorPosition2Board(CColorsType::GREEN);
    imgFHSV = Frame2HSV(imgSharp, CColorsType::GREEN);
    bitwise_and(imgFHSVBoard, imgFHSV, imgFComper); //sumar a figura imgFHSVBoard com imgFHSV para obter só a cor
    Canny(imgFComper, imgCanny, 180, 120);
    findContours(imgCanny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    for (size_t i = 0; i< contours.size(); i++) {
        approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);// 5, true); //
        if(fabs(contourArea(approx)) > 1000 && approx.size() == 4)
        {
            if(fig.isSquare(approx)) {
                poscenter.ChooseSaveBoardColorCenter( CColorsType::GREEN, contours[i]);

                colorContours = CV_RGB(0, 255, 0);
                drawContours(drawingContours, contours, (int)i, colorContours, 2, /*CV_AA*/8, hierarchy, 0, Point());
            }
        }
    }

    ///setColorPosition2Board(CColorsType::BLUE);
    imgFHSV = Frame2HSV(imgSharp, CColorsType::BLUE);
    bitwise_and(imgFHSVBoard, imgFHSV, imgFComper); //sumar a figura imgFHSVBoard com imgFHSV para obter só a cor
    Canny(imgFComper, imgCanny, 180, 120);
    findContours(imgCanny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    for (size_t i = 0; i< contours.size(); i++) {
        approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);// 5, true); //
        if(fabs(contourArea(approx)) > 1000 && approx.size() == 4)
        {
            if(fig.isSquare(approx)) {
                poscenter.ChooseSaveBoardColorCenter( CColorsType::BLUE, contours[i]);

                colorContours = CV_RGB(0, 0, 255);
                drawContours(drawingContours, contours, (int)i, colorContours, 2, /*CV_AA*/8, hierarchy, 0, Point());
            }
        }
    }

    ////setColorPosition2Board(CColorsType::YELLOW);
    imgFHSV = Frame2HSV(imgSharp, CColorsType::YELLOW);
    bitwise_and(imgFHSVBoard, imgFHSV, imgFComper); //sumar a figura imgFHSVBoard com imgFHSV para obter só a cor
    Canny(imgFComper, imgCanny, 180, 120);
    findContours(imgCanny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    for (size_t i = 0; i< contours.size(); i++) {
        approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);// 5, true); //
        if(fabs(contourArea(approx)) > 1000 && approx.size() == 4)
        {
            if(fig.isSquare(approx)) {
                poscenter.ChooseSaveBoardColorCenter( CColorsType::YELLOW, contours[i]);

                colorContours = CV_RGB(255, 255, 0);
                drawContours(drawingContours, contours, (int)i, colorContours, 2, /*CV_AA*/8, hierarchy, 0, Point());
            }
        }
    }

    ///setColorPosition2Board(CColorsType::BLACK);
    imgFHSV = Frame2HSV(imgSharp, CColorsType::BLACK );
    bitwise_and(imgFHSVBoard, imgFHSV, imgFComper); //sumar a figura imgFHSVBoard com imgFHSV para obter só a cor
    Canny(imgFComper, imgCanny, 180, 120);
    findContours(imgCanny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

    for (size_t i = 0; i< contours.size(); i++) {
        approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);// 5, true); //
        if(fabs(contourArea(approx)) > 1000 && approx.size() == 4)
        {
            if(fig.isSquare(approx)) {
                poscenter.ChooseSaveBoardColorCenter( CColorsType::BLACK, contours[i]);

                colorContours = CV_RGB(255, 255, 0);
                drawContours(drawingContours, contours, (int)i, colorContours, 2, /*CV_AA*/8, hierarchy, 0, Point());
            }
        }
    }

    //imshow("drawingContours", drawingContours);
}
示例#26
0
//                  색1       색2            색1            색2           색1              색2
void Take_Copter(Mat Cam, Mat Cam2,  Copter& cop)
{
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    Mat YUV_PIC3;
    
    Mat Pic2_col1(cop.Picture3.rows,cop.Picture3.cols,CV_8UC1);
    Mat Pic2_col2(cop.Picture3.rows,cop.Picture3.cols,CV_8UC1);
   	Mat temp3(cop.Picture3.rows,cop.Picture3.cols,CV_8UC1);
   	Mat temp4(cop.Picture3.rows,cop.Picture3.cols,CV_8UC1);
   	Mat temp5(cop.Picture3.rows,cop.Picture3.cols,CV_8UC1);
   	Mat temp6(cop.Picture3.rows,cop.Picture3.cols,CV_8UC1);
	
    cvtColor(cop.Picture3,YUV_PIC3,CV_RGB2YCrCb);
	
	vector<Mat> yuv;
		Mat Corr_1_1;//색1
    Mat Corr_1_2;//색1
    Mat Corr_2_1;//색2
    Mat Corr_2_2;//색2
    int corr_size_X =0;
    int corr_size_Y =0;


    Mat Result;
    double min,max;
    Point Copter_point;
   
    for(int i=0; i<V_BUFFER_SIZE; i++)
    {
        cop.prev_cx[i] = -5000;
        cop.prev_cy[i] = -5000;
    }

	if(cop.find_mode == true){
		cop.find_mode = false;
		matchTemplate(Cam,cop.Pic_Binary1,Corr_1_1,CV_TM_CCOEFF_NORMED);
    	matchTemplate(Cam2,cop.Pic_Binary2,Corr_1_2,CV_TM_CCOEFF_NORMED);
		if(Corr_1_1.rows<Corr_1_2.rows)
    	{ 
       		corr_size_Y = Corr_1_1.rows; 
    	}
    	else
    	{
        	corr_size_Y = Corr_1_2.rows;
    	}
    	if(Corr_1_1.cols<Corr_1_2.cols)
    	{
        	corr_size_X = Corr_1_1.cols;
    	}
    	else
    	{
        	corr_size_X = Corr_1_2.cols;
    	}
    	resize(Corr_1_1,Corr_1_1,Size(corr_size_X,corr_size_Y),0,0,INTER_CUBIC);
    	resize(Corr_1_2,Corr_1_2,Size(corr_size_X,corr_size_Y),0,0,INTER_CUBIC);
		Result = (0.6*Corr_1_1)+(0.6*Corr_1_2);
	}
	else
	{
		cop.find_mode = true;
		split(YUV_PIC3,yuv);
		threshold(yuv[0],yuv[0],cop.Y_MAX,255,THRESH_TOZERO_INV);
		threshold(yuv[0],Pic2_col1,cop.Y_MIN,255,THRESH_BINARY);
		threshold(yuv[1],yuv[1],cop.Cb_MAX,255,THRESH_TOZERO_INV);
		threshold(yuv[1],temp3,cop.Cb_MIN,255,THRESH_BINARY);
		threshold(yuv[2],yuv[2],cop.Cr_MAX,255,THRESH_TOZERO_INV);
		threshold(yuv[2],temp4,cop.Cr_MIN,255,THRESH_BINARY);
	
		bitwise_and(Pic2_col1,temp3,temp3);
		bitwise_and(temp3,temp4,Pic2_col1);

		split(YUV_PIC3,yuv);
	
		threshold(yuv[0],yuv[0],cop.Y_MAX2,255,THRESH_TOZERO_INV);
		threshold(yuv[0],Pic2_col2,cop.Y_MIN2,255,THRESH_BINARY);
		threshold(yuv[1],yuv[1],cop.Cb_MAX2,255,THRESH_TOZERO_INV);
		threshold(yuv[1],temp5,cop.Cb_MIN2,255,THRESH_BINARY);
		threshold(yuv[2],yuv[2],cop.Cr_MAX2,255,THRESH_TOZERO_INV);
		threshold(yuv[2],temp6,cop.Cr_MIN2,255,THRESH_BINARY);
    
		bitwise_and(Pic2_col2,temp5,temp5);
		bitwise_and(temp5,temp6,Pic2_col2);
	

		
		matchTemplate(Cam,Pic2_col1,Corr_2_1,CV_TM_CCOEFF_NORMED);
    	matchTemplate(Cam2,Pic2_col2,Corr_2_2,CV_TM_CCOEFF_NORMED);
		if(Corr_2_1.rows<Corr_2_2.rows)
    	{ 
       		corr_size_Y = Corr_2_1.rows; 
    	}
    	else
    	{
        	corr_size_Y = Corr_2_2.rows;
    	}
    	if(Corr_2_1.cols<Corr_2_2.cols)
    	{
        	corr_size_X = Corr_2_1.cols;
    	}
    	else
    	{
        	corr_size_X = Corr_2_2.cols;
    	}
    	resize(Corr_2_1,Corr_2_1,Size(corr_size_X,corr_size_Y),0,0,INTER_CUBIC);
   		resize(Corr_2_2,Corr_2_2,Size(corr_size_X,corr_size_Y),0,0,INTER_CUBIC);
		Result = (0.6*Corr_2_1)+(0.6*Corr_2_2);
	}
//	imshow("3",Pic2_col2);
//	imshow("2",Pic2_col1);
//	imshow("1",Result);
    minMaxLoc(Result,&min,&max,NULL,&Copter_point);

    cop.width = 3*(cop.Pic_Binary2.cols);
    cop.height =3*(cop.Pic_Binary2.rows);
    cop.x = Copter_point.x-(cop.width/3);
    cop.y = Copter_point.y-(cop.height/3);
    Reposition_minus(cop);
   	pthread_mutex_lock(&mutex);// =========* 
    resize(cop.Copter_Layer,cop.Copter_Layer,Size(cop.width,cop.height),0,0,INTER_NEAREST);
    if(cop.number == 1)
		cop.Copter_Layer = Cam_Image(Rect(cop.x , cop.y , cop.width , cop.height ) );
	else if(cop.number == 2)
		cop.Copter_Layer = Cam_Image(Rect(cop.x,cop.y,cop.width,cop.height));
	   pthread_mutex_unlock(&mutex);// ==========*

}
示例#27
0
  void PlateLines::processImage(Mat inputImage, vector<TextLine> textLines, float sensitivity)
  {
    if (this->debug)
      cout << "PlateLines findLines" << endl;

    timespec startTime;
    getTimeMonotonic(&startTime);


    // Ignore input images that are pure white or pure black
    Scalar avgPixelIntensity = mean(inputImage);
    if (avgPixelIntensity[0] >= 252)
      return;
    else if (avgPixelIntensity[0] <= 3)
      return;

    // Do a bilateral filter to clean the noise but keep edges sharp
    Mat smoothed(inputImage.size(), inputImage.type());
    adaptiveBilateralFilter(inputImage, smoothed, Size(3,3), 45, 45);


    int morph_elem  = 2;
    int morph_size = 2;
    Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );


    Mat edges(inputImage.size(), inputImage.type());
    Canny(smoothed, edges, 66, 133);

    // Create a mask that is dilated based on the detected characters


    Mat mask = Mat::zeros(inputImage.size(), CV_8U);

    for (unsigned int i = 0; i < textLines.size(); i++)
    {
      vector<vector<Point> > polygons;
      polygons.push_back(textLines[i].textArea);
      fillPoly(mask, polygons, Scalar(255,255,255));
    }



    dilate(mask, mask, getStructuringElement( 1, Size( 1 + 1, 2*1+1 ), Point( 1, 1 ) ));
    bitwise_not(mask, mask);

    // AND canny edges with the character mask
    bitwise_and(edges, mask, edges);


    vector<PlateLine> hlines = this->getLines(edges, sensitivity, false);
    vector<PlateLine> vlines = this->getLines(edges, sensitivity, true);
    for (unsigned int i = 0; i < hlines.size(); i++)
      this->horizontalLines.push_back(hlines[i]);
    for (unsigned int i = 0; i < vlines.size(); i++)
      this->verticalLines.push_back(vlines[i]);

    // if debug is enabled, draw the image
    if (this->debug)
    {
      Mat debugImgHoriz(edges.size(), edges.type());
      Mat debugImgVert(edges.size(), edges.type());
      edges.copyTo(debugImgHoriz);
      edges.copyTo(debugImgVert);
      cvtColor(debugImgHoriz,debugImgHoriz,CV_GRAY2BGR);
      cvtColor(debugImgVert,debugImgVert,CV_GRAY2BGR);

      for( size_t i = 0; i < this->horizontalLines.size(); i++ )
      {
        line( debugImgHoriz, this->horizontalLines[i].line.p1, this->horizontalLines[i].line.p2, Scalar(0,0,255), 1, CV_AA);
      }

      for( size_t i = 0; i < this->verticalLines.size(); i++ )
      {
        line( debugImgVert, this->verticalLines[i].line.p1, this->verticalLines[i].line.p2, Scalar(0,0,255), 1, CV_AA);
      }

      vector<Mat> images;
      images.push_back(debugImgHoriz);
      images.push_back(debugImgVert);

      Mat dashboard = drawImageDashboard(images, debugImgVert.type(), 1);
      displayImage(pipelineData->config, "Hough Lines", dashboard);
    }

    if (pipelineData->config->debugTiming)
    {
      timespec endTime;
      getTimeMonotonic(&endTime);
      cout << "Plate Lines Time: " << diffclock(startTime, endTime) << "ms." << endl;
    }

  }
示例#28
0
/* Process the images inside each directory */
bool processDir(std::string path, std::string image_name, std::string metrics_file) {

    /* Create the data output file for images that were processed */
    std::ofstream data_stream;
    data_stream.open(metrics_file, std::ios::app);
    if (!data_stream.is_open()) {
        std::cerr << "Could not open the data output file." << std::endl;
        return false;
    }

    // Create the output directory
    std::string out_directory = path + "result/";
    struct stat st = {0};
    if (stat(out_directory.c_str(), &st) == -1) {
        mkdir(out_directory.c_str(), 0700);
    }
    out_directory = out_directory + image_name + "/";
    st = {0};
    if (stat(out_directory.c_str(), &st) == -1) {
        mkdir(out_directory.c_str(), 0700);
    }

    // Count the number of images
    std::string dir_name = path + "jpg/" + image_name + "/";
    DIR *read_dir = opendir(dir_name.c_str());
    if (!read_dir) {
        std::cerr << "Could not open directory '" << dir_name << "'" << std::endl;
        return false;
    }
    struct dirent *dir = NULL;
    uint8_t z_count = 0;
    bool collect_name_pattern = false;
    std::string end_pattern;
    while ((dir = readdir(read_dir))) {
        if (!strcmp (dir->d_name, ".") || !strcmp (dir->d_name, "..")) continue;
        if (!collect_name_pattern) {
            std::string delimiter = "c1+";
            end_pattern = dir->d_name;
            size_t pos = end_pattern.find(delimiter);
            end_pattern.erase(0, pos);
            collect_name_pattern = true;
        }
        z_count++;
    }

    std::vector<cv::Mat> blue_list(NUM_Z_LAYERS_COMBINED), green_list(NUM_Z_LAYERS_COMBINED);
    for (uint8_t z_index = 1; z_index <= z_count; z_index++) {

        // Create the input filename and rgb stream output filenames
        std::string in_filename;
        if (z_count < 10) {
            in_filename = dir_name + image_name + 
                                        "_z" + std::to_string(z_index) + end_pattern;
        } else {
            if (z_index < 10) {
                in_filename = dir_name + image_name + 
                                        "_z0" + std::to_string(z_index) + end_pattern;
            } else if (z_index < 100) {
                in_filename = dir_name + image_name + 
                                        "_z" + std::to_string(z_index) + end_pattern;
            } else { // assuming number of z plane layers will never exceed 99
                std::cerr << "Does not support more than 99 z layers curently" << std::endl;
                return false;
            }
        }

        // Extract the bgr streams for each input image
        cv::Mat img = cv::imread(in_filename.c_str(), -1);
        if (img.empty()) return false;

        // Original image
        std::string out_original = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_a_original.jpg";
        cv::imwrite(out_original.c_str(), img);

        std::vector<cv::Mat> channel(3);
        cv::split(img, channel);
        blue_list[(z_index-1)%NUM_Z_LAYERS_COMBINED]  = channel[0];
        green_list[(z_index-1)%NUM_Z_LAYERS_COMBINED] = channel[1];

        // Continue collecting layers if needed
        if (z_index%NUM_Z_LAYERS_COMBINED && (z_index != z_count)) continue;

        // Merge some layers together
        cv::Mat blue  = cv::Mat::zeros(channel[0].size(), CV_8UC1);
        cv::Mat green = cv::Mat::zeros(channel[1].size(), CV_8UC1);
        for (unsigned int merge_index = 0; 
                    merge_index < NUM_Z_LAYERS_COMBINED; merge_index++) {
            bitwise_or(blue, blue_list[merge_index], blue);
            bitwise_or(green, green_list[merge_index], green);
        }

        /** Gather BGR channel information needed for feature extraction **/

        // Blue channel
        std::string out_blue = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_blue.jpg";
        if (DEBUG_FLAG) cv::imwrite(out_blue.c_str(), blue);

        cv::Mat blue_enhanced;
        if(!enhanceImage(blue, ChannelType::BLUE, &blue_enhanced)) return false;
        out_blue.insert(out_blue.find_last_of("."), "_enhanced", 9);
        if (DEBUG_FLAG) cv::imwrite(out_blue.c_str(), blue_enhanced);

        cv::Mat blue_segmented;
        std::vector<std::vector<cv::Point>> contours_blue;
        std::vector<cv::Vec4i> hierarchy_blue;
        std::vector<HierarchyType> blue_contour_mask;
        std::vector<double> blue_contour_area;
        contourCalc(blue_enhanced, ChannelType::BLUE, 1.0, &blue_segmented, 
                &contours_blue, &hierarchy_blue, &blue_contour_mask, &blue_contour_area);

        // Green channel
        std::string out_green = out_directory + "zlayer_" + 
                                        std::to_string(z_index) + "_green.jpg";
        if (DEBUG_FLAG) cv::imwrite(out_green.c_str(), green);

        cv::Mat green_enhanced;
        if(!enhanceImage(green, ChannelType::GREEN, &green_enhanced)) return false;
        out_green.insert(out_green.find_last_of("."), "_enhanced", 9);
        if (DEBUG_FLAG) cv::imwrite(out_green.c_str(), green_enhanced);

        cv::Mat not_blue, green_minus_blue, green_skeletonize;
        bitwise_not(blue_enhanced, not_blue);
        bitwise_and(green_enhanced, not_blue, green_minus_blue);
        skeletonize(green_enhanced, &green_skeletonize);
        out_green.insert(out_green.find_last_of("."), "_skeletonized", 13);
        if (DEBUG_FLAG) cv::imwrite(out_green.c_str(), green_skeletonize);

        cv::Mat green_segmented;
        std::vector<std::vector<cv::Point>> contours_green;
        std::vector<cv::Vec4i> hierarchy_green;
        std::vector<HierarchyType> green_contour_mask;
        std::vector<double> green_contour_area;
        contourCalc(green_enhanced, ChannelType::GREEN, 1.0, &green_segmented, 
                &contours_green, &hierarchy_green, &green_contour_mask, &green_contour_area);
    }
    closedir(read_dir);
    data_stream.close();

    return true;
}
示例#29
0
void CmEvaluation::EvalueMask(CStr gtW, CStr &maskDir, vecS &des, CStr resFile, double betaSqr, bool alertNul, CStr suffix, CStr title)
{
	vecS namesNS; 
	string gtDir, gtExt;
	int imgNum = CmFile::GetNamesNE(gtW, namesNS, gtDir, gtExt);
	int methodNum = (int)des.size();
	vecD pr(methodNum), rec(methodNum), count(methodNum), fm(methodNum);
	vecD intUnio(methodNum), mae(methodNum);
	for (int i = 0; i < imgNum; i++){
		Mat truM = imread(gtDir + namesNS[i] + gtExt, CV_LOAD_IMAGE_GRAYSCALE);
		for (int m = 0; m < methodNum; m++)	{
			string mapName = maskDir + namesNS[i] + "_" + des[m];
			mapName += suffix.empty() ? ".png" : "_" + suffix + ".png";
			Mat res = imread(mapName, CV_LOAD_IMAGE_GRAYSCALE);
			if (truM.data == NULL || res.data == NULL || truM.size != res.size){
				if (alertNul)
					printf("Truth(%d, %d), Res(%d, %d): %s\n", truM.cols, truM.rows, res.cols, res.rows, _S(mapName));
				continue;
			}
			compare(truM, 128, truM, CMP_GE);
			compare(res, 128, res, CMP_GE);
			Mat commMat, unionMat, diff1f;
			bitwise_and(truM, res, commMat);
			bitwise_or(truM, res, unionMat);
			double commV = sum(commMat).val[0];
			double p = commV/(sum(res).val[0] + EPS);
			double r = commV/(sum(truM).val[0] + EPS);
			pr[m] += p;
			rec[m] += r;
			intUnio[m] += commV / (sum(unionMat).val[0] + EPS);
			absdiff(truM, res, diff1f);
			mae[m] += sum(diff1f).val[0]/(diff1f.rows * diff1f.cols * 255);
			count[m]++;
		}
	}

	for (int m = 0; m < methodNum; m++){
		pr[m] /= count[m], rec[m] /= count[m];
		fm[m] = (1 + betaSqr) * pr[m] * rec[m] / (betaSqr * pr[m] + rec[m] + EPS);
		intUnio[m] /= count[m];
		mae[m] /= count[m];
	}

#ifndef fopen_s
	FILE *f = fopen(_S(resFile), "a");
#else
	FILE *f; 
	fopen_s(&f, _S(resFile), "a");
#endif
	if (f != NULL){
		fprintf(f, "\n%%%%\n");
		CmEvaluation::PrintVector(f, pr, "PrecisionMask" + suffix);
		CmEvaluation::PrintVector(f, rec, "RecallMask" + suffix);
		CmEvaluation::PrintVector(f, fm, "FMeasureMask" + suffix);
		CmEvaluation::PrintVector(f, intUnio, "IntUnion" + suffix);
		CmEvaluation::PrintVector(f, intUnio, "MAE" + suffix);
		fprintf(f, "bar([%s]');\ngrid on\n", _S("PrecisionMask" + suffix + "; RecallMask" + suffix + "; FMeasureMask" + suffix + "; IntUnion" + suffix));
		fprintf(f, "title('%s');\naxis([0 %d 0.8 1]);\nmethodLabels = { '%s'", _S(title), des.size() + 1, _S(des[0]));
		for (size_t i = 1; i < des.size(); i++)
			fprintf(f, ", '%s'", _S(des[i]));
		fprintf(f, " };\nlegend('Precision', 'Recall', 'FMeasure', 'IntUnion');\n");
		fprintf(f, "xticklabel_rotate([1:%d], 90, methodLabels, 'interpreter', 'none');\n", des.size());
		fclose(f);
	}

	if (des.size() == 1)
		printf("Precision = %g, recall = %g, F-Measure = %g, intUnion = %g, mae = %g\n", pr[0], rec[0], fm[0], intUnio[0], mae[0]);
}
示例#30
0
// Return mean absolute error (MAE)
double CmEvaluation::Evaluate_(CStr &gtImgW, CStr &inDir, CStr& resExt, vecD &precision, vecD &recall, vecD &tpr, vecD &fpr)
{
	vecS names;
	string truthDir, gtExt;
	int imgNum = CmFile::GetNamesNE(gtImgW, names, truthDir, gtExt); 
	precision.resize(NUM_THRESHOLD, 0);
	recall.resize(NUM_THRESHOLD, 0);
	tpr.resize(NUM_THRESHOLD, 0);
	fpr.resize(NUM_THRESHOLD, 0);
	if (imgNum == 0){
		printf("Can't load ground truth images %s\n", _S(gtImgW));
		return 10^20;
	}
	else
		printf("Evaluating %d saliency maps ... \r", imgNum);

	double mea = 0;
	for (int i = 0; i < imgNum; i++){
		if(i % 100 == 0)
			printf("Evaluating %03d/%d %-40s\r", i, imgNum, _S(names[i] + resExt));
		Mat resS = imread(inDir + names[i] + resExt, CV_LOAD_IMAGE_GRAYSCALE);
		CV_Assert_(resS.data != NULL, ("Can't load saliency map: %s\n", _S(names[i] + resExt)));
		normalize(resS, resS, 0, 255, NORM_MINMAX);
		Mat gtFM = imread(truthDir + names[i] + gtExt, CV_LOAD_IMAGE_GRAYSCALE), gtBM;
		if (gtFM.data == NULL) 
			continue;
		CV_Assert_(resS.size() == gtFM.size(), ("Saliency map and ground truth image size mismatch: %s\n", _S(names[i])));
		compare(gtFM, 128, gtFM, CMP_GT);
		bitwise_not(gtFM, gtBM);
		double gtF = sum(gtFM).val[0];
		double gtB = resS.cols * resS.rows * 255 - gtF;


#pragma omp parallel for
		for (int thr = 0; thr < NUM_THRESHOLD; thr++){
			Mat resM, tpM, fpM;
			compare(resS, thr * STEP, resM, CMP_GE);
			bitwise_and(resM, gtFM, tpM);
			bitwise_and(resM, gtBM, fpM);
			double tp = sum(tpM).val[0]; 
			double fp = sum(fpM).val[0];
			//double fn = gtF - tp;
			//double tn = gtB - fp;

			recall[thr] += tp/(gtF+EPS);
			double total = EPS + tp + fp;
			precision[thr] += (tp+EPS)/total;

			tpr[thr] += (tp + EPS) / (gtF + EPS);
			fpr[thr] += (fp + EPS) / (gtB + EPS);
		}

		gtFM.convertTo(gtFM, CV_32F, 1.0/255);
		resS.convertTo(resS, CV_32F, 1.0/255);
		cv::absdiff(gtFM, resS, resS);
		mea += sum(resS).val[0] / (gtFM.rows * gtFM.cols);
	}

	int thrS = 0, thrE = NUM_THRESHOLD, thrD = 1;
	for (int thr = thrS; thr != thrE; thr += thrD){
		precision[thr] /= imgNum;
		recall[thr] /= imgNum;
		tpr[thr] /= imgNum;
		fpr[thr] /= imgNum;
	}
	return mea/imgNum;
}