mirror of
https://github.com/dgirardeau/q3DMASC.git
synced 2026-08-29 08:34:48 +08:00
Scalar fields can now handle large values (with an internal double offset). Their names can also be longer than 255 characters.
This commit is contained in:
@@ -123,14 +123,14 @@ bool ContextBasedFeature::prepare( const CorePoints& corePoints,
|
||||
|
||||
//and the scalar field
|
||||
assert(!sf);
|
||||
sf1WasAlreadyExisting = CheckSFExistence(corePoints.cloud, qPrintable(resultSFName));
|
||||
sf = PrepareSF(corePoints.cloud, qPrintable(resultSFName), generatedScalarFields, SFCollector::CAN_REMOVE);
|
||||
sf1WasAlreadyExisting = CheckSFExistence(corePoints.cloud, resultSFName);
|
||||
sf = PrepareSF(corePoints.cloud, resultSFName, generatedScalarFields, SFCollector::CAN_REMOVE);
|
||||
if (!sf)
|
||||
{
|
||||
errorMessage = QString("[ContextBasedFeature::prepare] Failed to prepare scalar %1 @ scale %2").arg(resultSFName).arg(scale);
|
||||
return false;
|
||||
}
|
||||
source.name = sf->getName();
|
||||
source.name = QString::fromStdString(sf->getName());
|
||||
|
||||
// NOT NECESSARY IF THE VALUE IS ALREADY COMPUTED
|
||||
if (!scaled() && !sf1WasAlreadyExisting) //with 'kNN' neighbors, we can compute the values right away
|
||||
|
||||
+10
-7
@@ -25,21 +25,24 @@
|
||||
|
||||
using namespace masc;
|
||||
|
||||
bool Feature::CheckSFExistence(ccPointCloud* cloud, const char* resultSFName)
|
||||
bool Feature::CheckSFExistence(ccPointCloud* cloud, const QString& resultSFName)
|
||||
{
|
||||
if (!cloud || !resultSFName)
|
||||
if (!cloud || resultSFName.isEmpty())
|
||||
{
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
int sfIdx = cloud->getScalarFieldIndexByName(resultSFName);
|
||||
int sfIdx = cloud->getScalarFieldIndexByName(resultSFName.toStdString());
|
||||
return (sfIdx >= 0);
|
||||
}
|
||||
|
||||
CCCoreLib::ScalarField* Feature::PrepareSF(ccPointCloud* cloud, const char* resultSFName, SFCollector* generatedScalarFields/*=nullptr*/, SFCollector::Behavior behavior/*=SFCollector::CAN_REMOVE*/)
|
||||
CCCoreLib::ScalarField* Feature::PrepareSF( ccPointCloud* cloud,
|
||||
const QString& resultSFName,
|
||||
SFCollector* generatedScalarFields/*=nullptr*/,
|
||||
SFCollector::Behavior behavior/*=SFCollector::CAN_REMOVE*/ )
|
||||
{
|
||||
if (!cloud || !resultSFName)
|
||||
if (!cloud || resultSFName.isEmpty())
|
||||
{
|
||||
//invalid input parameters
|
||||
assert(false);
|
||||
@@ -47,7 +50,7 @@ CCCoreLib::ScalarField* Feature::PrepareSF(ccPointCloud* cloud, const char* resu
|
||||
}
|
||||
|
||||
CCCoreLib::ScalarField* resultSF = nullptr;
|
||||
int sfIdx = cloud->getScalarFieldIndexByName(resultSFName);
|
||||
int sfIdx = cloud->getScalarFieldIndexByName(resultSFName.toStdString());
|
||||
if (sfIdx >= 0)
|
||||
{
|
||||
// ccLog::Warning("Existing SF: " + QString(resultSFName) + ", do not store in generatedScalarFields");
|
||||
@@ -56,7 +59,7 @@ CCCoreLib::ScalarField* Feature::PrepareSF(ccPointCloud* cloud, const char* resu
|
||||
else
|
||||
{
|
||||
// ccLog::Warning("SF does not exist, create it: " + QString(resultSFName) + ", SFCollector::Behavior " + QString::number(behavior));
|
||||
ccScalarField* newSF = new ccScalarField(resultSFName);
|
||||
ccScalarField* newSF = new ccScalarField(resultSFName.toStdString());
|
||||
if (!newSF->resizeSafe(cloud->size()))
|
||||
{
|
||||
ccLog::Warning("Not enough memory");
|
||||
|
||||
+2
-2
@@ -215,10 +215,10 @@ namespace masc
|
||||
public: //helpers
|
||||
|
||||
//! Creates (or resets) a scalar field with the given name on the input core points cloud
|
||||
static bool CheckSFExistence(ccPointCloud* cloud, const char* resultSFName);
|
||||
static bool CheckSFExistence(ccPointCloud* cloud, const QString& resultSFName);
|
||||
|
||||
//! Creates (or resets) a scalar field with the given name on the input core points cloud
|
||||
static CCCoreLib::ScalarField* PrepareSF(ccPointCloud* cloud, const char* resultSFName, SFCollector* generatedScalarFields/*= nullptr*/, SFCollector::Behavior behavior);
|
||||
static CCCoreLib::ScalarField* PrepareSF(ccPointCloud* cloud, const QString& resultSFName, SFCollector* generatedScalarFields/*= nullptr*/, SFCollector::Behavior behavior);
|
||||
|
||||
//! Performs a mathematical operation between two scalars
|
||||
static ScalarType PerformMathOp(double s1, double s2, Operation op);
|
||||
|
||||
@@ -89,23 +89,23 @@ bool NeighborhoodFeature::prepare( const CorePoints& corePoints,
|
||||
|
||||
//and the scalar field
|
||||
assert(!sf1);
|
||||
sf1WasAlreadyExisting = CheckSFExistence(corePoints.cloud, qPrintable(resultSFName));
|
||||
sf1WasAlreadyExisting = CheckSFExistence(corePoints.cloud, resultSFName);
|
||||
if (sf1WasAlreadyExisting)
|
||||
{
|
||||
sf1 = PrepareSF(corePoints.cloud, qPrintable(resultSFName), generatedScalarFields, SFCollector::ALWAYS_KEEP);
|
||||
sf1 = PrepareSF(corePoints.cloud, resultSFName, generatedScalarFields, SFCollector::ALWAYS_KEEP);
|
||||
if (generatedScalarFields->scalarFields.contains(sf1)) // i.e. the SF is existing but was not present at the startup of the plugin
|
||||
generatedScalarFields->setBehavior(sf1, SFCollector::CAN_REMOVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
sf1 = PrepareSF(corePoints.cloud, qPrintable(resultSFName), generatedScalarFields, SFCollector::CAN_REMOVE);
|
||||
sf1 = PrepareSF(corePoints.cloud, resultSFName, generatedScalarFields, SFCollector::CAN_REMOVE);
|
||||
}
|
||||
if (!sf1)
|
||||
{
|
||||
error = QString("Failed to prepare scalar %1 @ scale %2").arg(resultSFName).arg(scale);
|
||||
return false;
|
||||
}
|
||||
source.name = sf1->getName();
|
||||
source.name = QString::fromStdString(sf1->getName());
|
||||
|
||||
// sf2 is not needed if sf1 was already existing!
|
||||
if (cloud2 && op != Feature::NO_OPERATION && !sf1WasAlreadyExisting)
|
||||
@@ -114,8 +114,8 @@ bool NeighborhoodFeature::prepare( const CorePoints& corePoints,
|
||||
|
||||
assert(!sf2);
|
||||
|
||||
sf2WasAlreadyExisting = CheckSFExistence(corePoints.cloud, qPrintable(resultSFName2));
|
||||
sf2 = PrepareSF(corePoints.cloud, qPrintable(resultSFName2), generatedScalarFields, sf2WasAlreadyExisting ? SFCollector::ALWAYS_KEEP : SFCollector::ALWAYS_REMOVE);
|
||||
sf2WasAlreadyExisting = CheckSFExistence(corePoints.cloud, resultSFName2);
|
||||
sf2 = PrepareSF(corePoints.cloud, resultSFName2, generatedScalarFields, sf2WasAlreadyExisting ? SFCollector::ALWAYS_KEEP : SFCollector::ALWAYS_REMOVE);
|
||||
|
||||
if (!sf2)
|
||||
{
|
||||
|
||||
+18
-14
@@ -581,34 +581,34 @@ bool PointFeature::prepare( const CorePoints& corePoints,
|
||||
resultSF1Name += "@" + QString::number(scale);
|
||||
|
||||
//prepare the corresponding scalar field
|
||||
sf1WasAlreadyExisting = CheckSFExistence(corePoints.cloud, qPrintable(resultSF1Name));
|
||||
sf1WasAlreadyExisting = CheckSFExistence(corePoints.cloud, resultSF1Name);
|
||||
if (sf1WasAlreadyExisting)
|
||||
{
|
||||
// if the SF exists, it is not added to generatedScalarFields
|
||||
statSF1 = PrepareSF(corePoints.cloud, qPrintable(resultSF1Name), generatedScalarFields, SFCollector::ALWAYS_KEEP);
|
||||
statSF1 = PrepareSF(corePoints.cloud, resultSF1Name, generatedScalarFields, SFCollector::ALWAYS_KEEP);
|
||||
if (generatedScalarFields->scalarFields.contains(statSF1)) // i.e. the SF is existing but was not present at the startup of the plugin
|
||||
generatedScalarFields->setBehavior(statSF1, SFCollector::CAN_REMOVE);
|
||||
}
|
||||
else
|
||||
statSF1 = PrepareSF(corePoints.cloud, qPrintable(resultSF1Name), generatedScalarFields, SFCollector::CAN_REMOVE);
|
||||
statSF1 = PrepareSF(corePoints.cloud, resultSF1Name, generatedScalarFields, SFCollector::CAN_REMOVE);
|
||||
if (!statSF1)
|
||||
{
|
||||
error = QString("Failed to prepare scalar field for field '%1' @ scale %2").arg(field1->getName()).arg(scale);
|
||||
return false;
|
||||
}
|
||||
source.name = statSF1->getName();
|
||||
source.name = QString::fromStdString(statSF1->getName());
|
||||
|
||||
if (field2 && op != Feature::NO_OPERATION && !sf1WasAlreadyExisting) // nothing to do if statSF1 was already there
|
||||
{
|
||||
QString resultSF2Name = field2->getName() + QString("_") + cloud2Label + "_" + Feature::StatToString(stat) + "@" + QString::number(scale);
|
||||
//keepStatSF2 = (corePoints.cloud->getScalarFieldIndexByName(qPrintable(resultSFName2)) >= 0); //we remember that the scalar field was already existing!
|
||||
//keepStatSF2 = (corePoints.cloud->getScalarFieldIndexByName(resultSFName2) >= 0); //we remember that the scalar field was already existing!
|
||||
|
||||
assert(!statSF2);
|
||||
sf2WasAlreadyExisting = CheckSFExistence(corePoints.cloud, qPrintable(resultSF2Name));
|
||||
sf2WasAlreadyExisting = CheckSFExistence(corePoints.cloud, resultSF2Name);
|
||||
if (sf2WasAlreadyExisting)
|
||||
statSF2 = PrepareSF(corePoints.cloud, qPrintable(resultSF2Name), generatedScalarFields, SFCollector::ALWAYS_KEEP);
|
||||
statSF2 = PrepareSF(corePoints.cloud, resultSF2Name, generatedScalarFields, SFCollector::ALWAYS_KEEP);
|
||||
else
|
||||
statSF2 = PrepareSF(corePoints.cloud, qPrintable(resultSF2Name), generatedScalarFields, SFCollector::ALWAYS_REMOVE);
|
||||
statSF2 = PrepareSF(corePoints.cloud, resultSF2Name, generatedScalarFields, SFCollector::ALWAYS_REMOVE);
|
||||
if (!statSF2)
|
||||
{
|
||||
error = QString("Failed to prepare scalar field for field '%1' @ scale %2").arg(field2->getName()).arg(scale);
|
||||
@@ -623,7 +623,7 @@ bool PointFeature::prepare( const CorePoints& corePoints,
|
||||
assert(cloud1 == corePoints.cloud || cloud1 == corePoints.origin);
|
||||
|
||||
//retrieve/create a SF to host the result
|
||||
int sfIdx = corePoints.cloud->getScalarFieldIndexByName(qPrintable(resultSF1Name));
|
||||
int sfIdx = corePoints.cloud->getScalarFieldIndexByName(resultSF1Name.toStdString());
|
||||
|
||||
CCCoreLib::ScalarField* resultSF = nullptr;
|
||||
if (sfIdx >= 0)
|
||||
@@ -634,7 +634,7 @@ bool PointFeature::prepare( const CorePoints& corePoints,
|
||||
else
|
||||
{
|
||||
//copy the SF1 field
|
||||
resultSF = new ccScalarField(qPrintable(resultSF1Name));
|
||||
resultSF = new ccScalarField(resultSF1Name.toStdString());
|
||||
if (!resultSF->resizeSafe(corePoints.cloud->size()))
|
||||
{
|
||||
error = "Not enough memory";
|
||||
@@ -679,7 +679,7 @@ bool PointFeature::prepare( const CorePoints& corePoints,
|
||||
corePoints.cloud->setCurrentDisplayedScalarField(newSFIdx);
|
||||
}
|
||||
|
||||
source.name = resultSF->getName();
|
||||
source.name = QString::fromStdString(resultSF->getName());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -738,7 +738,7 @@ bool PointFeature::computeStat(const CCCoreLib::DgmOctree::NeighboursSet& points
|
||||
double sum = 0.0;
|
||||
double sum2 = 0.0;
|
||||
|
||||
CCCoreLib::WeibullDistribution::ScalarContainer values;
|
||||
std::vector<ScalarType> values;
|
||||
if (storeValues)
|
||||
{
|
||||
try
|
||||
@@ -781,8 +781,10 @@ bool PointFeature::computeStat(const CCCoreLib::DgmOctree::NeighboursSet& points
|
||||
case Feature::MODE:
|
||||
{
|
||||
CCCoreLib::WeibullDistribution w;
|
||||
if (w.computeParameters(values))
|
||||
if (w.computeParameters(CCCoreLib::WeibullDistribution::VectorAsScalarContainer(values)))
|
||||
{
|
||||
outputValue = w.computeMode();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -810,8 +812,10 @@ bool PointFeature::computeStat(const CCCoreLib::DgmOctree::NeighboursSet& points
|
||||
case Feature::SKEW:
|
||||
{
|
||||
CCCoreLib::WeibullDistribution w;
|
||||
if (w.computeParameters(values))
|
||||
if (w.computeParameters(CCCoreLib::WeibullDistribution::VectorAsScalarContainer(values)))
|
||||
{
|
||||
outputValue = w.computeSkewness();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ public:
|
||||
: m_sf(sf)
|
||||
{}
|
||||
|
||||
virtual inline double pointValue(unsigned index) const override { return m_sf->at(index); }
|
||||
virtual inline double pointValue(unsigned index) const override { return m_sf->getValue(index); }
|
||||
virtual inline bool isValid() const { return m_sf != nullptr; }
|
||||
virtual inline QString getName() const { return m_sf->getName(); }
|
||||
virtual inline QString getName() const { return QString::fromStdString(m_sf->getName()); }
|
||||
virtual size_t size() const override { return m_sf->size(); }
|
||||
|
||||
protected:
|
||||
|
||||
+15
-16
@@ -36,7 +36,7 @@ static QColor GetColor(double value, double r1, double g1, double b1)
|
||||
return QColor(r, g, b);
|
||||
}
|
||||
|
||||
ConfusionMatrix::ConfusionMatrix(const std::vector<ScalarType> &actual, const std::vector<ScalarType> &predicted)
|
||||
ConfusionMatrix::ConfusionMatrix(const CCCoreLib::GenericDistribution::ScalarContainer& actual, const CCCoreLib::GenericDistribution::ScalarContainer& predicted)
|
||||
: nbClasses(0)
|
||||
, ui(new Ui::ConfusionMatrix)
|
||||
, m_overallAccuracy(0.0f)
|
||||
@@ -78,7 +78,7 @@ void ConfusionMatrix::computePrecisionRecallF1Score(cv::Mat& matrix, cv::Mat& pr
|
||||
}
|
||||
float TP_FP = TP + FP;
|
||||
if (TP_FP == 0)
|
||||
precisionRecallF1Score.at<float>(predictedIdx, PRECISION) = CCCoreLib::NAN_VALUE;
|
||||
precisionRecallF1Score.at<float>(predictedIdx, PRECISION) = std::numeric_limits<float>::quiet_NaN();
|
||||
else
|
||||
precisionRecallF1Score.at<float>(predictedIdx, PRECISION) = TP / TP_FP;
|
||||
}
|
||||
@@ -97,7 +97,7 @@ void ConfusionMatrix::computePrecisionRecallF1Score(cv::Mat& matrix, cv::Mat& pr
|
||||
}
|
||||
float TP_FN = TP + FN;
|
||||
if (TP_FN == 0)
|
||||
precisionRecallF1Score.at<float>(realIdx, RECALL) = CCCoreLib::NAN_VALUE;
|
||||
precisionRecallF1Score.at<float>(realIdx, RECALL) = std::numeric_limits<float>::quiet_NaN();
|
||||
else
|
||||
precisionRecallF1Score.at<float>(realIdx, RECALL) = TP / TP_FN;
|
||||
vec_TP_FN.at<int>(realIdx, 0) = TP_FN;
|
||||
@@ -109,7 +109,7 @@ void ConfusionMatrix::computePrecisionRecallF1Score(cv::Mat& matrix, cv::Mat& pr
|
||||
float den = precisionRecallF1Score.at<float>(realIdx, PRECISION)
|
||||
+ precisionRecallF1Score.at<float>(realIdx, RECALL);
|
||||
if (den == 0)
|
||||
precisionRecallF1Score.at<float>(realIdx, F1_SCORE) = CCCoreLib::NAN_VALUE;
|
||||
precisionRecallF1Score.at<float>(realIdx, F1_SCORE) = std::numeric_limits<float>::quiet_NaN();
|
||||
else
|
||||
precisionRecallF1Score.at<float>(realIdx, F1_SCORE) =
|
||||
2
|
||||
@@ -141,20 +141,19 @@ float ConfusionMatrix::computeOverallAccuracy(cv::Mat& matrix)
|
||||
if ((totalTrue + totalFalse) != 0)
|
||||
m_overallAccuracy = totalTrue / (totalTrue + totalFalse);
|
||||
else
|
||||
m_overallAccuracy = CCCoreLib::NAN_VALUE;
|
||||
m_overallAccuracy = std::numeric_limits<float>::quiet_NaN();
|
||||
|
||||
return m_overallAccuracy;
|
||||
}
|
||||
|
||||
void ConfusionMatrix::compute(const std::vector<ScalarType>& actual, const std::vector<ScalarType>& predicted)
|
||||
void ConfusionMatrix::compute(const CCCoreLib::GenericDistribution::ScalarContainer& actual, const CCCoreLib::GenericDistribution::ScalarContainer& predicted)
|
||||
{
|
||||
int idxActual;
|
||||
int idxPredicted;
|
||||
int actualClass;
|
||||
int predictedClass;
|
||||
|
||||
// get the set of classes with the contents of the actual classes
|
||||
std::set<ScalarType> classes(actual.begin(), actual.end());
|
||||
std::set<ScalarType> classes;
|
||||
for (size_t i = 0; i < actual.size(); ++i)
|
||||
{
|
||||
classes.insert(actual.getValue(i));
|
||||
}
|
||||
int nbClasses = static_cast<int>(classes.size());
|
||||
confusionMatrix = cv::Mat(nbClasses, nbClasses, CV_32S, cv::Scalar(0));
|
||||
precisionRecallF1Score = cv::Mat(nbClasses, 3, CV_32F, cv::Scalar(0));
|
||||
@@ -163,10 +162,10 @@ void ConfusionMatrix::compute(const std::vector<ScalarType>& actual, const std::
|
||||
// fill the confusion matrix
|
||||
for (int i = 0; i < actual.size(); i++)
|
||||
{
|
||||
actualClass = actual.at(i);
|
||||
idxActual = std::distance(classes.begin(), classes.find(actualClass));
|
||||
predictedClass = predicted.at(i);
|
||||
idxPredicted = std::distance(classes.begin(), classes.find(predictedClass));
|
||||
int actualClass = static_cast<int>(actual.getValue(i));
|
||||
int idxActual = std::distance(classes.begin(), classes.find(actualClass));
|
||||
int predictedClass = static_cast<int>(predicted.getValue(i));
|
||||
int idxPredicted = std::distance(classes.begin(), classes.find(predictedClass));
|
||||
confusionMatrix.at<int>(idxActual, idxPredicted)++;
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -3,7 +3,7 @@
|
||||
#include <QWidget>
|
||||
#include <set>
|
||||
|
||||
#include "CCTypes.h"
|
||||
#include <GenericDistribution.h>
|
||||
|
||||
#include <ccMainAppInterface.h>
|
||||
|
||||
@@ -25,13 +25,12 @@ public:
|
||||
F1_SCORE = 2
|
||||
};
|
||||
|
||||
explicit ConfusionMatrix(const std::vector<ScalarType>& actual,
|
||||
const std::vector<ScalarType>& predicted);
|
||||
explicit ConfusionMatrix(const CCCoreLib::GenericDistribution::ScalarContainer& actual, const CCCoreLib::GenericDistribution::ScalarContainer& predicted);
|
||||
~ConfusionMatrix() override;
|
||||
|
||||
void computePrecisionRecallF1Score(cv::Mat& matrix, cv::Mat& precisionRecallF1Score, cv::Mat &vec_TP_FN);
|
||||
float computeOverallAccuracy(cv::Mat& matrix);
|
||||
void compute(const std::vector<ScalarType> &actual, const std::vector<ScalarType> &predicted);
|
||||
void compute(const CCCoreLib::GenericDistribution::ScalarContainer& actual, const CCCoreLib::GenericDistribution::ScalarContainer& predicted);
|
||||
void setSessionRun(QString session, int run);
|
||||
bool save(QString filePath);
|
||||
float getOverallAccuracy();
|
||||
|
||||
@@ -70,7 +70,7 @@ static IScalarFieldWrapper::Shared GetSource(const Feature::Source& fs, const cc
|
||||
case Feature::Source::ScalarField:
|
||||
{
|
||||
assert(!fs.name.isEmpty());
|
||||
int sfIdx = cloud->getScalarFieldIndexByName(qPrintable(fs.name));
|
||||
int sfIdx = cloud->getScalarFieldIndexByName(fs.name.toStdString());
|
||||
if (sfIdx >= 0)
|
||||
{
|
||||
source.reset(new ScalarFieldWrapper(cloud->getScalarField(sfIdx)));
|
||||
@@ -288,7 +288,8 @@ bool Classifier::classify( const Feature::Source::Set& featureSources,
|
||||
{
|
||||
if (app)
|
||||
{
|
||||
ConfusionMatrix *confusionMatrix = new ConfusionMatrix(*classifSFBackup, *classificationSF);
|
||||
ConfusionMatrix* confusionMatrix = new ConfusionMatrix(CCCoreLib::GenericDistribution::SFAsScalarContainer(*classifSFBackup),
|
||||
CCCoreLib::GenericDistribution::SFAsScalarContainer(*classificationSF));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,12 +347,12 @@ bool Classifier::evaluate(const Feature::Source::Set& featureSources,
|
||||
|
||||
if (!outputSFName.isEmpty())
|
||||
{
|
||||
int outIdx = testCloud->getScalarFieldIndexByName(qPrintable(outputSFName));
|
||||
int outIdx = testCloud->getScalarFieldIndexByName(outputSFName.toStdString());
|
||||
if (outIdx >= 0)
|
||||
testCloud->deleteScalarField(outIdx);
|
||||
else
|
||||
ccLog::Print("add " + outputSFName + " to the TEST cloud");
|
||||
outIdx = testCloud->addScalarField(qPrintable(outputSFName));
|
||||
outIdx = testCloud->addScalarField(outputSFName.toStdString());
|
||||
outSF = static_cast<ccScalarField*>(testCloud->getScalarField(outIdx));
|
||||
}
|
||||
|
||||
@@ -481,7 +482,8 @@ bool Classifier::evaluate(const Feature::Source::Set& featureSources,
|
||||
metrics.ratio = static_cast<float>(metrics.goodGuess) / metrics.sampleCount;
|
||||
}
|
||||
|
||||
ConfusionMatrix* confusionMatrix = new ConfusionMatrix(actualClass, predictectedClass);
|
||||
ConfusionMatrix* confusionMatrix = new ConfusionMatrix(CCCoreLib::GenericDistribution::VectorAsScalarContainer(actualClass),
|
||||
CCCoreLib::GenericDistribution::VectorAsScalarContainer(predictectedClass));
|
||||
train3DMASCDialog.addConfusionMatrixAndSaveTraces(confusionMatrix);
|
||||
if (app)
|
||||
{
|
||||
|
||||
+2
-2
@@ -1013,14 +1013,14 @@ CCCoreLib::ScalarField* Tools::RetrieveSF(const ccPointCloud* cloud, const QStri
|
||||
int sfIdx = -1;
|
||||
if (caseSensitive)
|
||||
{
|
||||
sfIdx = cloud->getScalarFieldIndexByName(qPrintable(sfName));
|
||||
sfIdx = cloud->getScalarFieldIndexByName(sfName.toStdString());
|
||||
}
|
||||
else
|
||||
{
|
||||
QString sfNameUpper = sfName.toUpper();
|
||||
for (unsigned i = 0; i < cloud->getNumberOfScalarFields(); ++i)
|
||||
{
|
||||
if (QString(cloud->getScalarField(i)->getName()).toUpper() == sfNameUpper)
|
||||
if (QString::fromStdString(cloud->getScalarField(i)->getName()).toUpper() == sfNameUpper)
|
||||
{
|
||||
sfIdx = static_cast<int>(i);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user