improve kfactor support

add per camera gain
add the ability to save plot to vector pdf
add the ability to plot uint8_t mat types
This commit is contained in:
2021-07-20 23:17:31 +02:00
parent 1b6c3672b6
commit 24646e82ed
12 changed files with 185 additions and 110 deletions

View File

@ -308,9 +308,16 @@ double Cameras::getMeanTemp()
void Cameras::setSetup(const std::vector<CameraSetup>& setups) void Cameras::setSetup(const std::vector<CameraSetup>& setups)
{ {
for(auto& camera : cameras_) for(auto& camera : cameras_)
{
for(auto& setup : setups) for(auto& setup : setups)
{
if(camera->id() == setup.id) if(camera->id() == setup.id)
{
camera->cam()->setBayerMode(setup.bayerMode); camera->cam()->setBayerMode(setup.bayerMode);
camera->cam()->setGain(setup.gain);
}
}
}
} }
void Cameras::store(QSettings &settings) void Cameras::store(QSettings &settings)

View File

@ -101,7 +101,7 @@ cv::Mat ImagePipeline::process(const Profile profile, std::vector<Camera::Image>
<<"at"<<remaped.origin.x<<'x'<<remaped.origin.y; <<"at"<<remaped.origin.x<<'x'<<remaped.origin.y;
RemapedImage remapedImage = applyRemap(image.mat, camera.remapMap); RemapedImage remapedImage = applyRemap(image.mat, camera.remapMap);
if(profile.kFactor != 0 && remapedImage.image.type() == CV_8UC1) if(profile.kFactor != 0 && remapedImage.image.type() == CV_8UC1)
applyKfactor(remapedImage.image, remapedImage.angleX, profile.kFactor); applyKfactor(remapedImage.image, remapedImage.angle, profile.kFactor);
else if(profile.kFactor != 0) else if(profile.kFactor != 0)
qWarning()<<"Can not apply k factor due to image format"; qWarning()<<"Can not apply k factor due to image format";
remapedImages.push_back(remapedImage); remapedImages.push_back(remapedImage);

View File

@ -23,6 +23,7 @@ void CameraSetup::store(const QString &filename) const
matf<<("_"+QString::number(id)+"_bgmask").toStdString()<<bgmask; matf<<("_"+QString::number(id)+"_bgmask").toStdString()<<bgmask;
} }
matf<<("_"+QString::number(id)+"_bayermode").toStdString()<<bayerMode; matf<<("_"+QString::number(id)+"_bayermode").toStdString()<<bayerMode;
matf<<("_"+QString::number(id)+"_gain").toStdString()<<gain;
matf.release(); matf.release();
} }
@ -38,6 +39,15 @@ void CameraSetup::load(const QString &filename, size_t cameraId)
matf[("_"+QString::number(id)+"_ymat").toStdString()]>>remapMap.yMat; matf[("_"+QString::number(id)+"_ymat").toStdString()]>>remapMap.yMat;
matf[("_"+QString::number(id)+"_origin").toStdString()]>>remapMap.topLeftCoordinate; matf[("_"+QString::number(id)+"_origin").toStdString()]>>remapMap.topLeftCoordinate;
matf[("_"+QString::number(id)+"_bayermode").toStdString()]>>bayerMode; matf[("_"+QString::number(id)+"_bayermode").toStdString()]>>bayerMode;
try
{
matf[("_"+QString::number(id)+"_gain").toStdString()]>>gain;
}
catch(cv::Exception& e)
{
qWarning()<<"Profile dose not have gain";
gain = 1.0;
}
} }
else else
{ {

View File

@ -18,6 +18,7 @@ public:
cv::Mat darkmap; cv::Mat darkmap;
cv::Mat bgmask; cv::Mat bgmask;
cam::Camera::BayerMode bayerMode = cam::Camera::BAYER_BLUE; cam::Camera::BayerMode bayerMode = cam::Camera::BAYER_BLUE;
double gain = 1.0;
void store(const QString& filename) const; void store(const QString& filename) const;
void load(const QString& name, size_t cameraId); void load(const QString& name, size_t cameraId);
}; };

View File

@ -51,6 +51,9 @@ ConfigureCameraDialog::ConfigureCameraDialog(const CameraSetup& setup, std::shar
break; break;
} }
ui->doubleSpinBoxGain->setValue(setup_.gain);
camera_->cam()->setGain(setup_.gain);
camera_->cam()->setBayerMode(setup_.bayerMode); camera_->cam()->setBayerMode(setup_.bayerMode);
uint64_t min, max; uint64_t min, max;
@ -70,6 +73,7 @@ ConfigureCameraDialog::ConfigureCameraDialog(const CameraSetup& setup, std::shar
connect(ui->pushButtonBgShow, &QPushButton::clicked, [this](){if(setup_.bgmask.data) ui->widget_4->setImage(Camera::Image(setup_.bgmask, 0));}); connect(ui->pushButtonBgShow, &QPushButton::clicked, [this](){if(setup_.bgmask.data) ui->widget_4->setImage(Camera::Image(setup_.bgmask, 0));});
connect(ui->pushButtonDarkImageShow, &QPushButton::clicked, [this](){if(setup_.darkmap.data) ui->widget_4->setImage(Camera::Image(setup_.darkmap, 0));}); connect(ui->pushButtonDarkImageShow, &QPushButton::clicked, [this](){if(setup_.darkmap.data) ui->widget_4->setImage(Camera::Image(setup_.darkmap, 0));});
connect(ui->comboBox_bayer, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ConfigureCameraDialog::bayerIndexChanged); connect(ui->comboBox_bayer, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ConfigureCameraDialog::bayerIndexChanged);
connect(ui->doubleSpinBoxGain, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ConfigureCameraDialog::setExposure);
checkConfig(); checkConfig();
} }
@ -87,6 +91,15 @@ void ConfigureCameraDialog::setExposure(double value)
qDebug()<<"set exposure to "<<value*1000000.0; qDebug()<<"set exposure to "<<value*1000000.0;
} }
void ConfigureCameraDialog::setGain(double value)
{
if(!camera_->cam()->setGain(value))
QMessageBox::warning(this, "Warning", "Failed to set exposure");
else
qDebug()<<"set gain to "<<value;
setup_.gain = value;
}
void ConfigureCameraDialog::bayerIndexChanged(int index) void ConfigureCameraDialog::bayerIndexChanged(int index)
{ {
switch(index) switch(index)

View File

@ -36,6 +36,7 @@ private slots:
void takeImage(); void takeImage();
void setExposure(double value); void setExposure(double value);
void bayerIndexChanged(int index); void bayerIndexChanged(int index);
void setGain(double value);
public slots: public slots:
void accept() override; void accept() override;

View File

@ -31,13 +31,10 @@
<property name="horizontalSpacing"> <property name="horizontalSpacing">
<number>6</number> <number>6</number>
</property> </property>
<item row="1" column="4"> <item row="3" column="3">
<widget class="QPushButton" name="pushButtonRemapClear"> <widget class="QPushButton" name="pushButtonBgCreate">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>Clear</string> <string>Create</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -57,6 +54,33 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="3">
<widget class="QPushButton" name="pushButtonDarkImageCreate">
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="pushButtonRemapClear">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonDarkImageShow">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Show</string>
</property>
</widget>
</item>
<item row="2" column="4"> <item row="2" column="4">
<widget class="QPushButton" name="pushButtonDarkImageClear"> <widget class="QPushButton" name="pushButtonDarkImageClear">
<property name="enabled"> <property name="enabled">
@ -67,6 +91,27 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Dark image</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Remap Map (required)</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="pushButtonRemapCreate">
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="Led" name="ledDark" native="true"> <widget class="Led" name="ledDark" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
@ -83,58 +128,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Background image</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QPushButton" name="pushButtonBgCreate">
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="pushButtonRemapCreate">
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Dark image</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="pushButtonBgShow">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Show</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Remap Map (required)</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="pushButtonDarkImageCreate">
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="Led" name="ledRemap" native="true"> <widget class="Led" name="ledRemap" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
@ -151,16 +144,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="2">
<widget class="QPushButton" name="pushButtonDarkImageShow">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Show</string>
</property>
</widget>
</item>
<item row="3" column="4"> <item row="3" column="4">
<widget class="QPushButton" name="pushButtonBgClear"> <widget class="QPushButton" name="pushButtonBgClear">
<property name="enabled"> <property name="enabled">
@ -171,6 +154,33 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="2">
<widget class="QPushButton" name="pushButtonBgShow">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Show</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Background image</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Gain</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QDoubleSpinBox" name="doubleSpinBoxGain"/>
</item>
</layout> </layout>
</item> </item>
<item> <item>

View File

@ -35,6 +35,8 @@ CvImageViewer::CvImageViewer(QWidget *parent, size_t lastId) :
plot.setMinimumWidth(800); plot.setMinimumWidth(800);
plot.setMinimumHeight(600); plot.setMinimumHeight(600);
plot.setWindowIcon(windowIcon());
plot.setWindowTitle(windowTitle());
setMouseTracking(true); setMouseTracking(true);
} }
@ -133,6 +135,8 @@ void CvImageViewer::convertImage(cv::Mat image)
{ {
qimage_ = QImage(image_.data, image_.cols, image_.rows, image_.step, QImage::Format_Grayscale8); qimage_ = QImage(image_.data, image_.cols, image_.rows, image_.step, QImage::Format_Grayscale8);
statisticsAction_.setDisabled(false); statisticsAction_.setDisabled(false);
xPlotAction_.setDisabled(false);
yPlotAction_.setDisabled(false);
} }
else if(image_.type() == CV_32FC1 || image_.type() == CV_64FC1) else if(image_.type() == CV_32FC1 || image_.type() == CV_64FC1)
{ {
@ -221,22 +225,27 @@ void CvImageViewer::zoomToSelection()
void CvImageViewer::plotOnX() void CvImageViewer::plotOnX()
{ {
if(!xLine_.isNull() && origImage_.data && (origImage_.type() == CV_32FC1 || origImage_.type() == CV_64FC1)) if(!xLine_.isNull() && origImage_.data && (origImage_.type() == CV_32FC1 || origImage_.type() == CV_64FC1 || origImage_.type() == CV_8UC1))
{ {
cv::Mat plotImage;
if(origImage_.type() == CV_8UC1)
origImage_.convertTo(plotImage, CV_32FC1);
else
plotImage = origImage_;
plot.clear(); plot.clear();
QVector<double> keys; QVector<double> keys;
QVector<double> values; QVector<double> values;
int x, y; int x, y;
transfromToSourceCoordinates(xLine_.p1().x(), xLine_.p1().y(), x, y); transfromToSourceCoordinates(xLine_.p1().x(), xLine_.p1().y(), x, y);
double max = 0; double max = 0;
for(int i = 0; i < origImage_.cols; ++i) for(int i = 0; i < plotImage.cols; ++i)
{ {
keys.push_back(i); keys.push_back(i);
double value; double value;
if(origImage_.type() == CV_32FC1) if(plotImage.type() == CV_32FC1)
value = origImage_.at<float>(y, i); value = plotImage.at<float>(y, i);
else else
value = origImage_.at<double>(y, i); value = plotImage.at<double>(y, i);
if(max < value) if(max < value)
max = value; max = value;
values.push_back(value); values.push_back(value);
@ -252,22 +261,27 @@ void CvImageViewer::plotOnX()
void CvImageViewer::plotOnY() void CvImageViewer::plotOnY()
{ {
if(!xLine_.isNull() && origImage_.data && (origImage_.type() == CV_32FC1 || origImage_.type() == CV_64FC1)) if(!xLine_.isNull() && origImage_.data && (origImage_.type() == CV_32FC1 || origImage_.type() == CV_64FC1 || origImage_.type() == CV_8UC1))
{ {
cv::Mat plotImage;
if(origImage_.type() == CV_8UC1)
origImage_.convertTo(plotImage, CV_32FC1);
else
plotImage = origImage_;
plot.clear(); plot.clear();
QVector<double> keys; QVector<double> keys;
QVector<double> values; QVector<double> values;
int x, y; int x, y;
transfromToSourceCoordinates(yLine_.p1().x(), yLine_.p1().y(), x, y); transfromToSourceCoordinates(yLine_.p1().x(), yLine_.p1().y(), x, y);
double max = 0; double max = 0;
for(int i = 0; i < origImage_.rows; ++i) for(int i = 0; i < plotImage.rows; ++i)
{ {
keys.push_back(i); keys.push_back(i);
double value; double value;
if(origImage_.type() == CV_32FC1) if(plotImage.type() == CV_32FC1)
value = origImage_.at<float>(i, x); value = plotImage.at<float>(i, x);
else else
value = origImage_.at<double>(i, x); value = plotImage.at<double>(i, x);
if(max < value) if(max < value)
max = value; max = value;
values.push_back(value); values.push_back(value);

View File

@ -74,3 +74,4 @@ public:
}; };
#endif // CVIMAGEVIEWER_H #endif // CVIMAGEVIEWER_H

View File

@ -20,6 +20,7 @@ EditProfileDialog::EditProfileDialog(Cameras* cameras, const Profile profile, QW
ui->lineEditName->setText(name); ui->lineEditName->setText(name);
ui->doubleSpinBoxBrightness->setValue(profile_.lighting.brightness*100.0); ui->doubleSpinBoxBrightness->setValue(profile_.lighting.brightness*100.0);
ui->doubleSpinBoxExposure->setValue(profile_.exposureTime); ui->doubleSpinBoxExposure->setValue(profile_.exposureTime);
ui->doubleSpinBox_kFactor->setValue(profile_.kFactor);
qDebug()<<"Mask: "<<profile_.lighting.mask<<" & "<<(profile_.lighting.mask & CHANNEL_A); qDebug()<<"Mask: "<<profile_.lighting.mask<<" & "<<(profile_.lighting.mask & CHANNEL_A);

View File

@ -12,7 +12,8 @@ Plot::Plot(QWidget* parent):
actionAdd_Regression("Add regression", nullptr), actionAdd_Regression("Add regression", nullptr),
actionDelete_Regression("Delete regression", nullptr), actionDelete_Regression("Delete regression", nullptr),
actionExport_Selection("Export selection", nullptr), actionExport_Selection("Export selection", nullptr),
actionSetValueString("Set Y Axis Label", nullptr) actionSetValueString("Set Y Axis Label", nullptr),
savePdfAction("Save to pdf", nullptr)
{ {
xAxis->setLabel("Coordinate"); xAxis->setLabel("Coordinate");
yAxis->setLabel("Counts"); yAxis->setLabel("Counts");
@ -50,12 +51,14 @@ Plot::Plot(QWidget* parent):
connect(&actionDelete_Regression, &QAction::triggered, this, &Plot::deleteRegression); connect(&actionDelete_Regression, &QAction::triggered, this, &Plot::deleteRegression);
connect(&actionExport_Selection, &QAction::triggered, this, &Plot::saveCsvDiag); connect(&actionExport_Selection, &QAction::triggered, this, &Plot::saveCsvDiag);
connect(&actionSetValueString, &QAction::triggered, this, &Plot::askForValueString); connect(&actionSetValueString, &QAction::triggered, this, &Plot::askForValueString);
connect(&savePdfAction, &QAction::triggered, this, &Plot::savePdf);
graphContextMenu.addAction(&actionStatistics); graphContextMenu.addAction(&actionStatistics);
graphContextMenu.addAction(&actionAdd_Regression); graphContextMenu.addAction(&actionAdd_Regression);
graphContextMenu.addAction(&actionDelete_Regression); graphContextMenu.addAction(&actionDelete_Regression);
graphContextMenu.addAction(&actionExport_Selection); graphContextMenu.addAction(&actionExport_Selection);
graphContextMenu.addAction(&actionSetValueString); graphContextMenu.addAction(&actionSetValueString);
graphContextMenu.addAction(&savePdfAction);
} }
Plot::~Plot() Plot::~Plot()
@ -63,6 +66,14 @@ Plot::~Plot()
} }
void Plot::savePdf()
{
QString fileName = QFileDialog::getSaveFileName(this, "Save graph as PDF", "./", "*.pdf" );
if(!fileName.isEmpty())
QCustomPlot::savePdf(fileName);
}
bool Plot::event(QEvent *event) bool Plot::event(QEvent *event)
{ {
if(event->type()==QEvent::Gesture) graphContextMenu.show(); if(event->type()==QEvent::Gesture) graphContextMenu.show();
@ -78,9 +89,11 @@ void Plot::addMainGraph()
{ {
addGraph(); addGraph();
graph(graphCount()-1)->setSelectable(QCP::stDataRange); graph(graphCount()-1)->setSelectable(QCP::stDataRange);
graph(graphCount()-1)->setPen(QPen(QBrush(QColor(0,0,255,255)),2,Qt::SolidLine));
QPen selectionPen = graph(graphCount()-1)->pen(); QPen selectionPen = graph(graphCount()-1)->pen();
selectionPen.setColor(QColor(255,0,0)); selectionPen.setColor(QColor(255,0,0));
graph(graphCount()-1)->selectionDecorator()->setPen(selectionPen); graph(graphCount()-1)->selectionDecorator()->setPen(selectionPen);
} }
void Plot::clear() void Plot::clear()
@ -197,7 +210,7 @@ void Plot::deleteRegression()
void Plot::showStatistics() void Plot::showStatistics()
{ {
if(graphCount() > 0 && !graph(0)->selection().dataRanges().at(0).isEmpty()) if(graphCount() > 0 && !graph(0)->selection().dataRanges().isEmpty() && !graph(0)->selection().dataRanges().at(0).isEmpty())
{ {
QCPDataRange dataRange = graph(0)->selection().dataRanges().at(0); QCPDataRange dataRange = graph(0)->selection().dataRanges().at(0);
QCPGraphDataContainer::const_iterator begin = graph(0)->data()->at(dataRange.begin()); QCPGraphDataContainer::const_iterator begin = graph(0)->data()->at(dataRange.begin());
@ -210,10 +223,10 @@ void Plot::showStatistics()
statDiag.show(); statDiag.show();
statDiag.exec(); statDiag.exec();
} }
else if(graphCount() > 0 && selectedGraphs().size() > 1 && selectedGraphs().at(1) != graph(0)) else if(graphCount() > 0 && selectedGraphs().size() > 0 && selectedGraphs().at(0) != graph(0))
{ {
unsigned i = 0; unsigned i = 0;
while(selectedGraphs().at(1) != graph(i)) i++; while(selectedGraphs().at(0) != graph(i)) i++;
RegressionDiag regDiag(regressions.at(i-1), this); RegressionDiag regDiag(regressions.at(i-1), this);
regDiag.show(); regDiag.show();
regDiag.exec(); regDiag.exec();

View File

@ -13,51 +13,55 @@
class Plot : public QCustomPlot class Plot : public QCustomPlot
{ {
private: private:
std::vector<RegessionCalculator> regressions; std::vector<RegessionCalculator> regressions;
QMenu graphContextMenu; QMenu graphContextMenu;
int graphPointLimit = 10000; int graphPointLimit = 10000;
QAction actionStatistics; QAction actionStatistics;
QAction actionAdd_Regression; QAction actionAdd_Regression;
QAction actionDelete_Regression; QAction actionDelete_Regression;
QAction actionExport_Selection; QAction actionExport_Selection;
QAction actionSetValueString; QAction actionSetValueString;
QAction savePdfAction;
private slots:
void savePdf();
public: public:
Plot(QWidget* parent = nullptr); Plot(QWidget* parent = nullptr);
~Plot(); ~Plot();
void setLabel(QString label); void setLabel(QString label);
void clear(); void clear();
void setLimit(int graphPointLimit); void setLimit(int graphPointLimit);
int getLimit(); int getLimit();
void setMaxValue(double maxVal); void setMaxValue(double maxVal);
signals: signals:
void sigSaveCsv(); void sigSaveCsv();
public slots: public slots:
void addPoints(QVector<double> keys, QVector<double> values); void addPoints(QVector<double> keys, QVector<double> values);
void saveCsv(QString fileName); void saveCsv(QString fileName);
void saveCsvDiag(); void saveCsvDiag();
void showStatistics(); void showStatistics();
void deleteRegression(); void deleteRegression();
void addRegression(); void addRegression();
void askForValueString(); void askForValueString();
void addData(QVector<double> keys, QVector<double> values, bool inOrder = false, bool ignoreLimit = false); void addData(QVector<double> keys, QVector<double> values, bool inOrder = false, bool ignoreLimit = false);
void addData(double key, double value, bool ignoreLimit = false); void addData(double key, double value, bool ignoreLimit = false);
protected: protected:
virtual void mousePressEvent(QMouseEvent *event); virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event); virtual void mouseReleaseEvent(QMouseEvent *event);
virtual bool event(QEvent *event); virtual bool event(QEvent *event);
private: private:
void addMainGraph(); void addMainGraph();
}; };
#endif // PLOT_H #endif // PLOT_H