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)
{
for(auto& camera : cameras_)
{
for(auto& setup : setups)
{
if(camera->id() == setup.id)
{
camera->cam()->setBayerMode(setup.bayerMode);
camera->cam()->setGain(setup.gain);
}
}
}
}
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;
RemapedImage remapedImage = applyRemap(image.mat, camera.remapMap);
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)
qWarning()<<"Can not apply k factor due to image format";
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)+"_bayermode").toStdString()<<bayerMode;
matf<<("_"+QString::number(id)+"_gain").toStdString()<<gain;
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)+"_origin").toStdString()]>>remapMap.topLeftCoordinate;
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
{

View File

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

View File

@ -51,6 +51,9 @@ ConfigureCameraDialog::ConfigureCameraDialog(const CameraSetup& setup, std::shar
break;
}
ui->doubleSpinBoxGain->setValue(setup_.gain);
camera_->cam()->setGain(setup_.gain);
camera_->cam()->setBayerMode(setup_.bayerMode);
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->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->doubleSpinBoxGain, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ConfigureCameraDialog::setExposure);
checkConfig();
}
@ -87,6 +91,15 @@ void ConfigureCameraDialog::setExposure(double value)
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)
{
switch(index)

View File

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

View File

@ -31,13 +31,10 @@
<property name="horizontalSpacing">
<number>6</number>
</property>
<item row="1" column="4">
<widget class="QPushButton" name="pushButtonRemapClear">
<property name="enabled">
<bool>false</bool>
</property>
<item row="3" column="3">
<widget class="QPushButton" name="pushButtonBgCreate">
<property name="text">
<string>Clear</string>
<string>Create</string>
</property>
</widget>
</item>
@ -57,6 +54,33 @@
</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="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">
<widget class="QPushButton" name="pushButtonDarkImageClear">
<property name="enabled">
@ -67,6 +91,27 @@
</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="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">
<widget class="Led" name="ledDark" native="true">
<property name="sizePolicy">
@ -83,58 +128,6 @@
</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="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">
<widget class="Led" name="ledRemap" native="true">
<property name="sizePolicy">
@ -151,16 +144,6 @@
</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="3" column="4">
<widget class="QPushButton" name="pushButtonBgClear">
<property name="enabled">
@ -171,6 +154,33 @@
</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="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>
</item>
<item>

View File

@ -35,6 +35,8 @@ CvImageViewer::CvImageViewer(QWidget *parent, size_t lastId) :
plot.setMinimumWidth(800);
plot.setMinimumHeight(600);
plot.setWindowIcon(windowIcon());
plot.setWindowTitle(windowTitle());
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);
statisticsAction_.setDisabled(false);
xPlotAction_.setDisabled(false);
yPlotAction_.setDisabled(false);
}
else if(image_.type() == CV_32FC1 || image_.type() == CV_64FC1)
{
@ -221,22 +225,27 @@ void CvImageViewer::zoomToSelection()
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();
QVector<double> keys;
QVector<double> values;
int x, y;
transfromToSourceCoordinates(xLine_.p1().x(), xLine_.p1().y(), x, y);
double max = 0;
for(int i = 0; i < origImage_.cols; ++i)
for(int i = 0; i < plotImage.cols; ++i)
{
keys.push_back(i);
double value;
if(origImage_.type() == CV_32FC1)
value = origImage_.at<float>(y, i);
if(plotImage.type() == CV_32FC1)
value = plotImage.at<float>(y, i);
else
value = origImage_.at<double>(y, i);
value = plotImage.at<double>(y, i);
if(max < value)
max = value;
values.push_back(value);
@ -252,22 +261,27 @@ void CvImageViewer::plotOnX()
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();
QVector<double> keys;
QVector<double> values;
int x, y;
transfromToSourceCoordinates(yLine_.p1().x(), yLine_.p1().y(), x, y);
double max = 0;
for(int i = 0; i < origImage_.rows; ++i)
for(int i = 0; i < plotImage.rows; ++i)
{
keys.push_back(i);
double value;
if(origImage_.type() == CV_32FC1)
value = origImage_.at<float>(i, x);
if(plotImage.type() == CV_32FC1)
value = plotImage.at<float>(i, x);
else
value = origImage_.at<double>(i, x);
value = plotImage.at<double>(i, x);
if(max < value)
max = value;
values.push_back(value);

View File

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

View File

@ -20,6 +20,7 @@ EditProfileDialog::EditProfileDialog(Cameras* cameras, const Profile profile, QW
ui->lineEditName->setText(name);
ui->doubleSpinBoxBrightness->setValue(profile_.lighting.brightness*100.0);
ui->doubleSpinBoxExposure->setValue(profile_.exposureTime);
ui->doubleSpinBox_kFactor->setValue(profile_.kFactor);
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),
actionDelete_Regression("Delete regression", 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");
yAxis->setLabel("Counts");
@ -50,12 +51,14 @@ Plot::Plot(QWidget* parent):
connect(&actionDelete_Regression, &QAction::triggered, this, &Plot::deleteRegression);
connect(&actionExport_Selection, &QAction::triggered, this, &Plot::saveCsvDiag);
connect(&actionSetValueString, &QAction::triggered, this, &Plot::askForValueString);
connect(&savePdfAction, &QAction::triggered, this, &Plot::savePdf);
graphContextMenu.addAction(&actionStatistics);
graphContextMenu.addAction(&actionAdd_Regression);
graphContextMenu.addAction(&actionDelete_Regression);
graphContextMenu.addAction(&actionExport_Selection);
graphContextMenu.addAction(&actionSetValueString);
graphContextMenu.addAction(&savePdfAction);
}
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)
{
if(event->type()==QEvent::Gesture) graphContextMenu.show();
@ -78,9 +89,11 @@ void Plot::addMainGraph()
{
addGraph();
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();
selectionPen.setColor(QColor(255,0,0));
graph(graphCount()-1)->selectionDecorator()->setPen(selectionPen);
}
void Plot::clear()
@ -197,7 +210,7 @@ void Plot::deleteRegression()
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);
QCPGraphDataContainer::const_iterator begin = graph(0)->data()->at(dataRange.begin());
@ -210,10 +223,10 @@ void Plot::showStatistics()
statDiag.show();
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;
while(selectedGraphs().at(1) != graph(i)) i++;
while(selectedGraphs().at(0) != graph(i)) i++;
RegressionDiag regDiag(regressions.at(i-1), this);
regDiag.show();
regDiag.exec();

View File

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