diff --git a/CMakeLists.txt b/CMakeLists.txt index 40d0b92..e559fbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ if (INSTALL_Q3DMASC_PLUGIN) project( Q3DMASC_PLUGIN ) AddPlugin( NAME ${PROJECT_NAME} ) - set(Q3DMASC_PLUGIN_VERSION "0.8") + set(Q3DMASC_PLUGIN_VERSION "0.8+") include( CMakePolicies NO_POLICY_SCOPE ) diff --git a/ContextBasedFeature.cpp b/ContextBasedFeature.cpp index 1a36bcf..4102a77 100644 --- a/ContextBasedFeature.cpp +++ b/ContextBasedFeature.cpp @@ -132,7 +132,7 @@ bool ContextBasedFeature::prepare( const CorePoints& corePoints, if (!scaled() && !sfWasAlreadyExisting) //with 'kNN' neighbors, we can compute the values right away { unsigned pointCount = corePoints.size(); - QString logMessage = QString("Computing %1 on cloud %2 with context cloud %3\n(core points: %4)").arg(typeStr).arg(corePoints.cloud->getName()).arg(cloud2Label).arg(pointCount); + QString logMessage = QString("Computing %1 on cloud %2 with context cloud %3\n(core points: %4)").arg(typeStr).arg(corePoints.cloud->getName()).arg(cloud1Label).arg(pointCount); //first: look for the number of points in the relevent class const ScalarType fClass = static_cast(ctxClassLabel); diff --git a/q3DMASCClassifier.cpp b/q3DMASCClassifier.cpp index 9b9c4bb..6b8b7cf 100644 --- a/q3DMASCClassifier.cpp +++ b/q3DMASCClassifier.cpp @@ -129,13 +129,13 @@ bool Classifier::classify( const Feature::Source::Set& featureSources, if (cvConfidenceIdx >= 0) // if the scalar field exists, delete it cloud->deleteScalarField(cvConfidenceIdx); cvConfidenceIdx = cloud->addScalarField("Classification_confidence"); - CCCoreLib::ScalarField* cvConfidenceSF = cloud->getScalarField(cvConfidenceIdx); + ccScalarField* cvConfidenceSF = static_cast(cloud->getScalarField(cvConfidenceIdx)); //look for the classification field CCCoreLib::ScalarField* classificationSF = Tools::GetClassificationSF(cloud); ccScalarField* classifSFBackup = nullptr; - if (classificationSF) //save classification field (if any) + if (classificationSF) //save classification field (if any) by renaming it "Classification_backup" { ccLog::Warning("Classification SF found: copy it in Classification_backup, a confusion matrix will be generated"); // delete Classification_backup field (if any) @@ -143,31 +143,21 @@ bool Classifier::classify( const Feature::Source::Set& featureSources, if (sfIdx >= 0) cloud->deleteScalarField(sfIdx); - // backup the classification field - try - { - classifSFBackup = new ccScalarField(*static_cast(classificationSF)); // copy constructor - classifSFBackup->setName("Classification_backup"); - cloud->addScalarField(classifSFBackup); - } - catch (const std::bad_alloc) - { - ccLog::Warning("Not enough memory to backup the previous classification SF!"); - } + classificationSF->setName("Classification_backup"); // rename the classification field + classifSFBackup = static_cast(classificationSF); } - else + + //create the classification SF + ccScalarField* _classificationSF = new ccScalarField(LAS_FIELD_NAMES[LAS_CLASSIFICATION]); + if (!_classificationSF->resizeSafe(cloud->size())) { - //create the classification SF - ccScalarField* _classificationSF = new ccScalarField(LAS_FIELD_NAMES[LAS_CLASSIFICATION]); - if (!_classificationSF->resizeSafe(cloud->size())) - { - _classificationSF->release(); - errorMessage = QObject::tr("Not enough memory"); - return false; - } - cloud->addScalarField(_classificationSF); - classificationSF = _classificationSF; + _classificationSF->release(); + errorMessage = QObject::tr("Not enough memory"); + return false; } + cloud->addScalarField(_classificationSF); + classificationSF = _classificationSF; + assert(classificationSF); classificationSF->fill(0); //0 = no classification? @@ -329,10 +319,8 @@ bool Classifier::evaluate(const Feature::Source::Set& featureSources, return false; } - CCCoreLib::ScalarField* outSF = nullptr; - CCCoreLib::ScalarField* cvConfidenceSF = nullptr; - - ccLog::Warning("[evaluate] TEST cloud " + testCloud->getName()); + ccScalarField* outSF = nullptr; + ccScalarField* cvConfidenceSF = nullptr; if (!outputSFName.isEmpty()) { @@ -342,7 +330,7 @@ bool Classifier::evaluate(const Feature::Source::Set& featureSources, else ccLog::Warning("add " + outputSFName + " to the TEST cloud"); outIdx = testCloud->addScalarField(qPrintable(outputSFName)); - outSF = testCloud->getScalarField(outIdx); + outSF = static_cast(testCloud->getScalarField(outIdx)); } if (outSF) // add a Classification_confidence value to the test cloud if needed @@ -353,7 +341,7 @@ bool Classifier::evaluate(const Feature::Source::Set& featureSources, else ccLog::Warning("add Classification_confidence to the TEST cloud"); cvConfidenceIdx = testCloud->addScalarField("Classification_confidence"); - cvConfidenceSF = testCloud->getScalarField(cvConfidenceIdx); + cvConfidenceSF = static_cast(testCloud->getScalarField(cvConfidenceIdx)); } unsigned testSampleCount = (testSubset ? testSubset->size() : testCloud->size()); @@ -473,6 +461,20 @@ bool Classifier::evaluate(const Feature::Source::Set& featureSources, train3DMASCDialog.addConfusionMatrixAndSaveTraces(new ConfusionMatrix(actualClass, predictectedClass)); + //show the Classification_prediction field by default + if (outSF) + { + int classifSFIdx = testCloud->getScalarFieldIndexByName(outSF->getName()); + testCloud->setCurrentDisplayedScalarField(classifSFIdx); + testCloud->showSF(true); + } + + if (parentWidget && testCloud->getDisplay()) + { + testCloud->getDisplay()->redraw(); + QCoreApplication::processEvents(); + } + return true; } diff --git a/q3DMASCTools.cpp b/q3DMASCTools.cpp index db1049c..0493c44 100644 --- a/q3DMASCTools.cpp +++ b/q3DMASCTools.cpp @@ -1147,11 +1147,11 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features //Context-based features case Feature::Type::ContextBasedFeature: { - //build the scaled feature list attached to the second cloud (the 'context' cloud) + //build the scaled feature list attached to the context cloud if (feature->cloud1 && !static_cast(feature.data())->sfWasAlreadyExisting) // nothing to compute if the scalar field was already there { - FeaturesAndScales& fas = cloudsWithScaledFeatures[feature->cloud2]; + FeaturesAndScales& fas = cloudsWithScaledFeatures[feature->cloud1]; fas.contextBasedFeaturesPerScale[feature->scale].push_back(qSharedPointerCast(feature)); ++fas.featureCount; if (std::find(fas.scales.begin(), fas.scales.end(), feature->scale) == fas.scales.end()) @@ -1338,7 +1338,7 @@ bool Tools::PrepareFeatures(const CorePoints& corePoints, Feature::Set& features //Context-based features for (ContextBasedFeature::Shared& feature : fas.contextBasedFeaturesPerScale[currentScale]) { - if (feature->cloud1 == sourceCloud && feature->sf) + if (feature->cloud1 == sourceCloud && feature->sf) { ScalarType outputValue = 0; if (!feature->computeValue(nNSS.pointsInNeighbourhood, nNSS.queryPoint, outputValue))