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); }
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; }
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() */
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); }
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 >ImgW, 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; } }
/* 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; }
// 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; }
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); } } }
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; }
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); }
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; }
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; }
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); }
// 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); } }
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]); } } } */ }
/* 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; }
/* 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; }
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); }
// 색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);// ==========* }
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; } }
/* 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; }
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]); }
// Return mean absolute error (MAE) double CmEvaluation::Evaluate_(CStr >ImgW, 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; }