diff --git a/res/icon.png b/res/icon.png
new file mode 100644
index 0000000..feae36f
Binary files /dev/null and b/res/icon.png differ
diff --git a/res/resources.qrc b/res/resources.qrc
index 5739fb3..2f22372 100644
--- a/res/resources.qrc
+++ b/res/resources.qrc
@@ -2,5 +2,6 @@
noimage.png
splash.png
+ icon.png
diff --git a/src/camera.cpp b/src/camera.cpp
index 3640513..6e67e7d 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -6,7 +6,7 @@
Camera::Camera(cam::Camera::Description desc)
{
- cameraId_ = desc.getHash();
+ cameraId_ = desc.getId();
std::function cb = [this](cv::Mat image){newImage(Image(image, cameraId_));};
camera_ = new cam::Camera(cb);
camera_->openCamera(desc);
diff --git a/src/cameras.cpp b/src/cameras.cpp
index 1351ad3..74deaa9 100644
--- a/src/cameras.cpp
+++ b/src/cameras.cpp
@@ -3,6 +3,8 @@
#include
#include
#include
+#include
+#include
Cameras::Cameras(uvosled* led): led_(led)
{
@@ -46,7 +48,7 @@ std::shared_ptr Cameras::getCamera(size_t id)
std::vector desc = getCameras();
for(size_t i = 0; i < desc.size(); ++i)
{
- if(desc[i].getHash() == id)
+ if(desc[i].getId() == id)
return cameras_[i];
}
return std::shared_ptr(nullptr);
@@ -62,14 +64,35 @@ bool Cameras::addCamera(const cam::Camera::Description& desc)
return false;
}
- cameras_.back()->cam()->setTriggerMode(cam::Camera::TRIGGER_SOFTWARE);
cameras_.back()->cam()->setExposureTime(exposrueTime_*1000000);
- setFree(false);
- cameraAdded(cameras_.back());
- qDebug()<<"Using camera"<id();
+
+ if(desc.getVendor().find("Photonfocus") != std::string::npos)
+ {
+ qDebug()<<"Mitiagting broken PhotonFocus single shot mode";
+ std::shared_ptr camera = cameras_.back();
+ camera->cam()->setTriggerMode(cam::Camera::TRIGGER_FREE);
+ camera->cam()->setAcquisitionMode(cam::Camera::MODE_FREE);
+ camera->cam()->setFrameRate(10);
+ camera->cam()->startAcquisition();
+ QTimer::singleShot(2000, [camera, this](){finishAddCamera(camera);});
+ }
+ else
+ {
+ finishAddCamera(cameras_.back());
+ }
+
return true;
}
+void Cameras::finishAddCamera(std::shared_ptr camera)
+{
+ camera->cam()->setTriggerMode(cam::Camera::TRIGGER_SOFTWARE);
+ setFree(free_);
+ connect(camera.get(), &Camera::newImage, this, &Cameras::imageRecived);
+ qDebug()<<"Using camera"<id();
+ cameraAdded(camera);
+}
+
void Cameras::trigger()
{
for(auto& camera : cameras_)
@@ -108,6 +131,11 @@ bool Cameras::stop()
return ret;
}
+void Cameras::disable(bool disable)
+{
+ disable_ = disable;
+}
+
bool Cameras::setFree(bool free)
{
stop();
@@ -117,7 +145,10 @@ bool Cameras::setFree(bool free)
for(auto& camera : cameras_)
{
if(!camera->cam()->setAcquisitionMode(free ? cam::Camera::MODE_FREE : cam::Camera::MODE_SINGLE))
+ {
+ qDebug()<<"failed to set single on camera"<id();
ret = false;
+ }
}
return ret;
}
@@ -130,34 +161,40 @@ bool Cameras::setExposureTime(double exposureTime)
for(auto& camera : cameras_)
{
if(!camera->cam()->setExposureTime(exposrueTime_*1000000))
+ {
+ qDebug()<<"failed to set exposure on camera"<id();
ret = false;
+ }
}
return ret;
}
void Cameras::imageRecived(Camera::Image img)
{
- bool allreadyUpdated = false;
- for(auto& camera : cameras_)
+ if(!disable_)
{
+ bool allreadyUpdated = false;
for(auto& image : images_)
{
- if(image.cameraId == camera->id())
+ if(image.cameraId == img.cameraId)
{
allreadyUpdated = true;
- goto FOUND;
+ break;;
}
}
+
+ if(!allreadyUpdated)
+ images_.push_back(img);
+
+ qDebug()<<"Recived"<> cameras_;
@@ -30,11 +31,12 @@ private:
private slots:
void imageRecived(Camera::Image img);
+ void finishAddCamera(std::shared_ptr camera);
signals:
void cameraRemoved(std::shared_ptr camera);
void cameraAdded(std::shared_ptr camera);
- void newImages(std::vector images_);
+ void newImages(std::vector images);
public slots:
@@ -55,6 +57,7 @@ public:
Cameras(uvosled* led = nullptr);
void load(QSettings& settings);
void store(QSettings& settings);
+ void disable(bool disable);
};
#endif // CAMERAS_H
diff --git a/src/imagepipeline.cpp b/src/imagepipeline.cpp
index 469aca7..964aed8 100644
--- a/src/imagepipeline.cpp
+++ b/src/imagepipeline.cpp
@@ -1,37 +1,96 @@
#include "imagepipeline.h"
#include
+#include
+#include
#include
#include
+#include
ImagePipeline::ImagePipeline(Cameras* cameras, QObject *parent): QObject(parent), cameras_(cameras)
{
+ connect(cameras_, &Cameras::newImages, this, &ImagePipeline::apply);
}
cv::Mat ImagePipeline::process(const Profile profile, std::vector images)
{
+ qDebug()<<__FUNCTION__<<"got"< remapedImages;
remapedImages.reserve(images.size());
- for(Camera::Image& image : images)
+ try
{
- for(auto& camera : profile.cameras)
+ if(profile.nodistort && images.size() > 0)
{
- if(camera.id == image.cameraId)
+ for(auto& image : images)
{
- if(camera.darkmap.data)
- image.mat = image.mat - camera.darkmap;
- remapedImages.push_back(applyRemap(image.mat, camera.remapMap));
- break;
+ if(profile.cameras[0].id == image.cameraId)
+ {
+ RemapedImage img;
+ img.origin.x = 0;
+ img.origin.y = 0;
+ image.mat.copyTo(img.image);
+ if(profile.cameras[0].darkmap.data)
+ img.image = img.image - profile.cameras[0].darkmap;
+ remapedImages.push_back(img);
+ break;
+ }
+ }
+ }
+ else
+ {
+ for(Camera::Image& image : images)
+ {
+ qDebug()<<__FUNCTION__<<"image cam id"< 0)
+ {
+ cv::Mat output = simpleStich(remapedImages);
+ output.convertTo(output, CV_32FC1, 1.0/255.0, 0);
- if(profile.lightmap.data)
- normalize(output, profile.lightmap);
- return output;
+ if(profile.lightmap.data)
+ normalize(output, profile.lightmap);
+
+ if(profile.calcurve.data)
+ applyCurve(output, profile.calcurve);
+ return output;
+ }
+ else
+ {
+ qDebug()<<"Image pipe failure insufficant matched images";
+ return cv::Mat();
+ }
}
void ImagePipeline::apply(std::vector images)
@@ -41,6 +100,7 @@ void ImagePipeline::apply(std::vector images)
futureImageWatchers_.push_back(new QFutureWatcher());
connect(futureImageWatchers_.back(), &QFutureWatcher::finished, this, &ImagePipeline::imageFinished);
+ statusMsg("Processing");
QFuture futureImage = QtConcurrent::run(&ImagePipeline::process, profile_, images);
futureImageWatchers_.back()->setFuture(futureImage);
}
@@ -51,11 +111,20 @@ void ImagePipeline::setProfile(const Profile& profile)
profile_ = profile;
cameras_->setExposureTime(profile_.exposureTime);
cameras_->setLighting(profile_.lighting);
+ qDebug()<<"setting profile "<getCameras()))
{
invalid_ = true;
sigInvalidProfile("A camera required for this profile is not available");
}
+ statusMsg("set profile " + profile_.getName());
}
void ImagePipeline::imageFinished()
@@ -65,11 +134,18 @@ void ImagePipeline::imageFinished()
if(futureImageWatchers_[i]->isFinished())
{
cv::Mat result = futureImageWatchers_[i]->result();
- sigResult(Camera::Image(result, 0));
- delete futureImageWatchers_[i];
- futureImageWatchers_.erase(futureImageWatchers_.begin()+i);
- i--;
+ if(result.data)
+ {
+ sigResult(Camera::Image(result, 0));
+ delete futureImageWatchers_[i];
+ futureImageWatchers_.erase(futureImageWatchers_.begin()+i);
+ i--;
+ statusMsg("Finished");
+ }
+ else
+ {
+ sigInvalidProfile("Image pipe failure");
+ }
}
}
}
-
diff --git a/src/imagepipeline.h b/src/imagepipeline.h
index 5ca8d86..09c09d2 100644
--- a/src/imagepipeline.h
+++ b/src/imagepipeline.h
@@ -30,6 +30,7 @@ private slots:
signals:
void sigInvalidProfile(QString message);
void sigResult(Camera::Image image);
+ void statusMsg(QString msg);
public slots:
void setProfile(const Profile& profile);
diff --git a/src/main.cpp b/src/main.cpp
index 4bdf7ad..9bac951 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include "cameras.h"
#include "./ui/cameradialog.h"
@@ -17,6 +18,7 @@
#include "./ui/profiledialog.h"
#include "imagepipeline.h"
+
const char* organziation = "UVOS";
const char* application = "UVOS";
const char* version = "UVOS";
@@ -44,13 +46,18 @@ void showProfileDialog(Cameras* cameras)
{
qDebug()<<__FUNCTION__;
cameras->stop();
+ cameras->disable(true);
+ std::vector descs = cameras->getCameras();
ProfileDialog diag(cameras);
diag.show();
diag.exec();
+ cameras->disable(false);
}
int main(int argc, char *argv[])
{
+ Log::level = Log::WARN;
+
QApplication a(argc, argv);
QCoreApplication::setOrganizationName("UVOS");
QCoreApplication::setOrganizationDomain("uvos.xyz");
@@ -61,11 +68,12 @@ int main(int argc, char *argv[])
splash.show();
QDir().mkpath(Profile::profileLocation());
- QDir().mkpath(CameraSetup::camerasLocation());
qRegisterMetaType("cv::Mat");
qRegisterMetaType("size_t");
+ qRegisterMetaType("Camera::Image");
qRegisterMetaType("Image");
+ qRegisterMetaType>("std::vector");
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
@@ -100,11 +108,16 @@ int main(int argc, char *argv[])
QObject::connect(&w, &MainWindow::sigEditProfiles, [&cameras, &w](){showProfileDialog(&cameras); w.refreshProfiles();});
QObject::connect(&pipe, &ImagePipeline::sigResult, w.mainImageViewer(), &CvImageViewer::setImage, Qt::QueuedConnection);
+ QObject::connect(&pipe, &ImagePipeline::sigInvalidProfile, &w, &MainWindow::profileInconpatible);
QObject::connect(&w, &MainWindow::sigProfile, [&pipe](QString name)
{
Profile profile;
profile.load(name);
+ if(profile.cameras.size() != 0)
+ qDebug()<<"loading profile"<
#include
-void CameraSetup::store() const
+void CameraSetup::store(const QString &filename) const
{
- if(darkmap.data)
- cv::imwrite(darkmapLocation(id).toStdString(), darkmap);
+ cv::FileStorage matf(filename.toStdString(), cv::FileStorage::APPEND);
if(remapMap.xMat.data)
- saveRemapMap(remapMap, remapMapLocation(id).toStdString());
+ {
+ matf<<("_"+QString::number(id)+"_xmat").toStdString()<>bgmask;
matf.release();
}
-void CameraSetup::loadRemapMaps(const QString &filename)
-{
- remapMap = loadRemapMap(filename.toStdString());
-}
-
-void CameraSetup::load(size_t cameraId)
+void CameraSetup::load(const QString &filename, size_t cameraId)
{
id = cameraId;
- loadDarkMap(darkmapLocation(id));
- loadRemapMaps(remapMapLocation(id));
- loadBgMask(bgmaskLocation(id));
-}
-
-QString CameraSetup::camerasLocation()
-{
- return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/cameras/";
-}
-
-QString CameraSetup::darkmapLocation(size_t cameraId)
-{
- return camerasLocation() + QString::number(cameraId) + ".darkmap.png";
-}
-
-QString CameraSetup::bgmaskLocation(size_t cameraId)
-{
- return camerasLocation() + QString::number(cameraId) + "bgmask.mat";
-}
-
-QString CameraSetup::remapMapLocation(size_t cameraId)
-{
- return camerasLocation() + QString::number(cameraId) + "remap.mat";
+ cv::FileStorage matf(filename.toStdString(), cv::FileStorage::READ);
+ if (matf.isOpened())
+ {
+ matf[("_"+QString::number(id)+"_darkmap").toStdString()]>>darkmap;
+ matf[("_"+QString::number(id)+"_bgmask").toStdString()]>>bgmask;
+ matf[("_"+QString::number(id)+"_xmat").toStdString()]>>remapMap.xMat;
+ matf[("_"+QString::number(id)+"_ymat").toStdString()]>>remapMap.yMat;
+ matf[("_"+QString::number(id)+"_origin").toStdString()]>>remapMap.topLeftCoordinate;
+ }
+ else
+ {
+ qDebug()<<"could not open file"<(id));
settings.setValue(GROUP + QString("/exposureTime"), exposureTime);
settings.setValue(GROUP + QString("/name"), name_);
+ settings.setValue(GROUP + QString("/nodistort"), nodistort);
if(lightmap.data)
cv::imwrite((profileLocation() + QString::number(id) + ".lightmap.png").toStdString(), lightmap);
@@ -93,10 +72,18 @@ void Profile::store(QSettings& settings) const
{
const CameraSetup& camera = cameras[i];
settings.setArrayIndex(i);
- camera.store();
+ camera.store(profileLocation() + name_ + ".profile.mat");
settings.setValue("id", static_cast(camera.id));
}
settings.endArray();
+
+ cv::FileStorage matf((profileLocation() + name_ + ".calcurve.mat").toStdString(), cv::FileStorage::WRITE);
+ matf<<"cal"<>calcurve;
+ matf.release();
+
+ if(calcurve.data && (calcurve.type() != CV_32FC1 || calcurve.rows != 2))
+ calcurve.release();
+
+ cv::FileStorage matfl((profileLocation() + name_ + ".lightmap.mat").toStdString(), cv::FileStorage::READ);
+ matfl["cal"]>>lightmap;
+ matfl.release();
}
void Profile::load(const QString& name)
@@ -164,15 +163,43 @@ QList Profile::avaiableProfiles()
return ret;
}
-void Profile::setCamerasSetupsFromDescription(const std::vector& desc)
+void Profile::setCamerasSetupsFromDescription(const std::vector& descs)
{
- cameras.clear();
- cameras.reserve(desc.size());
- for(size_t i = 0; i < desc.size(); ++i)
+ for(size_t i = 0; i < cameras.size(); ++i)
{
- CameraSetup tmp;
- tmp.load(desc[i].getHash());
- cameras.push_back(tmp);
+ bool found = false;
+ for(auto& cameraDesc : descs)
+ {
+ if(cameras[i].id == cameraDesc.getId())
+ {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ cameras.erase(cameras.begin()+i);
+ --i;
+ }
+ }
+
+ for(size_t i = 0; i < descs.size(); ++i)
+ {
+ bool found = false;
+ for(auto& camera : cameras)
+ {
+ if(camera.id == descs[i].getId())
+ {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ CameraSetup tmp;
+ tmp.load(profileLocation() + name_ + ".profile.mat", descs[i].getId());
+ cameras.push_back(tmp);
+ }
}
}
@@ -184,7 +211,7 @@ bool Profile::camerasSufficant(const std::vector& desc
bool found = false;
for(auto& camera : desc)
{
- if(camera.getHash() == cameraProfile.id)
+ if(camera.getId() == cameraProfile.id)
{
found = true;
break;
diff --git a/src/profile.h b/src/profile.h
index 561787d..3eeae19 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -16,15 +16,8 @@ public:
RemapMap remapMap;
cv::Mat darkmap;
cv::Mat bgmask;
- void store() const;
- void load(size_t cameraId);
- void loadBgMask(const QString& filename);
- void loadDarkMap(const QString& filename);
- void loadRemapMaps(const QString& filename);
- static QString camerasLocation();
- static QString remapMapLocation(size_t cameraId);
- static QString bgmaskLocation(size_t cameraId);
- static QString darkmapLocation(size_t cameraId);
+ void store(const QString& filename) const;
+ void load(const QString& name, size_t cameraId);
};
class LightingSetup
@@ -50,7 +43,9 @@ public:
LightingSetup lighting;
double exposureTime = 1.0/60.0;
cv::Mat lightmap;
+ cv::Mat calcurve;
std::vector cameras;
+ bool nodistort = false;
Profile(const QString& name = "Unamed");
void store(QSettings& settings) const;
diff --git a/src/ui/cameradialog.ui b/src/ui/cameradialog.ui
index b01d46c..8c8e927 100644
--- a/src/ui/cameradialog.ui
+++ b/src/ui/cameradialog.ui
@@ -16,6 +16,10 @@
Select Cameras
+
+
+ :/images/icon.png:/images/icon.png
+
-
@@ -46,7 +50,9 @@
./src/ui/cameralistwidget.h
-
+
+
+
buttonBox
diff --git a/src/ui/cameralistwidget.cpp b/src/ui/cameralistwidget.cpp
index d7e1dc8..879cfd1 100644
--- a/src/ui/cameralistwidget.cpp
+++ b/src/ui/cameralistwidget.cpp
@@ -20,7 +20,7 @@ void CameraListWidget::setConfigured(std::vector configured)
setHorizontalHeaderItem(1, new QTableWidgetItem("Configured"));
for(size_t i = 0; i < desc_.size() && i < configured.size(); ++i)
{
- setItem(static_cast(i), 1, new QTableWidgetItem("No"));
+ setItem(static_cast(i), 1, new QTableWidgetItem(configured[i] ? "Yes" : "No"));
qDebug()<<"Set item "<& d
setRowCount(static_cast(desc_.size()));
for(size_t i = 0; i < desc_.size(); ++i)
{
- setItem(static_cast(i), 0, new QTableWidgetItem((desc_[i].vendor + " " + desc_[i].model).c_str()));
+ setItem(static_cast(i), 0, new QTableWidgetItem((desc_[i].getVendor() + " " + desc_[i].getModel()).c_str()));
}
}
diff --git a/src/ui/configurecameradialog.cpp b/src/ui/configurecameradialog.cpp
index b7622c0..b311528 100644
--- a/src/ui/configurecameradialog.cpp
+++ b/src/ui/configurecameradialog.cpp
@@ -7,20 +7,26 @@
#include
#include
#include
+#include
ConfigureCameraDialog::ConfigureCameraDialog(const CameraSetup& setup, std::shared_ptr camera, double exposureTime, QWidget *parent):
QDialog(parent),
setup_(setup),
camera_(camera),
+ profileExposure_(exposureTime),
ui(new Ui::ConfigureCameraDialog)
{
ui->setupUi(this);
+ qDebug()<<"profileExposure_"<doubleSpinBox->setValue(profileExposure_);
+ setExposure(profileExposure_);
- ui->doubleSpinBox->setValue(exposureTime);
+ uint64_t min, max;
+ camera_->cam()->getExposureTimeLimits(min, max);
+ ui->doubleSpinBox->setMaximum(max/1000000.0);
+ ui->doubleSpinBox->setMinimum(min/1000000.0);
- connect(ui->pushButtonBgLoad, &QPushButton::clicked, this, &ConfigureCameraDialog::loadBg);
- connect(ui->pushButtonRemapLoad, &QPushButton::clicked, this, &ConfigureCameraDialog::loadRemap);
- connect(ui->pushButtonDarkImageLoad, &QPushButton::clicked, this, &ConfigureCameraDialog::loadDark);
+ connect(ui->doubleSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), this, &ConfigureCameraDialog::setExposure);
connect(ui->pushButtonBgClear, &QPushButton::clicked, [this](){setup_.bgmask.release(); checkConfig();});
connect(ui->pushButtonRemapClear, &QPushButton::clicked, [this](){setup_.remapMap = RemapMap(); checkConfig();});
connect(ui->pushButtonDarkImageClear, &QPushButton::clicked, [this](){setup_.darkmap.release(); checkConfig();});
@@ -38,45 +44,12 @@ ConfigureCameraDialog::~ConfigureCameraDialog()
delete ui;
}
-
-
-void ConfigureCameraDialog::loadBg()
+void ConfigureCameraDialog::setExposure(double value)
{
- QString filename = QFileDialog::getOpenFileName(this, tr("Open Background Mask"), CameraSetup::camerasLocation(), "OpenCV Mat (*.mat)");
- if(!filename.isEmpty())
- {
- setup_.loadBgMask(filename);
- if(!setup_.bgmask.data)
- QMessageBox::warning(this, "Warning", "Could not load " + filename);
- checkConfig();
- }
-}
-
-void ConfigureCameraDialog::loadRemap()
-{
- QString filename = QFileDialog::getOpenFileName(this, tr("Open Background Mask"), CameraSetup::camerasLocation(), "OpenCV Mat (*.mat)");
- if(!filename.isEmpty())
- {
- setup_.loadRemapMaps(filename);
- if(!setup_.remapMap.xMat.data || !setup_.remapMap.yMat.data)
- {
- QMessageBox::warning(this, "Warning", "Could not load " + filename);
- setup_.remapMap = RemapMap();
- }
- checkConfig();
- }
-}
-
-void ConfigureCameraDialog::loadDark()
-{
- QString filename = QFileDialog::getOpenFileName(this, tr("Open Background Mask"), CameraSetup::camerasLocation(), "Image (*.png)");
- if(!filename.isEmpty())
- {
- setup_.loadDarkMap(filename);
- if(!setup_.darkmap.data)
- QMessageBox::warning(this, "Warning", "Could not load " + filename);
- checkConfig();
- }
+ if(!camera_->cam()->setExposureTime(value*1000000.0))
+ QMessageBox::warning(this, "Warning", "Failed to set exposure");
+ else
+ qDebug()<<"set exposure to "< points = detectCharucoPoints(img.mat, false);
if(points.size() < 8)
{
@@ -117,13 +95,13 @@ void ConfigureCameraDialog::gotImage(Camera::Image img)
break;
}
RemapMap map;
- if(createRemapMap(img.mat, map, points))
+ if(createRemapMap(masked, map, points))
setup_.remapMap = map;
else
QMessageBox::warning(this, "Failed", "Error creating map");
for(size_t i = 0; i < points.size(); ++i)
- cv::circle(img.mat, points[i].point, 5, cv::Scalar(0,255,0), 1);
- ui->widget_4->setImage(Camera::Image(setup_.bgmask, camera_->id()));
+ cv::circle(img.mat, points[i].point, img.mat.cols/50, cv::Scalar(255,255,255), img.mat.cols/200);
+ ui->widget_4->setImage(Camera::Image(img.mat, camera_->id()));
mode_ = MODE_IDLE;
break;
}
@@ -157,6 +135,8 @@ void ConfigureCameraDialog::captureDark()
{
QMessageBox::information(this, "Cover lense", "Please cover the lense of the camera.");
mode_ = MODE_DARK_GET;
+ ui->doubleSpinBox->setValue(profileExposure_);
+ setExposure(profileExposure_);
takeImage();
}
@@ -165,7 +145,7 @@ void ConfigureCameraDialog::accept()
if(checkConfig())
QDialog::accept();
else
- QMessageBox::warning(this, "Unfinished", "Can not accept unfinished camera setup");
+ QMessageBox::information(this, "Unfinished", "Can not accept unfinished camera setup");
}
bool ConfigureCameraDialog::checkConfig()
@@ -182,5 +162,5 @@ bool ConfigureCameraDialog::checkConfig()
ui->ledDark->setLit(darkMapOK);
ui->ledRemap->setLit(remapMapOk);
- return bgOk && remapMapOk && darkMapOK;
+ return remapMapOk;
}
diff --git a/src/ui/configurecameradialog.h b/src/ui/configurecameradialog.h
index ec5d60f..1566b7d 100644
--- a/src/ui/configurecameradialog.h
+++ b/src/ui/configurecameradialog.h
@@ -22,25 +22,27 @@ class ConfigureCameraDialog : public QDialog
std::shared_ptr camera_;
int mode_ = MODE_IDLE;
cv::Mat fgImage;
+ double profileExposure_;
private:
bool checkConfig();
void gotImage(Camera::Image img);
private slots:
- void loadBg();
- void loadRemap();
- void loadDark();
void captureBg();
void captureRemap();
void captureDark();
void takeImage();
+ void setExposure(double value);
+
+public slots:
+ void accept() override;
public:
explicit ConfigureCameraDialog(const CameraSetup& setup, const std::shared_ptr camera, double exposureTime = 1.0/60, QWidget *parent = nullptr);
~ConfigureCameraDialog();
CameraSetup getCameraSetup(){return setup_;}
- void accept() override;
+
private:
Ui::ConfigureCameraDialog *ui;
diff --git a/src/ui/configurecameradialog.ui b/src/ui/configurecameradialog.ui
index 4bf1a50..94fd5f5 100644
--- a/src/ui/configurecameradialog.ui
+++ b/src/ui/configurecameradialog.ui
@@ -6,8 +6,8 @@
0
0
- 466
- 438
+ 545
+ 614
@@ -31,6 +31,29 @@
6
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 40
+ 40
+
+
+
+
+ -
+
+
+ Create
+
+
+
-
@@ -48,13 +71,6 @@
- -
-
-
- Background image
-
-
-
-
@@ -62,32 +78,6 @@
- -
-
-
- false
-
-
- Clear
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
-
@@ -98,57 +88,40 @@
- -
-
+
-
+
- Create
+ Background image
- -
-
-
- -
-
+
-
+
- Remap Map
+ Show
- -
-
-
- Load
-
-
-
- -
-
-
- Load
-
-
-
- -
-
+
-
+
-
+
0
0
- 0
- 0
+ 40
+ 40
- -
-
+
-
+
- Load
+ Show
@@ -159,10 +132,36 @@
- -
-
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 40
+ 40
+
+
+
+
+ -
+
-
+ Remap Map (required)
+
+
+
+ -
+
+
+ false
+
+
+ Clear
@@ -182,11 +181,14 @@
-
+
+ 5
+
1.000000000000000
- 0.100000000000000
+ 0.001000000000000
@@ -219,18 +221,18 @@
-
- Led
- QWidget
-
- 1
-
CvImageViewer
QWidget
1
+
+ Led
+ QWidget
+
+ 1
+
diff --git a/src/ui/cvimageviewer.cpp b/src/ui/cvimageviewer.cpp
index 8d380c7..3b864df 100644
--- a/src/ui/cvimageviewer.cpp
+++ b/src/ui/cvimageviewer.cpp
@@ -1,21 +1,60 @@
#include "cvimageviewer.h"
#include
#include
+#include
+#include
+#include
CvImageViewer::CvImageViewer(QWidget *parent, size_t lastId) :
QWidget(parent),
- lastId_(lastId)
+ lastId_(lastId),
+ saveAction_("Save Image", nullptr)
{
+ connect(&saveAction_, &QAction::triggered, this, &CvImageViewer::saveImage);
qimage_.load(":/images/noimage.png");
+
+ imageContextMenu_.addAction(&saveAction_);
}
CvImageViewer::~CvImageViewer()
{
}
+void CvImageViewer::saveImage()
+{
+ QString fileName;
+ if(origImage_.type() == CV_8UC3 || origImage_.type() == CV_8SC3 || origImage_.type() == CV_8UC1 || origImage_.type() == CV_8SC1)
+ {
+ fileName = QFileDialog::getSaveFileName(this, "Save Image", "./", "*.mat *.png" );
+ }
+ else
+ {
+ fileName = QFileDialog::getSaveFileName(this, "Save Image", "./", "*.mat" );
+ }
+ if(!fileName.isEmpty())
+ {
+ QStringList tokens = fileName.split('.');
+ if(tokens.back() != "mat" && tokens.back() != "png")
+ fileName.append(".mat");
+ tokens = fileName.split('.');
+ if(tokens.back() == "png")
+ {
+ imwrite(fileName.toStdString(), origImage_);
+ }
+ else
+ {
+ cv::FileStorage matf(fileName.toStdString(), cv::FileStorage::WRITE);
+ matf<<"image"<button() == Qt::RightButton)
+ {
+ saveAction_.setEnabled(origImage_.data);
+ 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(imgrect_.width())*origImage_.cols;
+ int y = (event->y()-imgrect_.y())/static_cast(imgrect_.height())*origImage_.rows;
+ qDebug()<= 0 && y >= 0 && x <= origImage_.cols && y < origImage_.rows)
+ sigValue(x, y, origImage_.at(y,x));
+ }
+ else
+ {
+
+ sigValue(x, y, 0);
+ }
+ }
+ QWidget::mousePressEvent(event);
+}
+
void CvImageViewer::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event)
QPainter painter(this);
- if(!fixedOnWidth_)
- {
- double ratio = qimage_.size().width() / qimage_.size().height();
- painter.drawImage(QRect((rect().width()-rect().height())/2, rect().y(), rect().height()*ratio, rect().height()), qimage_);
- }
+ double ratio = qimage_.size().height() / (double)qimage_.size().width();
+ if(rect().width()*ratio <= rect().height())
+ imgrect_.setRect(0, (rect().height()-rect().width()*ratio)/2, rect().width(), rect().width()*ratio);
else
- {
- double ratio = qimage_.size().height() / qimage_.size().width();
- painter.drawImage(QRect(rect().x(), (rect().height()-rect().width())/2, rect().width(), rect().width()*ratio), qimage_);
- }
+ imgrect_.setRect((rect().width()-rect().height()/ratio)/2, 0, rect().height()/ratio, rect().height());
+ painter.drawImage(imgrect_, qimage_);
}
diff --git a/src/ui/cvimageviewer.h b/src/ui/cvimageviewer.h
index 58b0f77..f932a99 100644
--- a/src/ui/cvimageviewer.h
+++ b/src/ui/cvimageviewer.h
@@ -3,19 +3,32 @@
#include
#include
+#include
#include "../cameras.h"
class CvImageViewer : public QWidget
{
Q_OBJECT
+private:
+ cv::Mat origImage_;
cv::Mat image_;
QImage qimage_;
bool fixedOnWidth_ = false;
size_t lastId_;
+ QMenu imageContextMenu_;
+ QAction saveAction_;
+ QRect imgrect_;
+
+private slots:
+ void saveImage();
protected:
virtual void paintEvent(QPaintEvent* event) override;
+ virtual void mousePressEvent(QMouseEvent *event) override;
+
+signals:
+ void sigValue(size_t x, size_t y, double value);
public slots:
void setImage(Camera::Image img);
@@ -23,6 +36,8 @@ public slots:
public:
explicit CvImageViewer(QWidget *parent = nullptr, size_t lastId = 0);
void setFixedOnWidth(bool in){fixedOnWidth_ = in;}
+ cv::Mat getImage(){return origImage_;}
+
size_t lastId(){return lastId_;}
~CvImageViewer();
};
diff --git a/src/ui/editprofiledialog.cpp b/src/ui/editprofiledialog.cpp
index 0bdaf99..9b54db9 100644
--- a/src/ui/editprofiledialog.cpp
+++ b/src/ui/editprofiledialog.cpp
@@ -2,6 +2,8 @@
#include "ui_editprofiledialog.h"
#include
#include
+#include
+#include
#include "configurecameradialog.h"
@@ -24,26 +26,91 @@ EditProfileDialog::EditProfileDialog(Cameras* cameras, const Profile profile, QW
ui->checkBoxCh3->setChecked(profile_.lighting.mask & CHANNEL_C);
ui->checkBoxCh4->setChecked(profile_.lighting.mask & CHANNEL_D);
- if(profile_.cameras.size() == 0)
- profile_.setCamerasSetupsFromDescription(cameras_->getCameras());
+ ui->checkBoxNodistort->setChecked(profile_.nodistort);
+
+ std::vector descs = cameras_->getCameras();
+ profile_.setCamerasSetupsFromDescription(descs);
+
+ if(profile_.cameras.size() > 0)
+ {
+ uint64_t min, max;
+ std::shared_ptr cam = cameras_->getCamera(profile_.cameras[0].id);
+ if(cam)
+ {
+ cam->cam()->getExposureTimeLimits(min, max);
+ ui->doubleSpinBoxExposure->setMaximum(max/1000000.0);
+ ui->doubleSpinBoxExposure->setMinimum(min/1000000.0);
+ }
+ }
+
+ ui->calLed->setLit(profile_.calcurve.data);
connect(ui->doubleSpinBoxBrightness, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double in){profile_.lighting.brightness = in/100.0;});
- connect(ui->doubleSpinBoxExposure, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double in){profile_.exposureTime = in;});
+ connect(ui->doubleSpinBoxExposure, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double in){profile_.exposureTime = in; invalidateCameras();});
connect(ui->lineEditName, &QLineEdit::textChanged, [this](QString in){profile_.setName(in);});
connect(ui->checkBoxCh1, &QCheckBox::clicked, this, &EditProfileDialog::setMask);
connect(ui->checkBoxCh2, &QCheckBox::clicked, this, &EditProfileDialog::setMask);
connect(ui->checkBoxCh3, &QCheckBox::clicked, this, &EditProfileDialog::setMask);
connect(ui->checkBoxCh4, &QCheckBox::clicked, this, &EditProfileDialog::setMask);
connect(ui->pushButton, &QPushButton::clicked, this, &EditProfileDialog::configureCamera);
+ connect(ui->checkBoxNodistort, &QCheckBox::stateChanged, [this](int state){profile_.nodistort = state == Qt::Checked ?: false; setConfigured();});
+ connect(ui->pushButtonCalLoad, &QPushButton::clicked, this, &EditProfileDialog::loadCalcurve);
+ connect(ui->pushButtonLightmapLoad, &QPushButton::clicked, this, &EditProfileDialog::loadCalcurve);
ui->listView->setCameras(cameras_->getCameras());
ui->listView->setSelectionMode(QAbstractItemView::SingleSelection);
setConfigured();
}
-void EditProfileDialog::setConfigured()
+void EditProfileDialog::loadLightmap()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, "Open Lightmap", "./", "*.mat");
+ if(!fileName.isEmpty())
+ {
+ profile_.calcurve.release();
+ cv::FileStorage matf(fileName.toStdString(), cv::FileStorage::READ);
+ matf["image"]>>profile_.lightmap;
+
+ if(matf.isOpened() && (!profile_.calcurve.data || profile_.calcurve.type() != CV_32FC1))
+ {
+ profile_.lightmap.release();
+ QMessageBox::warning(this, "Invalid file", "File selected dose not contain a valid lightmap");
+ }
+ else if(!profile_.calcurve.data)
+ {
+ QMessageBox::warning(this, "Can no open", "Can not open file selected");
+ }
+ matf.release();
+ ui->ledLightmap->setLit(profile_.lightmap.data);
+ }
+}
+
+void EditProfileDialog::loadCalcurve()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, "Open Cal Curve", "./", "*.mat");
+ if(!fileName.isEmpty())
+ {
+ profile_.calcurve.release();
+ cv::FileStorage matf(fileName.toStdString(), cv::FileStorage::READ);
+ matf["cal"]>>profile_.calcurve;
+
+ if(matf.isOpened() && (!profile_.calcurve.data || profile_.calcurve.type() != CV_32FC1 || profile_.calcurve.rows != 2))
+ {
+ profile_.calcurve.release();
+ QMessageBox::warning(this, "Invalid file", "File selected dose not contain a valid cal curve");
+ }
+ else if(!profile_.calcurve.data)
+ {
+ QMessageBox::warning(this, "Can no open", "Can not open file selected");
+ }
+ matf.release();
+ ui->calLed->setLit(profile_.calcurve.data);
+ }
+}
+
+bool EditProfileDialog::setConfigured()
{
std::vector descs = cameras_->getCameras();
- std::vector configured(descs.size(), false);
+ std::vector configured(descs.size(), profile_.nodistort);
for(size_t i = 0; i< profile_.cameras.size(); ++i)
{
@@ -52,12 +119,19 @@ void EditProfileDialog::setConfigured()
{
for(auto& camera : descs)
{
- if(camera.getHash() == profileCamera.id)
+ if(camera.getId() == profileCamera.id)
configured[i] = true;
}
}
}
ui->listView->setConfigured(configured);
+ bool fullyConfigured = true;
+ for(bool config : configured)
+ {
+ if(!config)
+ fullyConfigured = false;
+ }
+ return fullyConfigured;
}
void EditProfileDialog::invalidateCameras()
@@ -78,10 +152,12 @@ void EditProfileDialog::configureCamera()
qDebug()<<"descs"< camera = cameras_->getCamera(profile_.cameras[i].id);
if(camera)
@@ -94,9 +170,18 @@ void EditProfileDialog::configureCamera()
}
}
}
+ setConfigured();
}
}
+void EditProfileDialog::accept()
+{
+ if(!setConfigured())
+ QMessageBox::information(this, "Unfinished", "Can not accept with unconfigured cameras");
+ else
+ QDialog::accept();
+}
+
void EditProfileDialog::setMask()
{
uint8_t mask = (ui->checkBoxCh1->isChecked() ? CHANNEL_A : 0) |
diff --git a/src/ui/editprofiledialog.h b/src/ui/editprofiledialog.h
index 5bfc50c..6a899c8 100644
--- a/src/ui/editprofiledialog.h
+++ b/src/ui/editprofiledialog.h
@@ -15,13 +15,17 @@ class EditProfileDialog : public QDialog
Profile profile_;
Cameras* cameras_;
- void setConfigured();
+ bool setConfigured();
void invalidateCameras();
private slots:
-
void setMask();
void configureCamera();
+ void loadCalcurve();
+ void loadLightmap();
+
+public slots:
+ virtual void accept() override;
public:
explicit EditProfileDialog(Cameras* cameras, const Profile profile = Profile(), QWidget *parent = nullptr);
diff --git a/src/ui/editprofiledialog.ui b/src/ui/editprofiledialog.ui
index 7e9783b..25d8a49 100644
--- a/src/ui/editprofiledialog.ui
+++ b/src/ui/editprofiledialog.ui
@@ -7,11 +7,11 @@
0
0
539
- 485
+ 652
- Profile
+ Edit Profile
-
@@ -153,6 +153,9 @@
-
+
+ 5
+
1.000000000000000
@@ -176,9 +179,89 @@
+ -
+
+
+ Don't undisort camera image
+
+
+
+ -
+
+
+ 10
+
+
-
+
+
+ Calibration curve:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 40
+ 40
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Load
+
+
+
+ -
+
+
+ Lightmap:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 40
+ 40
+
+
+
+
+ -
+
+
+ Load
+
+
+
+
+
-
@@ -192,6 +275,12 @@
+
+ Led
+ QWidget
+
+ 1
+
CameraListWidget
QListView
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp
index 7782173..2cf7348 100644
--- a/src/ui/mainwindow.cpp
+++ b/src/ui/mainwindow.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include "../profile.h"
@@ -17,9 +18,62 @@ MainWindow::MainWindow(QWidget *parent)
connect(ui->actionProfile, &QAction::triggered, [this](bool checked){(void)checked; sigEditProfiles();});
connect(ui->comboBox, &QComboBox::currentTextChanged, this, &MainWindow::sigProfile);
connect(ui->pushButtonCapture, &QPushButton::clicked, this, &MainWindow::sigCapture);
+ connect(ui->mainViewer, &CvImageViewer::sigValue, this, &MainWindow::setImageValue);
+ connect(ui->actionOpen, &QAction::triggered, [this](bool checked){(void)checked; openImage();});
+ connect(ui->actionSave_2, &QAction::triggered, [this](bool checked){(void)checked; saveImage();});
refreshProfiles();
}
+void MainWindow::setImageValue(size_t x, size_t y, double value)
+{
+ ui->lcdNumber_3->display((double)x);
+ ui->lcdNumber_2->display((double)y);
+ ui->lcdNumber->display(value);
+}
+
+void MainWindow::saveImage()
+{
+ if(!ui->mainViewer->getImage().data)
+ {
+ QMessageBox::warning(this, "No image", "There is no image to save");
+ return;
+ }
+
+ QString fileName = QFileDialog::getSaveFileName(this, "Save Image", "./", "*.mat");
+ if(!fileName.isEmpty())
+ {
+ QStringList tokens = fileName.split('.');
+ if(tokens.back() != "mat")
+ fileName.append(".mat");
+ cv::FileStorage matf(fileName.toStdString(), cv::FileStorage::WRITE);
+ matf<<"image"<mainViewer->getImage();
+ matf.release();
+ }
+}
+
+void MainWindow::openImage()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, "Open Image", "./", "*.mat");
+ if(!fileName.isEmpty())
+ {
+ cv::Mat image;
+ cv::FileStorage matf(fileName.toStdString(), cv::FileStorage::READ);
+ matf["image"]>>image;
+
+ if(matf.isOpened() && (!image.data || image.type() != CV_32FC1))
+ {
+ image.release();
+ QMessageBox::warning(this, "Invalid file", "File selected dose not contain a valid lightmap");
+ }
+ else if(!image.data)
+ {
+ QMessageBox::warning(this, "Can no open", "Can not open file selected");
+ }
+ matf.release();
+ ui->mainViewer->setImage(Camera::Image(image, 0));
+ }
+}
+
void MainWindow::addCamera(std::shared_ptr camera)
{
viewers_.push_back(new CvImageViewer(this, camera->id()));
@@ -28,6 +82,11 @@ void MainWindow::addCamera(std::shared_ptr camera)
ui->viewerLayout->addWidget(viewers_.back());
}
+void MainWindow::statusMsg(QString msg)
+{
+ ui->statusbar->showMessage(msg);
+}
+
void MainWindow::removeCamera(std::shared_ptr camera)
{
for(size_t i = 0; i < viewers_.size(); ++i)
@@ -93,4 +152,3 @@ MainWindow::~MainWindow()
delete viewer;
delete ui;
}
-
diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h
index 5fd0f33..0f33bd9 100644
--- a/src/ui/mainwindow.h
+++ b/src/ui/mainwindow.h
@@ -16,6 +16,11 @@ class MainWindow : public QMainWindow
private:
std::vector viewers_;
+private slots:
+ void setImageValue(size_t x, size_t y, double value);
+ void saveImage();
+ void openImage();
+
signals:
void sigCapture();
void sigProfile(QString profileName);
@@ -30,6 +35,7 @@ public slots:
void removeCamera(std::shared_ptr camera);
bool setProfile(const QString& profileName);
QString getProfileName();
+ void statusMsg(QString msg);
public:
MainWindow(QWidget *parent = nullptr);
diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui
index 3ae254c..784b7f2 100644
--- a/src/ui/mainwindow.ui
+++ b/src/ui/mainwindow.ui
@@ -11,7 +11,11 @@
- MainWindow
+ Lubricant Detector
+
+
+
+ :/images/icon.png:/images/icon.png
@@ -27,6 +31,9 @@
-
+
+ Qt::ScrollBarAsNeeded
+
true
@@ -68,7 +75,7 @@
0
0
467
- 353
+ 313
@@ -79,6 +86,55 @@
+ -
+
+
+ 10
+
+
-
+
+
+ Qt::LeftToRight
+
+
+ X
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ Y
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ -
+
+
+ Value
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+
@@ -146,7 +202,8 @@
File
-
+
+
@@ -189,6 +265,8 @@
1
-
+
+
+
diff --git a/src/ui/profiledialog.cpp b/src/ui/profiledialog.cpp
index c6fdaec..a6f04ff 100644
--- a/src/ui/profiledialog.cpp
+++ b/src/ui/profiledialog.cpp
@@ -34,7 +34,7 @@ void ProfileDialog::editProfile()
QMessageBox::critical(this, "Profile Incompatible", "Not all cameras need for this profile are available");
return;
}
- EditProfileDialog dialog(cameras_, profile);
+ EditProfileDialog dialog(cameras_, profile, this);
dialog.show();
int ret = dialog.exec();
if(ret == QDialog::Accepted)
diff --git a/src/ui/profiledialog.ui b/src/ui/profiledialog.ui
index c2b3e9c..9c07933 100644
--- a/src/ui/profiledialog.ui
+++ b/src/ui/profiledialog.ui
@@ -13,6 +13,10 @@
Profiles
+
+
+ :/images/icon.png:/images/icon.png
+
-
@@ -61,7 +65,9 @@
-
+
+
+
buttonBox