#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();
}
}
}