From b322bfdb47d2d473b79dfacd1b0f7cea9a5a1157 Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Fri, 24 Nov 2023 15:29:05 +0100 Subject: [PATCH] rework camera setup --- camconfig.cpp | 124 +++++++++++++++++++++++++++++----------------- camconfig.h | 12 ++--- camerapreview.cpp | 117 +++++++++++++++++++++++++++++++------------ camerapreview.h | 22 +++++--- main.cpp | 2 +- notes.md | 14 ++++++ pylonrecorder.cpp | 2 + 7 files changed, 201 insertions(+), 92 deletions(-) create mode 100644 notes.md diff --git a/camconfig.cpp b/camconfig.cpp index bd399a2..19e67b1 100644 --- a/camconfig.cpp +++ b/camconfig.cpp @@ -2,9 +2,11 @@ #include "mylogger.h" #include "util.h" + CamConfigurator::CamConfigurator(Pylon::DeviceInfoList_t &deviceList, QWidget *parent) : - deviceList(deviceList), QDialog(parent) { + deviceList(deviceList), QDialog(parent), preview(nullptr) { mode_combo = new QComboBox(this); + mode_combo->addItem("camera mode"); mode_combo->addItem("single camera"); if (deviceList.size() > 1){ mode_combo->addItem("stereo camera"); @@ -17,10 +19,11 @@ CamConfigurator::CamConfigurator(Pylon::DeviceInfoList_t &deviceList, QWidget *p } connect(device_combo, SIGNAL(currentIndexChanged(int)), SLOT(primaryDeviceChanged(int))); - orientation_combo = new QComboBox(this); - orientation_combo->addItem("Vertical"); - orientation_combo->addItem("Horizontal"); - orientation_combo->setEnabled(false); + // orientation_combo = new QComboBox(this); + // orientation_combo->addItem("Vertical"); + // orientation_combo->addItem("Horizontal"); + // orientation_combo->setEnabled(false); + // connect(orientation_combo, SIGNAL(currentIndexChanged(int)), SLOT(orientationChanged(int))); QWidget *header = new QWidget(this); QGridLayout *grid = new QGridLayout(header); @@ -28,16 +31,12 @@ CamConfigurator::CamConfigurator(Pylon::DeviceInfoList_t &deviceList, QWidget *p grid->addWidget(mode_combo, 0, 1); grid->addWidget(new QLabel("Primary device:", this), 1, 0); grid->addWidget(device_combo, 1, 1); - grid->addWidget(new QLabel("Orientation:", this), 2, 0); - grid->addWidget(orientation_combo, 2, 1); header->setLayout(grid); QVBoxLayout *vbox = new QVBoxLayout(this); vbox->addWidget(header); - stack = new QStackedWidget(this); - stack->addWidget(singleCameraView()); - stack->addWidget(new QLabel("Stereo View")); + stack->addWidget(new QLabel("CameraSetup, select mode!")); stack->setCurrentIndex(0); vbox->addWidget(stack); @@ -50,58 +49,91 @@ CamConfigurator::CamConfigurator(Pylon::DeviceInfoList_t &deviceList, QWidget *p // qInfo() << "Create Camera configuration!"; } -QWidget* CamConfigurator::singleCameraView() { - qInfo() << "Create Camera configuration!"; - - QWidget *w = new QWidget(this); - QVBoxLayout *l = new QVBoxLayout(w); - l->setParent(w); - w->setLayout(l); - QString cam_name = device_combo->currentText(); - singleCamPreview = new CameraPreview(cam_name, this); - l->addWidget(singleCamPreview); - return w; +CameraSetup* CamConfigurator::singleCameraView() { + qInfo() << "Create Single Camera configuration!"; + if (preview != nullptr) { + delete preview; + preview = nullptr; + } + preview = new SingleCamera(this); + return preview; } -// void CamConfigurator::stereoCameraView() { -// QWidget *w = new QWidget(this); -// QVBoxLayout *l = new QVBoxLayout(); -// w->setLayout(l); -// l->addWidget(orientation_combo); -// } + +CameraSetup* CamConfigurator::stereoCameraView() { + qInfo() << "Create stereoCameraConfiguration"; + if (preview != nullptr) { + delete preview; + preview = nullptr; + } + preview = new DualCamera(this); + return preview; +} void CamConfigurator::modeChanged(int idx) { - stack->setCurrentIndex(idx); - orientation_combo->setEnabled(idx == 1); + stack->setCurrentIndex(0); + if (stack->count() > 1 && preview != nullptr) { + qDebug() << "removing previous widget from stack"; + stack->removeWidget(preview); + delete preview; + preview == nullptr; + } + if (idx == 1) { + qDebug() << "Mode changed to single camera mode"; + qDebug() << "add new single camera preview"; + preview = singleCameraView(); + stack->addWidget(preview); + stack->setCurrentIndex(1); + QString device = device_combo->currentText(); + preview->setPrimaryCamera(device); + } else if (idx == 2) { + qDebug() << "Mode changed to dual camera mode"; + preview = stereoCameraView(); + stack->addWidget(preview); + stack->setCurrentIndex(1); + + QString device1 = device_combo->currentText(); + preview->setPrimaryCamera(device1); + int i = device_combo->currentIndex(); + if (i > 1) { + i = 1; + } + QString device2 = device_combo->itemText(1 - i); + preview->setSecondaryCamera(device2); + } else { + qDebug() << "Mode changed mode selection"; + stack->setCurrentIndex(0); + } + // stack->setCurrentIndex(idx); + // TODO release camera? + // orientation_combo->setEnabled(idx == 1); } + +// void CamConfigurator::orientationChanged(int idx) { + +// } + + void CamConfigurator::primaryDeviceChanged(int idx) { - std::cerr << idx << std::endl; - if (stack->currentIndex() == 0) { // single camera setting + if (mode_combo->currentText() == "single camera") { // single camera setting QString devicename = device_combo->currentText(); - singleCamPreview->updateCamera(devicename); + preview->setPrimaryCamera(devicename); + } else { + preview->switchArrangement(); } } CameraLayout CamConfigurator::layout(){ CameraLayout l; - if (mode_combo->currentText() == "single camera") { - l.mode = CameraMode::single; - l.layout = Layout::horizontal; - l.devices.push_back(device_combo->currentText().toStdString()); - l.rois.push_back(singleCamPreview->getRoi()); - } else { - qWarning() << "not implemented yet"; - } - return l; + qDebug() << "Request layout"; + return preview->cameraLayout(); } + CamConfigurator::~CamConfigurator() { - delete singleCamPreview; + qDebug() << "CamConfig Destructor"; + delete preview; } -// void OptionsDialog::file_opened(QString filename) -// { -// QObject::connect(this, SLOT(file_opened(QString)), ui->widget, SLOT(file_opened(QString))); -// } diff --git a/camconfig.h b/camconfig.h index 72e63c5..a48b07c 100644 --- a/camconfig.h +++ b/camconfig.h @@ -8,7 +8,7 @@ #include #include #include -#include "camerapreview.h" +#include "camerasetup.h" class ROI; @@ -29,6 +29,7 @@ public: public slots: void modeChanged(int idx); void primaryDeviceChanged(int idx); +// void orientationChanged(int idx); // signals: // void column_visibility_changed(QString who, QString column, bool state); @@ -36,14 +37,13 @@ public slots: private: Pylon::DeviceInfoList_t deviceList; - QComboBox *mode_combo, *device_combo, *orientation_combo; + QComboBox *mode_combo, *device_combo; //, *orientation_combo; QStackedWidget *stack; QDialogButtonBox *buttonbox; + CameraSetup *preview; - CameraPreview *singleCamPreview; - - QWidget* singleCameraView(); - //void stereoCameraView(); + CameraSetup* singleCameraView(); + CameraSetup* stereoCameraView(); }; #endif // CAMCONFIG_H \ No newline at end of file diff --git a/camerapreview.cpp b/camerapreview.cpp index 3db0a92..44eed6a 100644 --- a/camerapreview.cpp +++ b/camerapreview.cpp @@ -1,9 +1,11 @@ #include "camerapreview.h" #include #include +#include "mylogger.h" -CameraPreview::CameraPreview(QString &devicename, QWidget *parent):cameraname(devicename), QWidget(parent), camera(nullptr) { - QLabel *label = new QLabel(cameraname); +CameraPreview::CameraPreview(QWidget *parent):cameraname(""), camera(nullptr), QWidget(parent) { + qDebug() << "Camera preview constructor"; + label = new QLabel(cameraname); this->setLayout(new QVBoxLayout(this)); this->layout()->addWidget(label); imgLabel = new QLabel(this); @@ -15,25 +17,25 @@ CameraPreview::CameraPreview(QString &devicename, QWidget *parent):cameraname(de width->setMinimum(1); width->setMaximum(2048); width->setValue(width->maximum()); - connect(width, SIGNAL(textChanged(QString)), SLOT(updateROI(QString))); + connect(width, SIGNAL(textChanged(QString)), SLOT(updateWidth(QString))); height = new QSpinBox(controls); height->setMinimum(1); height->setMaximum(1536); height->setValue(height->maximum()); - connect(height, SIGNAL(textChanged(QString)), SLOT(updateROI(QString))); + connect(height, SIGNAL(textChanged(QString)), SLOT(updateHeight(QString))); xoffs = new QSpinBox(controls); xoffs->setMinimum(0); xoffs->setMaximum(2047); xoffs->setValue(0); - connect(xoffs, SIGNAL(textChanged(QString)), SLOT(updateROI(QString))); + connect(xoffs, SIGNAL(textChanged(QString)), SLOT(updateXoffs(QString))); yoffs = new QSpinBox(controls); yoffs->setMinimum(0); yoffs->setMaximum(1535); yoffs->setValue(0); - connect(yoffs, SIGNAL(textChanged(QString)), SLOT(updateROI(QString))); + connect(yoffs, SIGNAL(textChanged(QString)), SLOT(updateYoffs(QString))); QGridLayout *grid = new QGridLayout(controls); grid->addWidget(new QLabel("width", controls), 0, 0); @@ -49,22 +51,26 @@ CameraPreview::CameraPreview(QString &devicename, QWidget *parent):cameraname(de grid->addWidget(yoffs, 1, 3); controls->setLayout(grid); this->layout()->addWidget(controls); - updateCamera(devicename); + //setPrimaryCamera(devicename); + qDebug() << "Camera preview constructor"; takeStill(); } -void CameraPreview::updateCamera(QString &device){ - std::cerr << "update camera! " << device.toStdString() << std::endl; +void CameraPreview::setCamera(QString &device){ + qDebug() << "update camera! ";// << device.toStdString(); cameraname = device; - + label->setText(device); if (camera != NULL) { - std::cerr << "camera is not nullptr! " << std::endl; + qDebug() << "camera is not nullptr! "; delete camera; + camera = nullptr; } camera = new PylonWrapper(cameraname.toStdString()); std::string message; bool success = camera->openCamera(message); if (!success) { + qWarning() << "Could not open camera device!"; + qWarning() << QString::fromStdString(message); QMessageBox msgBox; QString msg = "

Could not open camera device!

" + QString::fromStdString(message) + "

"; msgBox.setText(msg); @@ -75,33 +81,69 @@ void CameraPreview::updateCamera(QString &device){ void CameraPreview::takeStill() { - if (camera->isOpen()) { + qDebug() << "Take Still image!"; + if (camera != nullptr && camera->isOpen()) { MyImage mimg; bool valid = camera->grabFrame(mimg); if (!valid) { - std::cerr << "Grabbing from camera failed!" << std::endl; + qWarning() << "Grabbing from camera failed!"; return; } QImage img(static_cast(mimg.data()), mimg.width(), mimg.height(), QImage::Format::Format_Grayscale8); - - // QPixmap img("/home/grewe/projects/programming/pylon-recorder/test.png"); - QPixmap mpm = QPixmap::fromImage(img); - this->pm = mpm; - mpm = mpm.scaledToWidth(1024); - setImage(mpm); - updateROI(""); + QPixmap mpm = QPixmap::fromImage(img); + this->pm = mpm; + mpm = mpm.scaledToWidth(1024); + setImage(mpm); + updateROI(); } else { - std::cerr << "Camera is not open! Connect to camera first!" << std::endl; + qDebug() << "Camera is not open! Connect to camera first!"; } - } void CameraPreview::setImage(const QPixmap &img) { imgLabel->setPixmap(img); } -void CameraPreview::updateROI(QString v){ +void CameraPreview::updateWidth(QString s) { + // if (xoffs->value() + width->value() > 2048) { + // xoffs->setValue(2048 - width->value()); + // } + validate(width, xoffs, 2048); + updateROI(); +} + +void CameraPreview::updateXoffs(QString s) { + // if (xoffs->value() + width->value() > 2048) { + // width->setValue(2048 - xoffs->value()); + // } + validate(xoffs, width, 2048); + updateROI(); +} + +void CameraPreview::updateHeight(QString s) { + // if (height->value() + yoffs->value() > 1536) { + // yoffs->setValue(1536 - height->value()); + // } + validate(height, yoffs, 1536); + updateROI(); +} + +void CameraPreview::updateYoffs(QString s) { + // if (height->value() + yoffs->value() > 1536) { + // height->setValue(1536 - yoffs->value()); + // } + validate(yoffs, height, 1536); + updateROI(); +} + +void CameraPreview::validate(QSpinBox *origin, QSpinBox *dest, int limit){ + if (origin->value() + dest->value() > limit) { + dest->setValue(limit - origin->value()); + } +} + +void CameraPreview::updateROI(bool emitSignal) { QImage img = pm.toImage(); double scaling = 1024.0 / img.width(); img = img.scaledToWidth(1024); @@ -121,10 +163,22 @@ void CameraPreview::updateROI(QString v){ QPixmap npm = QPixmap::fromImage(img); setImage(npm); + if (emitSignal) { + emit roiUpdated(xoffs->value(), yoffs->value(), width->value(), height->value()); + } +} + +void CameraPreview::setSize(int w, int h) { + width->setValue(w); + height->setValue(h); + validate(width, xoffs, 2048); + validate(height, yoffs, 1536); + updateROI(false); +} + +QString CameraPreview::device(){ + return cameraname; } -// FIXME at some point i need to check that xoffset + width must not exceed image width -// FIXME same for y offset and height -// FIXME initialize the cameras ROI CameraPreview::getRoi() { ROI r; @@ -138,14 +192,13 @@ ROI CameraPreview::getRoi() { } CameraPreview::~CameraPreview(){ - std::cerr << "cameraPreview destructor" << std::endl; + qDebug() << "cameraPreview destructor"; if (camera != nullptr){ - std::cerr << "close camera" << std::endl; + qDebug() << "close camera"; // camera->closeCamera(); - std::cerr << "call terminate" << std::endl; - // camera->terminate(); + delete camera; + camera = nullptr; } - delete camera; - std::cerr << "preview: deleted camera" << std::endl; + qDebug() << "preview: deleted camera"; } \ No newline at end of file diff --git a/camerapreview.h b/camerapreview.h index f3e427c..dcc540a 100644 --- a/camerapreview.h +++ b/camerapreview.h @@ -23,28 +23,36 @@ class CameraPreview : public QWidget Q_OBJECT public: - explicit CameraPreview(QString &devicename, QWidget *parent = 0); + explicit CameraPreview(QWidget *parent = 0); ~CameraPreview(); ROI getRoi(); + void updateROI(bool emitSignal=true); + void setSize(int width, int height); + QString device(); public slots: - void updateCamera(QString &device); - void updateROI(QString v); + void setCamera(QString &device); + void updateWidth(QString s); + void updateHeight(QString s); + void updateXoffs(QString s); + void updateYoffs(QString s); -// signals: -// void column_visibility_changed(QString who, QString column, bool state); -// void recent_file_changed(QStringList); +signals: + void roiUpdated(int x, int y, int width, int height); private: QString cameraname; QSpinBox *width, *height, *xoffs, *yoffs; QLabel *imgLabel; + QLabel *label; + QPixmap pm; void takeStill(); void setImage(const QPixmap &img); - // void setImage(const QImage &img); + void validate(QSpinBox *origin, QSpinBox *dest, int limit); + PylonWrapper *camera; }; diff --git a/main.cpp b/main.cpp index 9a7a189..862ec3e 100644 --- a/main.cpp +++ b/main.cpp @@ -42,7 +42,7 @@ int main(int argc, char *argv[]) settings.setValue("app/pos_x", pos.x()); settings.setValue("app/pos_y", pos.y()); qInfo() << "PylonRecorder stop"; - Logger::clean(); + //Logger::clean(); return ret; } diff --git a/notes.md b/notes.md new file mode 100644 index 0000000..c5f6721 --- /dev/null +++ b/notes.md @@ -0,0 +1,14 @@ +# PylonRecorder + +Recorder for up to two Basler cameras. + +## TODOs +* implement grabbing from 2 joined cameras +* set the region of interest +* save properly + +## FIXMEs & improvements + +* make the max image sizes depend on camera + + diff --git a/pylonrecorder.cpp b/pylonrecorder.cpp index 3629a10..1c30811 100644 --- a/pylonrecorder.cpp +++ b/pylonrecorder.cpp @@ -608,7 +608,9 @@ void PylonRecorder::cameraConfiguration(){ void PylonRecorder::camerasetup() { std::cerr << "camera settings accepted" << std::endl; std::cerr << d->result() << std::endl; + std::cerr << "camera settings accepted" << std::endl; CameraLayout l = d->layout(); + std::cerr << "camera settings accepted" << std::endl; delete d; }