fix comand line parser bug

add statistics dialog
add ability to zoom in on image viewer
This commit is contained in:
2021-07-09 12:18:43 +02:00
parent b10a260ddb
commit 07e6b6611d
10 changed files with 196 additions and 57 deletions

View File

@ -40,7 +40,6 @@ set(PROJECT_SOURCES
src/ui/mainwindow.ui src/ui/mainwindow.ui
src/ui/cvimageviewer.cpp src/ui/cvimageviewer.cpp
src/ui/cvimageviewer.h src/ui/cvimageviewer.h
src/ui/cvimageviewer.ui
src/ui/led.cpp src/ui/led.cpp
src/ui/led.h src/ui/led.h
src/ui/cameralistwidget.h src/ui/cameralistwidget.h
@ -48,6 +47,12 @@ set(PROJECT_SOURCES
src/ui/configurecameradialog.cpp src/ui/configurecameradialog.cpp
src/ui/configurecameradialog.h src/ui/configurecameradialog.h
src/ui/configurecameradialog.ui src/ui/configurecameradialog.ui
src/ui/aboutdiag.h
src/ui/aboutdiag.cpp
src/ui/aboutdiag.ui
src/ui/statisticsdialog.h
src/ui/statisticsdialog.cpp
src/ui/statisticsdialog.ui
) )

View File

@ -82,7 +82,7 @@ int main(int argc, char *argv[])
parser.addOption(simpleStichOption); parser.addOption(simpleStichOption);
QCommandLineOption quirkDurationOption(QStringList() << "d" << "quirk-duration", QCoreApplication::translate("main", "PhotonFocus quirk duration time"), QCoreApplication::translate("main", "time")); QCommandLineOption quirkDurationOption(QStringList() << "d" << "quirk-duration", QCoreApplication::translate("main", "PhotonFocus quirk duration time"), QCoreApplication::translate("main", "time"));
parser.addOption(quirkDurationOption); parser.addOption(quirkDurationOption);
QCommandLineOption cameraBootDurationOption(QStringList() << "d" << "quirk-duration", QCoreApplication::translate("main", "Camera boot time"), QCoreApplication::translate("main", "time")); QCommandLineOption cameraBootDurationOption(QStringList() << "t" << "boot-duration", QCoreApplication::translate("main", "Camera boot time"), QCoreApplication::translate("main", "time"));
parser.addOption(cameraBootDurationOption); parser.addOption(cameraBootDurationOption);
parser.process(a); parser.process(a);

View File

@ -49,7 +49,7 @@ public:
std::vector<CameraSetup> cameras; std::vector<CameraSetup> cameras;
bool nodistort = false; bool nodistort = false;
Profile(const QString& name = "Unamed"); Profile(const QString& name = "");
void store(QSettings& settings) const; void store(QSettings& settings) const;
void store(const QString& name); void store(const QString& name);
void store(); void store();

View File

@ -4,16 +4,28 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QFileDialog> #include <QFileDialog>
#include <opencv2/imgcodecs.hpp> #include <opencv2/imgcodecs.hpp>
#include <statisticsdialog.h>
CvImageViewer::CvImageViewer(QWidget *parent, size_t lastId) : CvImageViewer::CvImageViewer(QWidget *parent, size_t lastId) :
QWidget(parent), QWidget(parent),
lastId_(lastId), lastId_(lastId),
saveAction_("Save Image", nullptr) saveAction_("Save Image", nullptr),
zoomAction_("Zoom to selection", nullptr),
resetAction_("Reset Zoom", nullptr),
statisticsAction_("Get selection properties", nullptr),
roi_(0,0,0,0)
{ {
connect(&saveAction_, &QAction::triggered, this, &CvImageViewer::saveImage);
qimage_.load(":/images/noimage.png"); qimage_.load(":/images/noimage.png");
connect(&saveAction_, &QAction::triggered, this, &CvImageViewer::saveImage);
connect(&zoomAction_, &QAction::triggered, this, &CvImageViewer::zoomToSelection);
connect(&resetAction_, &QAction::triggered, this, &CvImageViewer::resetZoom);
connect(&statisticsAction_, &QAction::triggered, this, &CvImageViewer::showSatDiag);
imageContextMenu_.addAction(&saveAction_); imageContextMenu_.addAction(&saveAction_);
imageContextMenu_.addAction(&zoomAction_);
imageContextMenu_.addAction(&resetAction_);
imageContextMenu_.addAction(&statisticsAction_);
} }
CvImageViewer::~CvImageViewer() CvImageViewer::~CvImageViewer()
@ -50,62 +62,177 @@ void CvImageViewer::saveImage()
} }
} }
void CvImageViewer::setImage(Camera::Image img) void CvImageViewer::showSatDiag()
{ {
image_ = img.mat; if(origImage_.channels() > 1 || selectionRect_.width() < 2 || selectionRect_.height() < 2)
origImage_=img.mat; return;
qDebug()<<"viwer got"<<image_.rows<<'x'<<image_.cols<<" type "<<image_.type()<<"image from camera"<<img.cameraId;
int xA;
int yA;
int xB;
int yB;
transfromToSourceCoordinates(selectionRect_.x(), selectionRect_.y(), xA, yA);
transfromToSourceCoordinates(selectionRect_.x()+selectionRect_.width(), selectionRect_.y()+selectionRect_.height(), xB, yB);
selectionRect_ = QRect(0, 0, 0, 0);
cv::Rect roi(xA, yA, xB-xA, yB-yA);
cv::Mat roiImage = origImage_(roi);
if(roiImage.type() != CV_64FC1)
roiImage.convertTo(roiImage, CV_64FC1);
std::vector<double> data;
data.reserve(roiImage.total());
for (cv::MatIterator_<double> it = roiImage.begin<double>(); it != roiImage.end<double>(); ++it)
data.push_back(*it);
StatisticsDialog diag(data, this);
diag.show();
diag.exec();
}
void CvImageViewer::convertImage(cv::Mat image)
{
image_ = image;
if(image_.type() == CV_8UC3 || image_.type() == CV_8SC3) if(image_.type() == CV_8UC3 || image_.type() == CV_8SC3)
{ {
qimage_ = QImage(image_.data, image_.cols, image_.rows, image_.step, QImage::Format_RGB888); qimage_ = QImage(image_.data, image_.cols, image_.rows, image_.step, QImage::Format_RGB888);
statisticsAction_.setDisabled(true);
} }
else if(image_.type() == CV_8UC1 || image_.type() == CV_8SC1) else if(image_.type() == CV_8UC1 || image_.type() == CV_8SC1)
{ {
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);
} }
else if(image_.type() == CV_32FC1 || image_.type() == CV_64FC1) else if(image_.type() == CV_32FC1 || image_.type() == CV_64FC1)
{ {
double min, max; double min, max;
cv::minMaxIdx(img.mat, &min, &max); cv::minMaxIdx(image_, &min, &max);
double a = 255.0/(max - min); double a = 255.0/(max - min);
double b = 0-(min*a); double b = 0-(min*a);
qDebug()<<min<<max<<a<<b; qDebug()<<min<<max<<a<<b;
img.mat.convertTo(image_, CV_8UC1, a, b); image_.convertTo(image_, CV_8UC1, a, b);
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);
}
else if(image_.type() == CV_32FC3 || image_.type() == CV_64FC3)
{
double min, max;
cv::minMaxIdx(image_, &min, &max);
double a = 255.0/(max - min);
double b = 0-(min*a);
qDebug()<<min<<max<<a<<b;
image_.convertTo(image_, CV_8UC3, a, b);
qimage_ = QImage(image_.data, image_.cols, image_.rows, image_.step, QImage::Format_Grayscale8);
statisticsAction_.setDisabled(true);
} }
else else
{ {
img.mat.convertTo(image_, CV_8UC1, 255, 0); image_.convertTo(image_, CV_8UC1, 255, 0);
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(true);
} }
}
void CvImageViewer::setImage(Camera::Image img)
{
origImage_=img.mat;
qDebug()<<"viwer got"<<image_.rows<<'x'<<image_.cols<<" type "<<image_.type()<<"image from camera"<<img.cameraId;
convertImage(img.mat);
update(); update();
roi_ = cv::Rect(0, 0, image_.size().width, image_.size().height);
}
void CvImageViewer::transfromToSourceCoordinates(int inX, int inY, int& outX, int& outY)
{
qDebug()<<roi_.x<<inX<<imgrect_.x()<<imgrect_.width()<<roi_.width;
outX = roi_.x+(inX-imgrect_.x())/static_cast<double>(imgrect_.width())*roi_.width;
outY = roi_.y+(inY-imgrect_.y())/static_cast<double>(imgrect_.height())*roi_.height;
}
void CvImageViewer::resetZoom()
{
selectionRect_ = QRect(0, 0, 0, 0);
convertImage(origImage_);
update();
roi_ = cv::Rect(0, 0, image_.size().width, image_.size().height);
}
void CvImageViewer::zoomToSelection()
{
if(selectionRect_.width() > 2 && selectionRect_.height() > 2)
{
convertImage(origImage_);
int xA;
int yA;
int xB;
int yB;
transfromToSourceCoordinates(selectionRect_.x(), selectionRect_.y(), xA, yA);
transfromToSourceCoordinates(selectionRect_.x()+selectionRect_.width(), selectionRect_.y()+selectionRect_.height(), xB, yB);
selectionRect_ = QRect(0, 0, 0, 0);
roi_ = cv::Rect(xA, yA, xB-xA, yB-yA);
cv::Mat cropped;
cropped = image_(roi_);
convertImage(cropped);
update();
}
} }
void CvImageViewer::mousePressEvent(QMouseEvent *event) void CvImageViewer::mousePressEvent(QMouseEvent *event)
{ {
if(event->button() == Qt::RightButton) if(origImage_.data)
{ {
saveAction_.setEnabled(origImage_.data); if(event->button() == Qt::RightButton)
imageContextMenu_.popup(event->globalPos());
}
else if(origImage_.data && event->x() > imgrect_.x() && event->y() > imgrect_.y() && event->x() < imgrect_.x()+imgrect_.width() && event->y() < imgrect_.y()+imgrect_.height())
{
int x = (event->x()-imgrect_.x())/static_cast<double>(imgrect_.width())*origImage_.cols;
int y = (event->y()-imgrect_.y())/static_cast<double>(imgrect_.height())*origImage_.rows;
qDebug()<<x<<y;
if(origImage_.type() == CV_32FC1)
{ {
if(x >= 0 && y >= 0 && x <= origImage_.cols && y < origImage_.rows) saveAction_.setEnabled(origImage_.data);
sigValue(x, y, origImage_.at<float>(y,x)); imageContextMenu_.popup(event->globalPos());
} }
else else if(origImage_.data && event->x() > imgrect_.x() && event->y() > imgrect_.y() && event->x() < imgrect_.x()+imgrect_.width() && event->y() < imgrect_.y()+imgrect_.height())
{ {
sigValue(x, y, 0); selectionStarted_ = true;
selectionRect_.setTopLeft(event->pos());
selectionRect_.setBottomRight(event->pos());
int x;
int y;
transfromToSourceCoordinates(event->x(), event->y(), x, y);
if(origImage_.type() == CV_32FC1)
{
if(x >= 0 && y >= 0 && x <= origImage_.cols && y < origImage_.rows)
sigValue(x, y, origImage_.at<float>(y,x));
}
else
{
sigValue(x, y, 0);
}
} }
} }
QWidget::mousePressEvent(event); QWidget::mousePressEvent(event);
} }
void CvImageViewer::mouseMoveEvent(QMouseEvent *event)
{
if(selectionStarted_)
{
if(event->x() > imgrect_.x() && event->y() > imgrect_.y() && event->x() < imgrect_.x()+imgrect_.width() && event->y() < imgrect_.y()+imgrect_.height())
{
selectionRect_.setBottomRight(event->pos());
repaint();
}
}
}
void CvImageViewer::mouseReleaseEvent(QMouseEvent *event)
{
selectionStarted_ = false;
QWidget::mouseReleaseEvent(event);
}
void CvImageViewer::resizeEvent(QResizeEvent *event)
{
selectionRect_ = QRect(0, 0, 0, 0);
QWidget::resizeEvent(event);
}
void CvImageViewer::paintEvent(QPaintEvent* event) void CvImageViewer::paintEvent(QPaintEvent* event)
{ {
Q_UNUSED(event) Q_UNUSED(event)
@ -117,4 +244,8 @@ void CvImageViewer::paintEvent(QPaintEvent* event)
else else
imgrect_.setRect((rect().width()-rect().height()/ratio)/2, 0, rect().height()/ratio, rect().height()); imgrect_.setRect((rect().width()-rect().height()/ratio)/2, 0, rect().height()/ratio, rect().height());
painter.drawImage(imgrect_, qimage_); painter.drawImage(imgrect_, qimage_);
painter.setPen(QPen(QBrush(QColor(0,0,0,180)),1,Qt::DashLine));
painter.setBrush(QBrush(QColor(255,255,255,120)));
painter.drawRect(selectionRect_);
} }

View File

@ -18,14 +18,29 @@ private:
size_t lastId_; size_t lastId_;
QMenu imageContextMenu_; QMenu imageContextMenu_;
QAction saveAction_; QAction saveAction_;
QAction zoomAction_;
QAction resetAction_;
QAction statisticsAction_;
QRect imgrect_; QRect imgrect_;
cv::Rect roi_;
QRect selectionRect_;
bool selectionStarted_ = false;
void transfromToSourceCoordinates(int inX, int inY, int& outX, int& outY);
void convertImage(cv::Mat image);
private slots: private slots:
void saveImage(); void saveImage();
void zoomToSelection();
void resetZoom();
void showSatDiag();
protected: protected:
virtual void paintEvent(QPaintEvent* event) override; virtual void paintEvent(QPaintEvent* event) override;
virtual void mousePressEvent(QMouseEvent *event) override; virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent *event) override;
virtual void resizeEvent(QResizeEvent *event) override;
signals: signals:
void sigValue(size_t x, size_t y, double value); void sigValue(size_t x, size_t y, double value);

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CvImageViewer</class>
<widget class="QWidget" name="CvImageViewer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -15,8 +15,9 @@ EditProfileDialog::EditProfileDialog(Cameras* cameras, const Profile profile, QW
ui(new Ui::EditProfileDialog) ui(new Ui::EditProfileDialog)
{ {
ui->setupUi(this); ui->setupUi(this);
QString name = profile_.getName();
ui->lineEditName->setText(profile_.getName()); if(!name.isEmpty())
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);

View File

@ -9,6 +9,7 @@
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
, about_(this)
, ui(new Ui::MainWindow) , ui(new Ui::MainWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -22,9 +23,9 @@ MainWindow::MainWindow(QWidget *parent)
connect(ui->mainViewer, &CvImageViewer::sigValue, this, &MainWindow::setImageValue); connect(ui->mainViewer, &CvImageViewer::sigValue, this, &MainWindow::setImageValue);
connect(ui->actionOpen, &QAction::triggered, [this](bool checked){(void)checked; openImage();}); connect(ui->actionOpen, &QAction::triggered, [this](bool checked){(void)checked; openImage();});
connect(ui->actionSave_2, &QAction::triggered, [this](bool checked){(void)checked; saveImage();}); connect(ui->actionSave_2, &QAction::triggered, [this](bool checked){(void)checked; saveImage();});
connect(ui->actionAbout, &QAction::triggered, [this](bool checked){(void)checked; about_.show();});
refreshProfiles(); refreshProfiles();
} }
void MainWindow::setImageValue(size_t x, size_t y, double value) void MainWindow::setImageValue(size_t x, size_t y, double value)
{ {
ui->lcdNumber_3->display((double)x); ui->lcdNumber_3->display((double)x);

View File

@ -5,6 +5,7 @@
#include <stdint.h> #include <stdint.h>
#include "../cameras.h" #include "../cameras.h"
#include "cvimageviewer.h" #include "cvimageviewer.h"
#include "aboutdiag.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui { class MainWindow; }
@ -15,6 +16,7 @@ class MainWindow : public QMainWindow
Q_OBJECT Q_OBJECT
private: private:
std::vector<CvImageViewer*> viewers_; std::vector<CvImageViewer*> viewers_;
AboutDiag about_;
private slots: private slots:
void setImageValue(size_t x, size_t y, double value); void setImageValue(size_t x, size_t y, double value);

View File

@ -246,8 +246,15 @@
<addaction name="actionCameras"/> <addaction name="actionCameras"/>
<addaction name="actionProfile"/> <addaction name="actionProfile"/>
</widget> </widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menuSetup"/> <addaction name="menuSetup"/>
<addaction name="menuHelp"/>
</widget> </widget>
<widget class="QStatusBar" name="statusbar"/> <widget class="QStatusBar" name="statusbar"/>
<action name="actionQuit"> <action name="actionQuit">
@ -289,6 +296,11 @@
<string>Ctrl+O</string> <string>Ctrl+O</string>
</property> </property>
</action> </action>
<action name="actionAbout">
<property name="text">
<string>About</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>