#include "onf_stepoptimizegaussianonmaximanumber.h" #include "ct_log/ct_logmanager.h" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/core/core.hpp" #include "opencv2/imgproc/types_c.h" ONF_StepOptimizeGaussianOnMaximaNumber::ONF_StepOptimizeGaussianOnMaximaNumber() : SuperClass() { _sigmaStep = 0.05; _sigmaMax = 1.0; _minHeight = 2.0; _CoefMult = 2.0; } QString ONF_StepOptimizeGaussianOnMaximaNumber::description() const { return tr("Filtre Gaussien optimisé par le nombre de maxima"); } QString ONF_StepOptimizeGaussianOnMaximaNumber::detailledDescription() const { return tr(""); } QString ONF_StepOptimizeGaussianOnMaximaNumber::inputDescription() const { return SuperClass::inputDescription() + tr("

"); } QString ONF_StepOptimizeGaussianOnMaximaNumber::outputDescription() const { return SuperClass::outputDescription() + tr("

"); } QString ONF_StepOptimizeGaussianOnMaximaNumber::detailsDescription() const { return tr(""); } QString ONF_StepOptimizeGaussianOnMaximaNumber::URL() const { //return tr("STEP URL HERE"); return SuperClass::URL(); //by default URL of the plugin } CT_VirtualAbstractStep* ONF_StepOptimizeGaussianOnMaximaNumber::createNewInstance() const { return new ONF_StepOptimizeGaussianOnMaximaNumber(); } //////////////////// PROTECTED METHODS ////////////////// void ONF_StepOptimizeGaussianOnMaximaNumber::declareInputModels(CT_StepInModelStructureManager& manager) { manager.addResult(_inResult, tr("Image 2D")); manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup); manager.addGroup(_inZeroOrMoreRootGroup, _inGroup); manager.addItem(_inGroup, _inImage, tr("Image")); } void ONF_StepOptimizeGaussianOnMaximaNumber::declareOutputModels(CT_StepOutModelStructureManager& manager) { manager.addResultCopy(_inResult); manager.addItem(_inGroup, _filteredImage, tr("Image filtrée")); manager.addItemAttribute(_filteredImage, _attSigma, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), tr("Sigma")); manager.addItem(_inGroup, _maximaImage, tr("Maxima")); } void ONF_StepOptimizeGaussianOnMaximaNumber::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { postInputConfigDialog->addDouble(tr("Sigma max"), tr("en mètres"), 0, 1000, 2, _sigmaMax); postInputConfigDialog->addDouble(tr("Incrément de Sigma par étape"), tr("en mètres"), 0, 1000, 2, _sigmaStep); postInputConfigDialog->addDouble(tr("Ne pas détécter de maxima en dessous de"), tr("m"), 0, 99999, 2, _minHeight); postInputConfigDialog->addDouble(tr("Coeff Mult"), "", 1, 1000, 2, _CoefMult); postInputConfigDialog->addEmpty(); postInputConfigDialog->addTitle(tr("N.B. : Portée du filtre = 7.7 x Sigma (en mètres)")); } void ONF_StepOptimizeGaussianOnMaximaNumber::compute() { for (CT_StandardItemGroup* grp : _inGroup.iterateOutputs(_inResult)) { if (isStopped()) {return;} CT_Image2D* imageIn = const_cast*>(grp->singularItem(_inImage)); if (imageIn != nullptr) { Eigen::Vector2d min; imageIn->getMinCoordinates(min); CT_Image2D* filteredImage = new CT_Image2D(min(0), min(1), imageIn->xdim(), imageIn->ydim(), imageIn->resolution(), imageIn->level(), imageIn->NA(), imageIn->NA()); grp->addSingularItem(_filteredImage, filteredImage); CT_Image2D* maximaImage = new CT_Image2D(min(0), min(1), imageIn->xdim(), imageIn->ydim(), imageIn->resolution(), imageIn->level(), -1, 0); grp->addSingularItem(_maximaImage, maximaImage); cv::Mat_& filteredMat = filteredImage->getMat(); QMultiMap nbMaxis; for (double sigmaInMeters = _sigmaStep ; sigmaInMeters <= (_sigmaMax + _sigmaMax/1000.0) ; sigmaInMeters += _sigmaStep) { double sigma = sigmaInMeters / imageIn->resolution(); cv::GaussianBlur(imageIn->getMat(), filteredMat, cv::Size2d(0, 0), sigma); cv::Mat_ dilatedMat(filteredMat.rows, filteredMat.cols); cv::Mat maximaMat = cv::Mat::zeros(filteredMat.rows, filteredMat.cols, CV_32F); // Nécessaire car compare ne prend pas la version template Mat_ en output !!! // Détéction des maxima cv::dilate(filteredMat, dilatedMat, cv::getStructuringElement(cv::MORPH_RECT, cv::Size2d(3,3))); cv::compare(filteredMat, dilatedMat, maximaMat, cv::CMP_EQ); // numérotation des maxima cv::Mat labels = cv::Mat::zeros(filteredMat.rows, filteredMat.cols, CV_32S); // Nécessaire car compare ne prend pas la version template Mat_ en output !!! cv::connectedComponents(maximaMat, labels); QList maximaIds; cv::Mat_ labs = labels; for (int col = 0 ; col < maximaMat.cols ; col++) { for (int lin = 0 ; lin < maximaMat.rows ; lin++) { if (filteredMat(lin, col) < float(_minHeight)) { labs(lin, col) = 0; } qint32 maxId = labs(lin, col); if (maxId != 0 && !maximaIds.contains(maxId)) {maximaIds.append(maxId);} } } maximaImage->getMat() = labels; int maxNumber = maximaIds.size(); nbMaxis.insert(sigmaInMeters, maxNumber); } double sigmaInMeters = _sigmaStep; if (nbMaxis.size() > 0) { int limit = int(nbMaxis.last() * _CoefMult); QMapIterator it(nbMaxis); it.toBack(); while (it.hasPrevious()) { it.previous(); if (it.value() <= limit) {sigmaInMeters = it.key();} } } PS_LOG->addMessage(LogInterface::info, LogInterface::step, QString(tr("Sigma retenu : %1")).arg(sigmaInMeters)); double sigma = sigmaInMeters / imageIn->resolution(); cv::GaussianBlur(imageIn->getMat(), filteredMat, cv::Size2d(0, 0), sigma); cv::Mat_ dilatedMat(filteredMat.rows, filteredMat.cols); cv::Mat maximaMat = cv::Mat::zeros(filteredMat.rows, filteredMat.cols, CV_32F); // Nécessaire car compare ne prend pas la version template Mat_ en output !!! // Détéction des maxima cv::dilate(filteredMat, dilatedMat, cv::getStructuringElement(cv::MORPH_RECT, cv::Size2d(3,3))); cv::compare(filteredMat, dilatedMat, maximaMat, cv::CMP_EQ); // numérotation des maxima cv::Mat labels = cv::Mat::zeros(filteredMat.rows, filteredMat.cols, CV_32S); // Nécessaire car compare ne prend pas la version template Mat_ en output !!! cv::connectedComponents(maximaMat, labels); filteredImage->addItemAttribute(_attSigma, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_VALUE, sigmaInMeters)); filteredImage->computeMinMax(); maximaImage->computeMinMax(); } } }