cv::Mat blobIdentification(cv::Mat image) { cv::Mat grayscaleImage; cv::Mat imageOpening; cv::Mat imageDifference; cv::Mat imageThreshold; cv::Mat meanImageDifference; cv::Mat stdDevImageDifference; // Morphological opening cv::morphologyEx(image, imageOpening, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(9,9))); // Get the threshold cutoff, generate the image difference cv::subtract(image, imageOpening, imageDifference); cv::meanStdDev(imageDifference, meanImageDifference, stdDevImageDifference); double mean = meanImageDifference.at<double>(0, 0); double stdev = stdDevImageDifference.at<double>(0, 0); double threshold_value = mean + (3 * stdev); imageThreshold = MatrixOperations::greaterThanValue((float)threshold_value, imageDifference); // Only use pixels which pass the threshold from the cross correlation cv::Mat grayscaleCrossCorrelation = crossCorrelateWithGaussian(image); cv::bitwise_and(imageThreshold, grayscaleCrossCorrelation, grayscaleImage); // Morphological close cv::Mat closingElement = getStructuringElement(cv::MORPH_RECT, cv::Size(3,3)); cv::morphologyEx(grayscaleImage, grayscaleImage, cv::MORPH_CLOSE, closingElement); grayscaleImage.convertTo(grayscaleImage, CV_8UC1); return grayscaleImage; }
cv::Mat blobIdentification(cv::Mat image, std::string debugPath) { //this is a hack, but it handles the different thresholds between this scope and Neil's scope bool neilscope = false; int thresholdMultiplier = 10; if (image.rows==1944) { neilscope = true; thresholdMultiplier = 3; std::cout << "running as Neilscope image\n"; } //input image has been normalized cv::Mat grayscaleImage; cv::Mat imageOpening; cv::Mat imageDifference; cv::Mat imageThreshold; cv::Mat meanImageDifference; cv::Mat stdDevImageDifference; // Get background image via morphological opening w/ 9x9 strel //Q: use gaussianBlur instead? cv::morphologyEx(image, imageOpening, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(9,9))); //std::cout << "opened\n"; if (debugPath!="") imwrite(debugPath + "/opened2-1.tif",imageOpening*255); // Subtract background cv::subtract(image, imageOpening, imageDifference); if (debugPath!="") imwrite(debugPath + "/subtracted2-2.tif",imageDifference*255); //std::cout << "subtracted\n"; imageOpening.release(); //FBM //TODO: bring all these parameters out to settings //TODO: image mask if (!neilscope) { cv::Mat img_mask(image.rows,image.cols, CV_8UC1); img_mask = cv::Scalar(0); for (int i = 800; i < 1800; i++) { for (int j = 400; j < 1400; j++) { img_mask.at<char>(i,j) = 1; } } if (debugPath!="") imwrite(debugPath + "/mask2-3.tif",img_mask*255); cv::meanStdDev(imageDifference, meanImageDifference, stdDevImageDifference, img_mask); img_mask.release(); } else { cv::meanStdDev(imageDifference, meanImageDifference, stdDevImageDifference); } // Find mean and std dev of background-subtracted image //threshold for binarization is mean + 3*std_dev double mean = meanImageDifference.at<double>(0, 0); double stdev = stdDevImageDifference.at<double>(0, 0); double threshold_value = mean + (thresholdMultiplier * stdev); std::cout << "\nmean: " << mean << " std: " << stdev << " thresh: " << threshold_value << "\n"; //get binary (thresholded) image imageThreshold = MatrixOperations::greaterThanValue((float)threshold_value, imageDifference); if (debugPath!="") imwrite(debugPath + "/thresholded2-4.tif",imageThreshold*255); //std::cout << "thresholded\n"; imageDifference.release(); //FBM // Only use pixels which pass the threshold from the cross correlation //I don't understand what this is doing cv::Mat grayscaleCrossCorrelation = crossCorrelateWithGaussian(image); cv::bitwise_and(imageThreshold, grayscaleCrossCorrelation, grayscaleImage); //std::cout << "cross correlated\n"; image.release(); //FBM imageThreshold.release(); //FBM grayscaleCrossCorrelation.release(); //FBM if (debugPath!="") imwrite(debugPath + "/grayscalecorrelated2-5.tif",grayscaleImage*255); // Morphological close cv::Mat closingElement = getStructuringElement(cv::MORPH_RECT, cv::Size(3,3)); cv::morphologyEx(grayscaleImage, grayscaleImage, cv::MORPH_CLOSE, closingElement); grayscaleImage.convertTo(grayscaleImage, CV_8UC1); closingElement.release(); //FBM if (debugPath!="") imwrite(debugPath + "/grayscaleclsed2-6.tif",grayscaleImage*255); return grayscaleImage; }