From b9b4b0fc2a841f22dcbca9f33a7c154be21901bb Mon Sep 17 00:00:00 2001 From: uvos Date: Thu, 8 Jul 2021 11:24:19 +0200 Subject: [PATCH] fix various bugs add commandline parser for various options allow cameras to be operated in serial fashion allow disabeling of quirks allow changing of Photonfocus quirk timeings --- src/cameras.cpp | 41 +++++++++++++++++++----- src/cameras.h | 7 +++- src/imagepipeline.cpp | 55 ++++++++++++++++++++++++-------- src/imagepipeline.h | 6 ++-- src/main.cpp | 31 +++++++++++++++--- src/ui/configurecameradialog.cpp | 13 ++++++-- src/ui/configurecameradialog.h | 3 +- src/ui/editprofiledialog.cpp | 8 +++-- src/ui/editprofiledialog.ui | 5 ++- src/ui/mainwindow.cpp | 1 + 10 files changed, 134 insertions(+), 36 deletions(-) diff --git a/src/cameras.cpp b/src/cameras.cpp index 8783e5b..20ee047 100644 --- a/src/cameras.cpp +++ b/src/cameras.cpp @@ -6,7 +6,8 @@ #include #include -Cameras::Cameras(uvosled* led): led_(led) +Cameras::Cameras(uvosled* led, bool quirks, bool serial): + led_(led), quirks_(quirks), serial_(serial) { ledTimer.setSingleShot(true); cameraFailureTimer.setSingleShot(true); @@ -82,7 +83,7 @@ bool Cameras::addCamera(const cam::Camera::Description& desc) cameras_.back()->cam()->setExposureTime(exposrueTime_); - if(desc.getVendor().find("Photonfocus") != std::string::npos) + if(quirks_ && desc.getVendor().find("Photonfocus") != std::string::npos) { qDebug()<<"Mitiagting broken PhotonFocus single shot mode"; std::shared_ptr camera = cameras_.back(); @@ -107,7 +108,13 @@ bool Cameras::addCamera(const cam::Camera::Description& desc) camera->cam()->setAcquisitionMode(cam::Camera::MODE_FREE); camera->cam()->setFrameRate(10); camera->cam()->startAcquisition(); - QTimer::singleShot(5000, [camera, this](){finishAddCamera(camera);}); + if(!serial_) + QTimer::singleShot(quirkTime, this, [this, camera](){finishAddCamera(camera);}); + else + { + std::this_thread::sleep_for(std::chrono::microseconds(static_cast(quirkTime*1000))); + finishAddCamera(camera); + } } else { @@ -147,10 +154,23 @@ void Cameras::lightOff() void Cameras::trigger() { - lightFor(lighting_, exposrueTime_*1.5); - - for(auto& camera : cameras_) - camera->cam()->trigger(); + if(serial_) + { + if(captureingCamera == 0) + lightFor(lighting_, exposrueTime_*1.5*cameras_.size()); + cameras_[captureingCamera]->cam()->trigger(); + ++captureingCamera; + if(captureingCamera < cameras_.size()) + QTimer::singleShot(exposrueTime_*1000, this, &Cameras::trigger); + else + captureingCamera = 0; + } + else + { + lightFor(lighting_, exposrueTime_*1.5); + for(auto& camera : cameras_) + camera->cam()->trigger(); + } } bool Cameras::start() @@ -242,7 +262,12 @@ void Cameras::imageRecived(Camera::Image img) qDebug()<<"Recived"<> cameras_; std::vector images_; + size_t captureingCamera = 0; QTimer ledTimer; QTimer cameraFailureTimer; + bool quirks_; + bool serial_; bool lightFor(const LightingSetup& lighting, double time); @@ -57,7 +60,7 @@ public slots: void reloadCameras(); public: - Cameras(uvosled* led = nullptr); + Cameras(uvosled* led = nullptr, bool quirks = true, bool serial = false); ~Cameras(); bool setCameras(const std::vector& descriptions); bool addCamera(const cam::Camera::Description& desc); @@ -70,6 +73,8 @@ public: void load(QSettings& settings); void store(QSettings& settings); void disable(bool disable); + + inline static float quirkTime = 3; }; #endif // CAMERAS_H diff --git a/src/imagepipeline.cpp b/src/imagepipeline.cpp index 1804afa..8a316f5 100644 --- a/src/imagepipeline.cpp +++ b/src/imagepipeline.cpp @@ -8,12 +8,41 @@ #include #include -ImagePipeline::ImagePipeline(Cameras* cameras, QObject *parent): QObject(parent), cameras_(cameras) +ImagePipeline::ImagePipeline(Cameras* cameras, bool simpleStichingAlg, QObject *parent): + QObject(parent), cameras_(cameras), simpleStichingAlg_(simpleStichingAlg) { connect(cameras_, &Cameras::newImages, this, &ImagePipeline::apply); } -cv::Mat ImagePipeline::process(const Profile profile, std::vector images) +void ImagePipeline::applyDarkMap(cv::Mat& image, const cv::Mat& darkmap) +{ + cv::Mat localDarkMap; + if(image.size() != darkmap.size()) + { + qWarning()<<"image and darkmap not of the same size"< images, bool simpleStichingAlg) { qDebug()<<__func__<<"got"< remapedImages; @@ -32,7 +61,7 @@ cv::Mat ImagePipeline::process(const Profile profile, std::vector img.origin.y = 0; image.mat.copyTo(img.image); if(profile.cameras[0].darkmap.data) - img.image = img.image - profile.cameras[0].darkmap; + applyDarkMap(img.image, profile.cameras[0].darkmap); remapedImages.push_back(img); break; } @@ -42,7 +71,7 @@ cv::Mat ImagePipeline::process(const Profile profile, std::vector { for(Camera::Image& image : images) { - qDebug()<<__FUNCTION__<<"image cam id"< if(!camera.remapMap.xMat.data || !camera.remapMap.yMat.data) return cv::Mat(); if(camera.darkmap.data) - { - cv::Mat subtracted; - image.mat.copyTo(subtracted); - qDebug()<<"Camera"< if(remapedImages.size() > 0) { std::sort(remapedImages.begin(), remapedImages.end(), [](const RemapedImage& imgA, const RemapedImage& imgB) -> bool {return imgA.origin.x < imgB.origin.x;}); - cv::Mat output = stich(remapedImages); + cv::Mat output; + if(simpleStichingAlg) + output = simpleStich(remapedImages); + else + output = stich(remapedImages, true); if(output.depth() != CV_8U) output.convertTo(output, CV_8U); @@ -125,7 +152,7 @@ void ImagePipeline::apply(std::vector images) connect(futureImageWatchers_.back(), &QFutureWatcher::finished, this, &ImagePipeline::imageFinished); statusMsg("Processing"); - QFuture futureImage = QtConcurrent::run(&ImagePipeline::process, profile_, images); + QFuture futureImage = QtConcurrent::run(&ImagePipeline::process, profile_, images, simpleStichingAlg_); futureImageWatchers_.back()->setFuture(futureImage); } } @@ -141,7 +168,7 @@ void ImagePipeline::setProfile(const Profile& profile) { qDebug()<getCameras())) diff --git a/src/imagepipeline.h b/src/imagepipeline.h index 09c09d2..9e2ff2c 100644 --- a/src/imagepipeline.h +++ b/src/imagepipeline.h @@ -19,8 +19,10 @@ private: Profile profile_; bool invalid_ = true; std::vector*> futureImageWatchers_; + bool simpleStichingAlg_; - static cv::Mat process(const Profile profile, std::vector images); + static cv::Mat process(const Profile profile, std::vector images, bool simpleStich); + static void applyDarkMap(cv::Mat& image, const cv::Mat &darkmap); private slots: @@ -36,7 +38,7 @@ public slots: void setProfile(const Profile& profile); public: - ImagePipeline(Cameras* cameras, QObject* parent = nullptr); + ImagePipeline(Cameras* cameras, bool simpleStichingAlg = false, QObject* parent = nullptr); }; #endif // IMAGEPIPELINE_H diff --git a/src/main.cpp b/src/main.cpp index 8ead414..94d3d58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "cameras.h" #include "./ui/cameradialog.h" @@ -66,9 +67,25 @@ int main(int argc, char *argv[]) QApplication a(argc, argv); QCoreApplication::setOrganizationName("UVOS"); QCoreApplication::setOrganizationDomain("uvos.xyz"); - QCoreApplication::setApplicationName("LubircantThiknessMapperUi"); + QCoreApplication::setApplicationName("MAClient"); QCoreApplication::setApplicationVersion("0.1"); + //parse comand line + QCommandLineParser parser; + parser.addHelpOption(); + parser.addVersionOption(); + QCommandLineOption noQuirkOption(QStringList() << "q" << "no-quirk", QCoreApplication::translate("main", "Do not enable camera specific quirks")); + parser.addOption(noQuirkOption); + QCommandLineOption serialOption(QStringList() << "s" << "serial", QCoreApplication::translate("main", "Take images in sequence instead of all at once")); + parser.addOption(serialOption); + QCommandLineOption simpleStichOption(QStringList() << "x" << "simple-stich", QCoreApplication::translate("main", "use simple sticher")); + parser.addOption(simpleStichOption); + QCommandLineOption quirkDurationOption(QStringList() << "d" << "quirk-duration", QCoreApplication::translate("main", "PhotonFocus quirk duration time"), QCoreApplication::translate("main", "time")); + parser.addOption(quirkDurationOption); + QCommandLineOption cameraBootDurationOption(QStringList() << "d" << "quirk-duration", QCoreApplication::translate("main", "Camera boot time"), QCoreApplication::translate("main", "time")); + parser.addOption(cameraBootDurationOption); + parser.process(a); + QSplashScreen splash(QPixmap(":/images/splash.png")); splash.show(); @@ -88,12 +105,18 @@ int main(int argc, char *argv[]) uvosled_poweron(&led); // Give cameras some time to power on // TODO: figure out how to do this better - sleep(10); + if(parser.isSet(cameraBootDurationOption)) + sleep(parser.value(cameraBootDurationOption).toDouble()); + else + sleep(20); } - Cameras cameras(uvosledRet < 0 ? nullptr : &led); + Cameras cameras(uvosledRet < 0 ? nullptr : &led, !parser.isSet(noQuirkOption), parser.isSet(serialOption)); cameras.setFree(false); - ImagePipeline pipe(&cameras); + ImagePipeline pipe(&cameras, parser.isSet(simpleStichOption)); + + if(parser.isSet(quirkDurationOption)) + cameras.quirkTime = parser.value(quirkDurationOption).toDouble(); MainWindow w; diff --git a/src/ui/configurecameradialog.cpp b/src/ui/configurecameradialog.cpp index 4a905b4..902ac68 100644 --- a/src/ui/configurecameradialog.cpp +++ b/src/ui/configurecameradialog.cpp @@ -9,11 +9,12 @@ #include #include -ConfigureCameraDialog::ConfigureCameraDialog(const CameraSetup& setup, std::shared_ptr camera, double exposureTime, QWidget *parent): +ConfigureCameraDialog::ConfigureCameraDialog(const CameraSetup& setup, std::shared_ptr camera, double exposureTime, bool nodistort, QWidget *parent): QDialog(parent), setup_(setup), camera_(camera), profileExposure_(exposureTime), + nodistort_(nodistort), ui(new Ui::ConfigureCameraDialog) { ui->setupUi(this); @@ -21,6 +22,14 @@ ConfigureCameraDialog::ConfigureCameraDialog(const CameraSetup& setup, std::shar ui->doubleSpinBox->setValue(profileExposure_); setExposure(profileExposure_); + if(nodistort) + { + ui->ledRemap->setHidden(true); + ui->label_2->setHidden(true); + ui->pushButtonRemapClear->setHidden(true); + ui->pushButtonRemapCreate->setHidden(true); + } + switch(setup.bayerMode) { case cam::Camera::BAYER_BLUE: @@ -215,5 +224,5 @@ bool ConfigureCameraDialog::checkConfig() ui->ledDark->setLit(darkMapOK); ui->ledRemap->setLit(remapMapOk); - return remapMapOk; + return remapMapOk || nodistort_; } diff --git a/src/ui/configurecameradialog.h b/src/ui/configurecameradialog.h index 0b780af..071fe7c 100644 --- a/src/ui/configurecameradialog.h +++ b/src/ui/configurecameradialog.h @@ -23,6 +23,7 @@ class ConfigureCameraDialog : public QDialog int mode_ = MODE_IDLE; cv::Mat fgImage; double profileExposure_; + bool nodistort_; private: bool checkConfig(); @@ -40,7 +41,7 @@ public slots: void accept() override; public: - explicit ConfigureCameraDialog(const CameraSetup& setup, const std::shared_ptr camera, double exposureTime = 1.0/60, QWidget *parent = nullptr); + explicit ConfigureCameraDialog(const CameraSetup& setup, const std::shared_ptr camera, double exposureTime = 1.0/60, bool nodistort = false, QWidget *parent = nullptr); ~ConfigureCameraDialog(); CameraSetup getCameraSetup(){return setup_;} diff --git a/src/ui/editprofiledialog.cpp b/src/ui/editprofiledialog.cpp index cc7862c..6d63704 100644 --- a/src/ui/editprofiledialog.cpp +++ b/src/ui/editprofiledialog.cpp @@ -48,7 +48,7 @@ EditProfileDialog::EditProfileDialog(Cameras* cameras, const Profile profile, QW ui->ledLightmap->setLit(profile_.lightmap.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; invalidateCameras();}); + connect(ui->doubleSpinBoxExposure, QOverload::of(&QDoubleSpinBox::valueChanged), [this](double in){profile_.exposureTime = in;}); 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); @@ -168,7 +168,7 @@ void EditProfileDialog::configureCamera() std::shared_ptr camera = cameras_->getCamera(profile_.cameras[i].id); if(camera) { - ConfigureCameraDialog diag(profile_.cameras[i], camera, profile_.exposureTime, this); + ConfigureCameraDialog diag(profile_.cameras[i], camera, profile_.exposureTime, profile_.nodistort, this); diag.show(); int ret = diag.exec(); if(ret == QDialog::Accepted) @@ -182,8 +182,10 @@ void EditProfileDialog::configureCamera() void EditProfileDialog::accept() { - if(!setConfigured() || profile_.getName() == "Unamed") + if(!setConfigured()) QMessageBox::information(this, "Unfinished", "Can not accept with unconfigured cameras"); + else if(profile_.getName().isEmpty() || profile_.getName() == "Unamed") + QMessageBox::information(this, "Unfinished", "A profile name is required"); else QDialog::accept(); } diff --git a/src/ui/editprofiledialog.ui b/src/ui/editprofiledialog.ui index a275e2f..5c4552b 100644 --- a/src/ui/editprofiledialog.ui +++ b/src/ui/editprofiledialog.ui @@ -26,7 +26,10 @@ - Unamed + + + + Unamed diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 2ff4fb5..dd8aed5 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -151,6 +151,7 @@ QString MainWindow::getProfileName() void MainWindow::refreshProfiles() { + QString tmp = ui->comboBox->currentText(); ui->comboBox->clear(); QList profiles = Profile::avaiableProfiles(); for(const QString& string : profiles)