mirror of
https://github.com/dgirardeau/q3DMASC.git
synced 2026-08-29 08:34:48 +08:00
save traces
When the option is selected, overall accuracy, features and classifiers are saved
This commit is contained in:
@@ -259,6 +259,16 @@
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_keepTraces">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, a directory is created near the parameters file. Each time you click on Run, the features used to train the random forest will be stored and an entry will be created in a specific file to save the metrics associated with the classifier.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Keep traces</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
+15
-4
@@ -89,7 +89,9 @@ float ConfusionMatrix::computeOverallAccuracy(cv::Mat& matrix)
|
||||
int nbClasses = matrix.rows;
|
||||
float totalTrue = 0;
|
||||
float totalFalse = 0;
|
||||
float overallAccuracy = 0.;
|
||||
|
||||
m_overallAccuracy = 0.0;
|
||||
|
||||
for (int realIdx = 0; realIdx < nbClasses; realIdx++)
|
||||
{
|
||||
for (int predictedIdx = 0; predictedIdx< nbClasses; predictedIdx++)
|
||||
@@ -101,11 +103,11 @@ float ConfusionMatrix::computeOverallAccuracy(cv::Mat& matrix)
|
||||
}
|
||||
}
|
||||
if ((totalTrue + totalFalse) != 0)
|
||||
overallAccuracy = totalTrue / (totalTrue + totalFalse);
|
||||
m_overallAccuracy = totalTrue / (totalTrue + totalFalse);
|
||||
else
|
||||
overallAccuracy = CCCoreLib::NAN_VALUE;
|
||||
m_overallAccuracy = CCCoreLib::NAN_VALUE;
|
||||
|
||||
return overallAccuracy;
|
||||
return m_overallAccuracy;
|
||||
}
|
||||
|
||||
void ConfusionMatrix::compute(std::vector<ScalarType>& actual, std::vector<ScalarType>& predicted)
|
||||
@@ -219,3 +221,12 @@ void ConfusionMatrix::compute(std::vector<ScalarType>& actual, std::vector<Scala
|
||||
this->ui->tableWidget->setItem(2 + realIdx, 2 + nbClasses + F1_SCORE, newItem);
|
||||
}
|
||||
}
|
||||
|
||||
void ConfusionMatrix::setSessionRun(QString session, int run)
|
||||
{
|
||||
QString label;
|
||||
|
||||
label = session + " / " + QString::number(run);
|
||||
|
||||
this->ui->label_sessionRun->setText(label);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ public:
|
||||
void computePrecisionRecallF1Score(cv::Mat& matrix, cv::Mat& precisionRecallF1Score);
|
||||
float computeOverallAccuracy(cv::Mat& matrix);
|
||||
void compute(std::vector<ScalarType>& actual, std::vector<ScalarType>& predicted);
|
||||
void setSessionRun(QString session, int run);
|
||||
float m_overallAccuracy;
|
||||
|
||||
private:
|
||||
Ui::ConfusionMatrix *ui;
|
||||
|
||||
+14
-49
@@ -13,8 +13,8 @@
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" rowminimumheight="1,0">
|
||||
<item row="0" column="0" colspan="7">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="5">
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
@@ -36,25 +36,6 @@
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Overall accuracy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_overallAccuracy">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
@@ -68,51 +49,35 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Session</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="label_session">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_overallAccuracy">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Run</string>
|
||||
<string>Overall accuracy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6">
|
||||
<widget class="QLabel" name="label_run">
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_sessionRun">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
|
||||
+21
@@ -390,6 +390,7 @@ void q3DMASCPlugin::doTrainAction()
|
||||
trainDlg.minSampleCountSpinBox->setValue(s_params.rt.minSampleCount);
|
||||
trainDlg.testDataRatioSpinBox->setValue(static_cast<int>(s_params.testDataRatio * 100));
|
||||
trainDlg.testDataRatioSpinBox->setEnabled(testCloud == nullptr);
|
||||
trainDlg.setInputFilePath(inputFilename);
|
||||
|
||||
//display the loaded features and let the user select the ones to use
|
||||
trainDlg.setResultText("Select features and press 'Run'");
|
||||
@@ -689,6 +690,26 @@ void q3DMASCPlugin::doTrainAction()
|
||||
}
|
||||
|
||||
trainDlg.sortByFeatureImportance();
|
||||
|
||||
// if the checkbox "Save traces" is checked
|
||||
if (trainDlg.getSaveTrace())
|
||||
{
|
||||
//save the classifier in the trace directory with a generic name depending on the run
|
||||
QString tracePath = trainDlg.getTracePath();
|
||||
if (!tracePath.isEmpty())
|
||||
{
|
||||
QString outputFilename = tracePath + "/run_" + QString::number(trainDlg.getRun()) + ".txt";
|
||||
if (masc::Tools::SaveClassifier(outputFilename, features, mainCloudLabel, classifier, m_app->getMainWindow()))
|
||||
{
|
||||
m_app->dispToConsole("Classifier succesfully saved to " + outputFilename, ccMainAppInterface::STD_CONSOLE_MESSAGE);
|
||||
trainDlg.setClassifierSaved();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_app->dispToConsole("Failed to save classifier file");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ bool Tools::SaveClassifier( QString filename,
|
||||
const masc::Classifier& classifier,
|
||||
QWidget* parent/*=nullptr*/)
|
||||
{
|
||||
//first save the classifier data (same base filename but with the ymal extension)
|
||||
//first save the classifier data (same base filename but with the yaml extension)
|
||||
QFileInfo fi(filename);
|
||||
QString yamlFilename = fi.baseName() + ".yaml";
|
||||
QString yamlAbsoluteFilename = fi.absoluteDir().absoluteFilePath(yamlFilename);
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
#include <QFileDialog>
|
||||
#include <QSettings>
|
||||
#include <QTextStream>
|
||||
#include <QStandardPaths>
|
||||
#include <QDateTime>
|
||||
|
||||
#include <ccLog.h>
|
||||
|
||||
//System
|
||||
#include <assert.h>
|
||||
@@ -36,14 +40,43 @@ Train3DMASCDialog::Train3DMASCDialog(QWidget* parent/*=nullptr*/)
|
||||
, Ui::Train3DMASCDialog()
|
||||
, classifierSaved(false)
|
||||
, saveRequested(false)
|
||||
, traceFileConfigured(false)
|
||||
, m_traceFile(nullptr)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
QDateTime dateTime = QDateTime::currentDateTime();
|
||||
m_baseName = "3dmasc_" + dateTime.toString("yyyyMMdd") + "_" + dateTime.toString("hh") + "h" + dateTime.toString("mm");
|
||||
run = 0;
|
||||
|
||||
readSettings();
|
||||
|
||||
connect(closePushButton, SIGNAL(clicked()), this, SLOT(onClose()));
|
||||
connect(savePushButton, SIGNAL(clicked()), this, SLOT(onSave()));
|
||||
connect(exportToolButton, SIGNAL(clicked()), this, SLOT(onExportResults()));
|
||||
}
|
||||
|
||||
Train3DMASCDialog::~Train3DMASCDialog()
|
||||
{
|
||||
writeSettings();
|
||||
closeTraceFile();
|
||||
}
|
||||
|
||||
void Train3DMASCDialog::readSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup("3DMASC");
|
||||
bool saveTrace = settings.value("saveTrace", false).toBool();
|
||||
setCheckBoxSaveTrace(saveTrace);
|
||||
}
|
||||
|
||||
void Train3DMASCDialog::writeSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.beginGroup("3DMASC");
|
||||
settings.setValue("saveTrace", checkBox_keepTraces->isChecked());
|
||||
}
|
||||
|
||||
void Train3DMASCDialog::clearResults()
|
||||
{
|
||||
resultLabel->clear();
|
||||
@@ -189,5 +222,132 @@ void Train3DMASCDialog::onExportResults()
|
||||
|
||||
void Train3DMASCDialog::addConfusionMatrix(std::unique_ptr<ConfusionMatrix>& ptr)
|
||||
{
|
||||
run++; // increment the run number
|
||||
ptr->setSessionRun(m_baseName, run);
|
||||
saveTraces(*ptr);
|
||||
m_confusionMatrices.push_back(std::move(ptr));
|
||||
}
|
||||
|
||||
void Train3DMASCDialog::setInputFilePath(QString filePath)
|
||||
{
|
||||
m_parameterFilePath = filePath;
|
||||
}
|
||||
|
||||
void Train3DMASCDialog::setCheckBoxSaveTrace(bool state)
|
||||
{
|
||||
checkBox_keepTraces->setChecked(state);
|
||||
}
|
||||
|
||||
bool Train3DMASCDialog::openTraceFile()
|
||||
{
|
||||
QString traceFileName;
|
||||
QString traceFilePath;
|
||||
|
||||
// get currentPath
|
||||
QFileInfo info(m_parameterFilePath);
|
||||
QDir parameterDir = QDir(info.path());
|
||||
|
||||
QFileDialog dialog(this);
|
||||
dialog.setFileMode(QFileDialog::DirectoryOnly);
|
||||
dialog.setWindowTitle("Choose a valid directory for the traces");
|
||||
dialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).at(0));
|
||||
|
||||
if (!m_traceFile) // create trace file if it does not exists already
|
||||
{
|
||||
m_tracePath = parameterDir.absolutePath() + "/" + m_baseName;
|
||||
traceFileName = m_baseName + ".txt";
|
||||
|
||||
if (!parameterDir.mkdir(m_baseName)) // create a specific directory to store the traces
|
||||
{
|
||||
ccLog::Error("impossible to save in the default directory: " + m_tracePath);
|
||||
// impossible to save in the default directory, you have to propose another path
|
||||
if(dialog.exec())
|
||||
m_tracePath = dialog.selectedFiles().at(0);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
ccLog::Print("directory for traces created: " + m_tracePath);
|
||||
|
||||
traceFilePath = m_tracePath + "/" + traceFileName;
|
||||
m_traceFile = new QFile(traceFilePath);
|
||||
|
||||
if(!m_traceFile->open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
{
|
||||
ccLog::Error("impossible to open trace file: " + traceFilePath);
|
||||
delete m_traceFile;
|
||||
m_tracePath.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_traceFile && m_traceFile->isOpen())
|
||||
{
|
||||
traceFileConfigured = true;
|
||||
ccLog::Print("save trace in: " + traceFilePath);
|
||||
m_traceStream.setDevice(m_traceFile);
|
||||
m_traceStream << "run overallAccuracy\n";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Train3DMASCDialog::closeTraceFile()
|
||||
{
|
||||
if (m_traceFile)
|
||||
if (m_traceFile->isOpen())
|
||||
{
|
||||
ccLog::Print("[3DMASC] traces stored in: " + m_traceFile->fileName());
|
||||
m_traceFile->close();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Train3DMASCDialog::saveTraces(ConfusionMatrix &confusionMatrix)
|
||||
{
|
||||
if (checkBox_keepTraces->isChecked())
|
||||
{
|
||||
if (!traceFileConfigured) // if the trace file is not configured yet, do it
|
||||
{
|
||||
if (!openTraceFile())
|
||||
return;
|
||||
}
|
||||
else // save the trace
|
||||
{
|
||||
// save the run number and the overall accuracy
|
||||
if (m_traceStream.device())
|
||||
m_traceStream << run << " " << confusionMatrix.m_overallAccuracy << Qt::endl;
|
||||
// save the confusion matrix
|
||||
// save the features
|
||||
// save the classifier
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Train3DMASCDialog::getSaveTrace()
|
||||
{
|
||||
return checkBox_keepTraces->isChecked();
|
||||
}
|
||||
|
||||
QString Train3DMASCDialog::getTracePath()
|
||||
{
|
||||
if (traceFileConfigured)
|
||||
{
|
||||
QFileInfo fi(*m_traceFile);
|
||||
return fi.absoluteDir().absolutePath();
|
||||
}
|
||||
else if (openTraceFile())
|
||||
{
|
||||
QFileInfo fi(*m_traceFile);
|
||||
return fi.absoluteDir().absolutePath();
|
||||
}
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
|
||||
int Train3DMASCDialog::getRun()
|
||||
{
|
||||
return run;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
//Qt
|
||||
#include <QDialog>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <ui_Train3DMASCDialog.h>
|
||||
|
||||
@@ -33,6 +35,10 @@ public:
|
||||
|
||||
//! Default constructor
|
||||
Train3DMASCDialog(QWidget* parent = nullptr);
|
||||
~Train3DMASCDialog();
|
||||
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
|
||||
void clearResults();
|
||||
|
||||
@@ -54,6 +60,14 @@ public:
|
||||
inline bool shouldSaveClassifier() const { return saveRequested; }
|
||||
|
||||
void addConfusionMatrix(std::unique_ptr<ConfusionMatrix>& ptr);
|
||||
void setInputFilePath(QString filename);
|
||||
void setCheckBoxSaveTrace(bool state);
|
||||
bool openTraceFile();
|
||||
bool closeTraceFile();
|
||||
void saveTraces(ConfusionMatrix &confusionMatrix);
|
||||
bool getSaveTrace();
|
||||
QString getTracePath();
|
||||
int getRun();
|
||||
|
||||
protected slots:
|
||||
|
||||
@@ -66,4 +80,11 @@ protected: //members
|
||||
bool classifierSaved;
|
||||
bool saveRequested;
|
||||
std::vector<std::unique_ptr<ConfusionMatrix>> m_confusionMatrices;
|
||||
bool traceFileConfigured;
|
||||
QFile *m_traceFile;
|
||||
QString m_tracePath;
|
||||
QTextStream m_traceStream;
|
||||
QString m_parameterFilePath;
|
||||
QString m_baseName;
|
||||
uint run;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user