Compare commits

..

22 Commits

Author SHA1 Message Date
cd9bbcfa62 [dualcamgrabber] cleanup 2025-03-12 17:32:48 +01:00
0fa532d59a [dualcamgrabber] working with software triggering 2025-03-12 15:26:04 +01:00
4f2d45df6b [dualcomwrapper] enable software triggering 2025-03-12 11:01:56 +01:00
12c2f6292f [recorder] wait for writer to finish before deleting buffer ...
more messaging, use the size-aware Image constructor
2025-03-12 10:00:35 +01:00
6ec776cd4e [campreview] more messaging, respond to camera image sizes 2025-03-12 09:57:29 +01:00
222c3a9ce1 [writer] remove nix outputting, remove support for raw storage 2025-03-12 09:56:32 +01:00
cb1c7772e8 [grabber] remove leftover code, explicitly set the image size 2025-03-12 09:55:45 +01:00
63dbc21df8 [camsetup] better messaging, 2025-03-12 09:54:22 +01:00
6916899620 [wrapper] add sensor Size functions 2025-03-12 09:53:12 +01:00
b221a03d43 [camconfig] more debug messages 2025-03-12 09:50:59 +01:00
f4231e281b [myimage] must be explicitely created with width and height 2025-03-12 08:29:42 +01:00
6ef19c2375 [safety] some try catches at points that sometimes fail 2025-03-10 11:57:41 +01:00
767f8b7e42 roi dimensions must be multiples of four 2024-03-18 11:46:57 +01:00
2bed70b971 remove debug code fix time conversion issue 2024-03-15 10:32:37 +01:00
dadce69944 [dualcam] properly read rois 2024-03-14 15:14:47 +01:00
d78b9d8b02 [recorder] fix missed signal 2024-03-14 15:14:18 +01:00
23b0a9afcd [writer] remove cam number, simplify writing done signal 2024-03-14 15:13:29 +01:00
fe20326953 [qt] remove deprecated pixmap calls 2024-03-14 11:17:44 +01:00
f803854da3 disable mode selection if selection was done 2024-03-13 09:19:23 +01:00
155ac6b471 add user given camera name to configuration 2024-03-13 08:58:45 +01:00
18f088c4fd [camids] add dialog to set camera User specified ids, disabled at the
moment
2024-03-13 08:30:38 +01:00
a3418bc25e cleanup and proper (de)activation of actions 2024-03-12 17:00:01 +01:00
21 changed files with 543 additions and 244 deletions

View File

@@ -43,10 +43,10 @@ include_directories (AFTER ${NIX_INCLUDE_DIR})
# ####################################### # #######################################
# OPENCV # OPENCV
message ("=> finding opencv ...") # message ("=> finding opencv ...")
find_package(OpenCV REQUIRED opencv_highgui opencv_core) # find_package(OpenCV REQUIRED opencv_highgui opencv_core)
include_directories(AFTER ${OpenCV_INCLUDE_DIRS} ) # include_directories(AFTER ${OpenCV_INCLUDE_DIRS} )
set(LINK_LIBS ${LINK_LIBS} ${OpenCV_LIBRARIES}) # set(LINK_LIBS ${LINK_LIBS} ${OpenCV_LIBRARIES})
####################################### #######################################
# Pylon # Pylon
@@ -58,5 +58,5 @@ file (GLOB RECORDER_SOURCES *.cpp)
file (GLOB RECORDER_INCLUDES *.hpp) file (GLOB RECORDER_INCLUDES *.hpp)
add_executable ( recorder ${RECORDER_SOURCES} ${RECORDER_INCLUDES} ${RECORDER_RES_SOURCES} ) add_executable ( recorder ${RECORDER_SOURCES} ${RECORDER_INCLUDES} ${RECORDER_RES_SOURCES} )
target_include_directories ( recorder PUBLIC "${PROJECT_BINARY_DIR}" ) target_include_directories ( recorder PUBLIC "${PROJECT_BINARY_DIR}" )
target_link_libraries ( recorder Qt5::PrintSupport Qt5::Core Qt5::Widgets Qt5::Gui ${NIX_LIBRARIES} pylon::pylon ${OpenCV_LIBRARIES}) target_link_libraries ( recorder Qt5::PrintSupport Qt5::Core Qt5::Widgets Qt5::Gui ${NIX_LIBRARIES} pylon::pylon)
# ${PYLON_LIBRARIES} ${OpenCV_LIBRARIES}) # ${PYLON_LIBRARIES} ${OpenCV_LIBRARIES})

View File

@@ -5,6 +5,7 @@
CamConfigurator::CamConfigurator(Pylon::DeviceInfoList &deviceList, QWidget *parent) : CamConfigurator::CamConfigurator(Pylon::DeviceInfoList &deviceList, QWidget *parent) :
deviceList(deviceList), QDialog(parent), preview(nullptr) { deviceList(deviceList), QDialog(parent), preview(nullptr) {
qDebug() << "CamConfig constructor";
mode_combo = new QComboBox(this); mode_combo = new QComboBox(this);
mode_combo->addItem("camera mode"); mode_combo->addItem("camera mode");
mode_combo->addItem("single camera"); mode_combo->addItem("single camera");
@@ -45,6 +46,7 @@ CamConfigurator::CamConfigurator(Pylon::DeviceInfoList &deviceList, QWidget *par
connect(buttonbox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
vbox->addWidget(buttonbox); vbox->addWidget(buttonbox);
qDebug() << "CamConfig constructor done!";
} }
@@ -71,6 +73,7 @@ CameraSetup* CamConfigurator::stereoCameraView() {
void CamConfigurator::modeChanged(int idx) { void CamConfigurator::modeChanged(int idx) {
qDebug() << "Mode changed!";
stack->setCurrentIndex(0); stack->setCurrentIndex(0);
if (stack->count() > 1 && preview != nullptr) { if (stack->count() > 1 && preview != nullptr) {
qDebug() << "removing previous widget from stack"; qDebug() << "removing previous widget from stack";
@@ -86,6 +89,7 @@ void CamConfigurator::modeChanged(int idx) {
stack->setCurrentIndex(1); stack->setCurrentIndex(1);
QString device = device_combo->currentText(); QString device = device_combo->currentText();
preview->setPrimaryCamera(device); preview->setPrimaryCamera(device);
mode_combo->setEnabled(false);
} else if (idx == 2) { } else if (idx == 2) {
qDebug() << "Mode changed to dual camera mode"; qDebug() << "Mode changed to dual camera mode";
preview = stereoCameraView(); preview = stereoCameraView();
@@ -100,6 +104,7 @@ void CamConfigurator::modeChanged(int idx) {
} }
QString device2 = device_combo->itemText(1 - i); QString device2 = device_combo->itemText(1 - i);
preview->setSecondaryCamera(device2); preview->setSecondaryCamera(device2);
mode_combo->setEnabled(false);
} else { } else {
qDebug() << "Mode changed mode selection"; qDebug() << "Mode changed mode selection";
stack->setCurrentIndex(0); stack->setCurrentIndex(0);
@@ -113,10 +118,11 @@ void CamConfigurator::modeChanged(int idx) {
void CamConfigurator::primaryDeviceChanged(int idx) { void CamConfigurator::primaryDeviceChanged(int idx) {
qDebug() << "Primary device changed!";
if (mode_combo->currentText() == "single camera") { // single camera setting if (mode_combo->currentText() == "single camera") { // single camera setting
QString devicename = device_combo->currentText(); QString devicename = device_combo->currentText();
preview->setPrimaryCamera(devicename); preview->setPrimaryCamera(devicename);
} else { } else if (mode_combo->currentText() == "stereo camera") { // stereo camera setting
preview->switchArrangement(); preview->switchArrangement();
} }
} }

View File

@@ -9,29 +9,33 @@ CameraPreview::CameraPreview(QWidget *parent):cameraname(""), camera(nullptr), Q
this->setLayout(new QVBoxLayout(this)); this->setLayout(new QVBoxLayout(this));
this->layout()->addWidget(label); this->layout()->addWidget(label);
imgLabel = new QLabel(this); imgLabel = new QLabel(this);
imgLabel->setMinimumSize(QSize(1024, 768)); imgLabel->setMinimumSize(QSize(800, 600));
this->layout()->addWidget(imgLabel); this->layout()->addWidget(imgLabel);
QWidget *controls = new QWidget(this); QWidget *controls = new QWidget(this);
width = new QSpinBox(controls); width = new QSpinBox(controls);
width->setMinimum(1); width->setMinimum(32);
width->setMaximum(2048); width->setMaximum(2048);
width->setSingleStep(32);
width->setValue(width->maximum()); width->setValue(width->maximum());
connect(width, SIGNAL(textChanged(QString)), SLOT(updateWidth(QString))); connect(width, SIGNAL(textChanged(QString)), SLOT(updateWidth(QString)));
height = new QSpinBox(controls); height = new QSpinBox(controls);
height->setMinimum(1); height->setSingleStep(32);
height->setMinimum(32);
height->setMaximum(1536); height->setMaximum(1536);
height->setValue(height->maximum()); height->setValue(height->maximum());
connect(height, SIGNAL(textChanged(QString)), SLOT(updateHeight(QString))); connect(height, SIGNAL(textChanged(QString)), SLOT(updateHeight(QString)));
xoffs = new QSpinBox(controls); xoffs = new QSpinBox(controls);
xoffs->setSingleStep(8);
xoffs->setMinimum(0); xoffs->setMinimum(0);
xoffs->setMaximum(2047); xoffs->setMaximum(2047);
xoffs->setValue(0); xoffs->setValue(0);
connect(xoffs, SIGNAL(textChanged(QString)), SLOT(updateXoffs(QString))); connect(xoffs, SIGNAL(textChanged(QString)), SLOT(updateXoffs(QString)));
yoffs = new QSpinBox(controls); yoffs = new QSpinBox(controls);
yoffs->setSingleStep(8);
yoffs->setMinimum(0); yoffs->setMinimum(0);
yoffs->setMaximum(1535); yoffs->setMaximum(1535);
yoffs->setValue(0); yoffs->setValue(0);
@@ -53,15 +57,13 @@ CameraPreview::CameraPreview(QWidget *parent):cameraname(""), camera(nullptr), Q
this->layout()->addWidget(controls); this->layout()->addWidget(controls);
//setPrimaryCamera(devicename); //setPrimaryCamera(devicename);
qDebug() << "Camera preview constructor"; qDebug() << "Camera preview constructor";
takeStill();
} }
void CameraPreview::setCamera(QString &device){ void CameraPreview::setCamera(QString &device){
qDebug() << "update camera! ";// << device.toStdString(); qDebug() << "update camera! " << device;
cameraname = device; cameraname = device;
label->setText(device); if (camera != nullptr) {
if (camera != NULL) {
qDebug() << "camera is not nullptr! "; qDebug() << "camera is not nullptr! ";
delete camera; delete camera;
camera = nullptr; camera = nullptr;
@@ -76,7 +78,28 @@ void CameraPreview::setCamera(QString &device){
QString msg = "<p><b>Could not open camera device!</b><p><p>" + QString::fromStdString(message) + "</p>"; QString msg = "<p><b>Could not open camera device!</b><p><p>" + QString::fromStdString(message) + "</p>";
msgBox.setText(msg); msgBox.setText(msg);
msgBox.exec(); msgBox.exec();
return;
} }
int64_t max_height = camera->sensorHeight();
int64_t max_width = camera->sensorWidth();
std::cerr << "set spin box values " << max_width << " " << max_height << std::endl;
width->blockSignals(true);
height->blockSignals(true);
xoffs->blockSignals(true);
yoffs->blockSignals(true);
width->setMaximum(max_width);
width->setValue(max_width);
height->setMaximum(max_height);
height->setValue(max_height);
xoffs->setMaximum(max_width - 1);
xoffs->setValue(0);
yoffs->setMaximum(max_height - 1);
yoffs->setValue(0);
label->setText(device + " - " + camera->userName());
width->blockSignals(false);
height->blockSignals(false);
xoffs->blockSignals(false);
yoffs->blockSignals(false);
takeStill(); takeStill();
} }
@@ -84,17 +107,19 @@ void CameraPreview::setCamera(QString &device){
void CameraPreview::takeStill() { void CameraPreview::takeStill() {
qDebug() << "Take Still image!"; qDebug() << "Take Still image!";
if (camera != nullptr && camera->isOpen()) { if (camera != nullptr && camera->isOpen()) {
MyImage mimg; ImageSettings s = camera->getImageSettings();
MyImage mimg(s.width, s.height);
bool valid = camera->grabFrame(mimg); bool valid = camera->grabFrame(mimg);
if (!valid) { if (!valid) {
qWarning() << "Grabbing from camera failed!"; qWarning() << "Grabbing from camera failed!";
return; return;
} }
qDebug() << "Grabbed image from camera succeeded!";
QImage img(static_cast<uchar *>(mimg.data()), mimg.width(), mimg.height(), QImage img(static_cast<uchar *>(mimg.data()), mimg.width(), mimg.height(),
QImage::Format::Format_Grayscale8); QImage::Format::Format_Grayscale8);
QPixmap mpm = QPixmap::fromImage(img); QPixmap mpm = QPixmap::fromImage(img);
this->pm = mpm; this->pm = mpm;
mpm = mpm.scaledToWidth(1024); mpm = mpm.scaledToWidth(800);
setImage(mpm); setImage(mpm);
updateROI(); updateROI();
} else { } else {
@@ -110,7 +135,7 @@ void CameraPreview::updateWidth(QString s) {
// if (xoffs->value() + width->value() > 2048) { // if (xoffs->value() + width->value() > 2048) {
// xoffs->setValue(2048 - width->value()); // xoffs->setValue(2048 - width->value());
// } // }
validate(width, xoffs, 2048); validate(width, xoffs, camera->sensorWidth());
updateROI(); updateROI();
} }
@@ -118,7 +143,7 @@ void CameraPreview::updateXoffs(QString s) {
// if (xoffs->value() + width->value() > 2048) { // if (xoffs->value() + width->value() > 2048) {
// width->setValue(2048 - xoffs->value()); // width->setValue(2048 - xoffs->value());
// } // }
validate(xoffs, width, 2048); validate(xoffs, width, camera->sensorHeight());
updateROI(); updateROI();
} }
@@ -126,7 +151,7 @@ void CameraPreview::updateHeight(QString s) {
// if (height->value() + yoffs->value() > 1536) { // if (height->value() + yoffs->value() > 1536) {
// yoffs->setValue(1536 - height->value()); // yoffs->setValue(1536 - height->value());
// } // }
validate(height, yoffs, 1536); validate(height, yoffs, camera->sensorHeight());
updateROI(); updateROI();
} }
@@ -134,20 +159,33 @@ void CameraPreview::updateYoffs(QString s) {
// if (height->value() + yoffs->value() > 1536) { // if (height->value() + yoffs->value() > 1536) {
// height->setValue(1536 - yoffs->value()); // height->setValue(1536 - yoffs->value());
// } // }
validate(yoffs, height, 1536); validate(yoffs, height, camera->sensorWidth());
updateROI(); updateROI();
} }
void CameraPreview::validate(QSpinBox *origin, QSpinBox *dest, int limit){ void CameraPreview::validate(QSpinBox *origin, QSpinBox *dest, int limit){
qDebug() << "validate";
int val = ensureDivbyfour(origin->value());
origin->setValue(val);
if (origin->value() + dest->value() > limit) { if (origin->value() + dest->value() > limit) {
dest->setValue(limit - origin->value()); dest->setValue(limit - origin->value());
} }
qDebug() << "validate done";
}
int CameraPreview::ensureDivbyfour(int val) {
// if (val % 4 != 0) {
// int divisor = floor(val / 4);
// val = divisor * 4;
// }
return val;
} }
void CameraPreview::updateROI(bool emitSignal) { void CameraPreview::updateROI(bool emitSignal) {
qDebug() << "Update roi with signal: " << emitSignal;
QImage img = pm.toImage(); QImage img = pm.toImage();
double scaling = 1024.0 / img.width(); double scaling = 800.0 / img.width();
img = img.scaledToWidth(1024); img = img.scaledToWidth(800);
QPainter qPainter(&img); QPainter qPainter(&img);
qPainter.setBrush(Qt::NoBrush); qPainter.setBrush(Qt::NoBrush);
qPainter.setPen(Qt::red); qPainter.setPen(Qt::red);
@@ -161,20 +199,24 @@ void CameraPreview::updateROI(bool emitSignal) {
int rheight = round(height->value() * scaling); int rheight = round(height->value() * scaling);
qPainter.drawRect(rxoffs, ryoffs, rwidth, rheight); qPainter.drawRect(rxoffs, ryoffs, rwidth, rheight);
bool bEnd = qPainter.end(); bool bEnd = qPainter.end();
QPixmap npm = QPixmap::fromImage(img); QPixmap npm = QPixmap::fromImage(img);
setImage(npm); setImage(npm);
if (emitSignal) { if (emitSignal) {
emit roiUpdated(xoffs->value(), yoffs->value(), width->value(), height->value()); emit roiUpdated(xoffs->value(), yoffs->value(), width->value(), height->value());
} }
qDebug() << "update ROI done";
} }
void CameraPreview::setSize(int w, int h) { void CameraPreview::setSize(int w, int h) {
qDebug() << "set size " << w << " " << h;
width->setValue(w); width->setValue(w);
height->setValue(h); height->setValue(h);
validate(width, xoffs, 2048); if (camera != nullptr && camera->isOpen()) {
validate(height, yoffs, 1536); validate(width, xoffs, camera->sensorWidth());
validate(height, yoffs, camera->sensorHeight());
}
updateROI(false); updateROI(false);
qDebug() << "set size done";
} }
QString CameraPreview::device(){ QString CameraPreview::device(){
@@ -183,12 +225,14 @@ QString CameraPreview::device(){
ROI CameraPreview::getRoi() { ROI CameraPreview::getRoi() {
ROI r; ROI r;
uint32_t max_height = camera->sensorHeight();
uint32_t max_width = camera->sensorWidth();
r.x = xoffs->value(); r.x = xoffs->value();
r.y = yoffs->value(); r.y = yoffs->value();
r.width = width->value(); r.width = width->value();
r.height = height->value(); r.height = height->value();
r.height = r.height > 1536 ? 1536 - r.y : r.height; r.height = r.height > max_height ? max_height - r.y : r.height;
r.width = r.width > 2048 ? 2048 - r.x : r.width; r.width = r.width > max_width ? max_width - r.x : r.width;
return r; return r;
} }

View File

@@ -52,7 +52,7 @@ private:
void takeStill(); void takeStill();
void setImage(const QPixmap &img); void setImage(const QPixmap &img);
void validate(QSpinBox *origin, QSpinBox *dest, int limit); void validate(QSpinBox *origin, QSpinBox *dest, int limit);
int ensureDivbyfour(int value);
PylonWrapper *camera; PylonWrapper *camera;
}; };

View File

@@ -10,6 +10,7 @@ SingleCamera::SingleCamera (QWidget *parent) :
this->layout()->addWidget(camera1Preview); this->layout()->addWidget(camera1Preview);
} }
CameraLayout SingleCamera::cameraLayout(){ CameraLayout SingleCamera::cameraLayout(){
CameraLayout l; CameraLayout l;
qDebug() << "Request layout"; qDebug() << "Request layout";
@@ -20,6 +21,7 @@ CameraLayout SingleCamera::cameraLayout(){
return l; return l;
} }
SingleCamera::~SingleCamera(){ SingleCamera::~SingleCamera(){
if (camera1Preview != nullptr) { if (camera1Preview != nullptr) {
delete camera1Preview; delete camera1Preview;
@@ -33,7 +35,8 @@ DualCamera::DualCamera (QWidget *parent) :
camera1Preview(nullptr), camera1Preview(nullptr),
camera2Preview(nullptr), camera2Preview(nullptr),
primary_device("") { primary_device("") {
qDebug() << "DualCamera View ... "; qDebug() << "DualCamera View constructor... ";
std::cerr << "DualCamera View constructor... " << std::endl;
this->setLayout(new QHBoxLayout(this)); this->setLayout(new QHBoxLayout(this));
camera1Preview = new CameraPreview(); camera1Preview = new CameraPreview();
camera2Preview = new CameraPreview(); camera2Preview = new CameraPreview();
@@ -46,12 +49,18 @@ DualCamera::DualCamera (QWidget *parent) :
void DualCamera::updateROI1(int x, int y, int w, int h) { void DualCamera::updateROI1(int x, int y, int w, int h) {
qDebug() << "Update ROI1: x " << x << " y " << y << " w " << w << " h " << h;
if (camera2Preview != nullptr) {
camera2Preview->setSize(w, h); camera2Preview->setSize(w, h);
} }
}
void DualCamera::updateROI2(int x, int y, int w, int h) { void DualCamera::updateROI2(int x, int y, int w, int h) {
qDebug() << "Update ROI2: x " << x << " y " << y << " w " << w << " h " << h;
if (camera1Preview != nullptr) {
camera1Preview->setSize(w, h); camera1Preview->setSize(w, h);
} }
}
void DualCamera::switchArrangement() { void DualCamera::switchArrangement() {
qDebug() << "switch camera arrangement"; qDebug() << "switch camera arrangement";

View File

@@ -62,7 +62,7 @@ public:
void setPrimaryCamera(QString &device) { void setPrimaryCamera(QString &device) {
qDebug() << "Update primary camera"; qDebug() << "Update primary camera to " << device;
if (camera1Preview != nullptr) { if (camera1Preview != nullptr) {
camera1Preview->setCamera(device); camera1Preview->setCamera(device);
primary_device = device; primary_device = device;
@@ -71,7 +71,7 @@ public:
void setSecondaryCamera(QString &device) { void setSecondaryCamera(QString &device) {
qDebug()<< "Update secondary camera"; qDebug()<< "Update secondary camera to " << device;
if (camera2Preview != nullptr) { if (camera2Preview != nullptr) {
camera2Preview->setCamera(device); camera2Preview->setCamera(device);
} }

48
camids.cpp Normal file
View File

@@ -0,0 +1,48 @@
#include "camids.h"
#include "mylogger.h"
#include "util.h"
CameraID::CameraID(Pylon::DeviceInfoList &deviceList, QWidget *parent) :
deviceList(deviceList), QDialog(parent) {
device_combo = new QComboBox(this);
for (auto d : deviceList) {
device_combo->addItem(QString(d.GetFullName()) + " - " + QString(d.GetUserDefinedName()));
}
connect(device_combo, SIGNAL(currentIndexChanged(int)), SLOT(primaryDeviceChanged(int)));
QWidget *header = new QWidget(this);
QGridLayout *grid = new QGridLayout(header);
grid->addWidget(new QLabel("Camera device:", this), 1, 0);
grid->addWidget(device_combo, 1, 1);
edit = new QLineEdit(this);
grid->addWidget(new QLabel("Camera Id", this), 2, 0);
grid->addWidget(edit, 2, 1);
header->setLayout(grid);
QVBoxLayout *vbox = new QVBoxLayout(this);
vbox->addWidget(header);
buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok
| QDialogButtonBox::Cancel);
connect(buttonbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
vbox->addWidget(buttonbox);
std::cerr <<"ping\n";
}
void CameraID::setID() {
std::cerr << "Set ID!" << std::endl;
}
QString CameraID::newID() {
std::cerr <<"ping\n";
return edit->text();
}
int CameraID::cameraIndex() {
std::cerr <<"ping\n";
return device_combo->currentIndex();
}

45
camids.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef CAMIDS_H
#define CAMIDS_H
#include <QDialog>
#include <QComboBox>
#include <QLabel>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QLineEdit>
#include <QDialogButtonBox>
#include <pylon/PylonIncludes.h>
#include "mylogger.h"
namespace Ui {
class CameraID;
}
class CameraID : public QDialog
{
Q_OBJECT
public:
explicit CameraID(Pylon::DeviceInfoList_t &deviceList, QWidget *parent = 0);
// ~CameraID(){};
QString newID();
int cameraIndex();
public slots:
void setID();
// signals:
// void column_visibility_changed(QString who, QString column, bool state);
// void recent_file_changed(QStringList);
private:
Pylon::DeviceInfoList_t deviceList;
QComboBox *device_combo;
QLineEdit *edit;
QDialogButtonBox *buttonbox;
};
#endif // CAMIDS_H

View File

@@ -2,42 +2,84 @@
#include <iostream> #include <iostream>
#include <pylon/PylonIncludes.h> #include <pylon/PylonIncludes.h>
#include <stitchimage.h> #include <stitchimage.h>
#include <chrono>
using namespace std::chrono;
typedef high_resolution_clock Time;
typedef milliseconds ms;
typedef duration<float> fsec;
void DualcamGrabber::run() { void DualcamGrabber::run() {
stop_request = false; stop_request = false;
size_t counter = 0; size_t counter = 0;
if (wrapper->isOpen()) { if (!wrapper->isOpen()) {
return;
}
Pylon::CInstantCameraArray &cameras = wrapper->getCameraArray(); Pylon::CInstantCameraArray &cameras = wrapper->getCameraArray();
wrapper->frameRate(static_cast<uint>(framerate)); wrapper->frameRate(static_cast<uint>(100), -1);
wrapper->exposureTime(exposure); wrapper->exposureTime(exposure);
wrapper->gain(gain); wrapper->gain(gain);
wrapper->enableSoftwareTrigger(0);
wrapper->enableSoftwareTrigger(1);
cameras.StartGrabbing(); cameras.StartGrabbing();
Pylon::CGrabResultPtr frame0, frame1; Pylon::CGrabResultPtr frame0, frame1;
Pylon::CPylonImage leftImage; Pylon::CPylonImage leftImage;
Pylon::CPylonImage rightImage; Pylon::CPylonImage rightImage;
Pylon::CPylonImage stitchedImage; Pylon::CPylonImage stitchedImage;
std::string errorMessage = ""; std::string errorMessage = "";
bool failure = false;
while (cameras.IsGrabbing() && !stop_request) { auto before = high_resolution_clock::now();
MyImage *img = new MyImage(); auto done = high_resolution_clock::now();
auto total_duration = duration_cast<microseconds>(done - before);
int expected_usecs = (int)(1./framerate * 1000000);
while (cameras.IsGrabbing() && !stop_request && !failure) {
if (counter > 0) {
long delay = total_duration.count() - expected_usecs;
if (delay > 0) {
emit delayed(delay, counter-1);
} else {
usleep(-delay);
}
}
before = high_resolution_clock::now();
if (cameras[0].WaitForFrameTriggerReady(1000, Pylon::TimeoutHandling_ThrowException) &&
cameras[1].WaitForFrameTriggerReady(1000, Pylon::TimeoutHandling_ThrowException)) {
// std::cerr << "executing software triggers" << std::endl;
cameras[0].ExecuteSoftwareTrigger();
cameras[1].ExecuteSoftwareTrigger();
}
try {
cameras[0].RetrieveResult( 5000, frame0, Pylon::TimeoutHandling_ThrowException ); cameras[0].RetrieveResult( 5000, frame0, Pylon::TimeoutHandling_ThrowException );
cameras[1].RetrieveResult( 5000, frame1, Pylon::TimeoutHandling_ThrowException ); cameras[1].RetrieveResult( 5000, frame1, Pylon::TimeoutHandling_ThrowException );
leftImage.AttachGrabResultBuffer( frame0 ); leftImage.AttachGrabResultBuffer( frame0 );
rightImage.AttachGrabResultBuffer( frame1 ); rightImage.AttachGrabResultBuffer( frame1 );
} catch( const Pylon::GenericException &e ) {
qDebug() << "Grabbing frame failed! " << e.what();
failure = true;
}
if (leftImage.IsValid() && rightImage.IsValid()) { if (!failure && leftImage.IsValid() && rightImage.IsValid()) {
try { try {
StitchImage::StitchToRight(leftImage, rightImage, &stitchedImage, errorMessage); StitchImage::StitchToRight(leftImage, rightImage, &stitchedImage, errorMessage);
MyImage *img = new MyImage(stitchedImage.GetWidth(), stitchedImage.GetHeight());
img->setFrame(stitchedImage); img->setFrame(stitchedImage);
buffer->push(img); buffer->push(img);
} catch(const std::exception& e) { } catch(const std::exception& e) {
std::cerr << e.what() << '\n'; std::cerr << e.what() << '\n';
} }
} }
counter += 1; counter += 1;
done = high_resolution_clock::now();
total_duration = duration_cast<microseconds>(done - before);
} }
cameras.StopGrabbing(); cameras.StopGrabbing();
} }
}

View File

@@ -53,6 +53,7 @@ public slots:
signals: signals:
void terminated(); void terminated();
void delayed(int, int);
}; };
#endif // DUALCAMGRABBER_H #endif // DUALCAMGRABBER_H

View File

@@ -49,13 +49,14 @@ double DualcamWrapper::maxFrameRate(int camindex) {
bool DualcamWrapper::frameRate(uint new_framerate, int camindex) { bool DualcamWrapper::frameRate(uint new_framerate, int camindex) {
qDebug() << "Setting FrameRate to " << new_framerate << " for camera " << camindex;
if (valid) { if (valid) {
if (camindex == -1) { if (camindex == -1) {
frameRate(new_framerate, 0); frameRate(new_framerate, 0);
frameRate(new_framerate, 1); frameRate(new_framerate, 1);
return true; return true;
} else if (camindex == 0 && camindex ==1) { } else if (camindex >= 0 && camindex < 2) {
GenApi::INodeMap& nodemap = getNodemap(0); GenApi::INodeMap& nodemap = getNodemap(camindex);
GenApi::INode* n = nodemap.GetNode( "AcquisitionFrameRateEnable" ); GenApi::INode* n = nodemap.GetNode( "AcquisitionFrameRateEnable" );
Pylon::CBooleanParameter enableframerate(n); Pylon::CBooleanParameter enableframerate(n);
enableframerate.SetValue(true); enableframerate.SetValue(true);
@@ -72,7 +73,8 @@ bool DualcamWrapper::frameRate(uint new_framerate, int camindex) {
double DualcamWrapper::frameRate(int camindex) { double DualcamWrapper::frameRate(int camindex) {
assert(camindex > 0 && camindex < 2); qDebug() << "Reading FrameRate from camera " << camindex;
assert(camindex >= 0 && camindex < 2);
double rate = -1.; double rate = -1.;
if (valid) { if (valid) {
GenApi::INodeMap& nodemap = getNodemap(camindex); GenApi::INodeMap& nodemap = getNodemap(camindex);
@@ -85,6 +87,7 @@ double DualcamWrapper::frameRate(int camindex) {
double DualcamWrapper::exposureTime(int camindex) { double DualcamWrapper::exposureTime(int camindex) {
qDebug() << "Reading ExposureTime from camera " << camindex;
assert(camindex > 0 && camindex < 2); assert(camindex > 0 && camindex < 2);
double time = -1.; double time = -1.;
if (valid) { if (valid) {
@@ -98,28 +101,53 @@ double DualcamWrapper::exposureTime(int camindex) {
bool DualcamWrapper::exposureTime(double exposure_time, int camindex) { bool DualcamWrapper::exposureTime(double exposure_time, int camindex) {
qDebug() << "Setting exposure time to " << exposure_time << " for camera " << camindex;
if (valid) { if (valid) {
if (camindex == -1) { if (camindex == -1) {
exposureTime(exposure_time, 0); exposureTime(exposure_time, 0);
exposureTime(exposure_time, 1); exposureTime(exposure_time, 1);
} else { } else {
GenApi::INodeMap& nodemap = getNodemap(camindex);
double d = GenApi::CFloatPtr(nodemap.GetNode("ExposureTime"))->GetValue();
GenApi::INode* n = nodemap.GetNode( "ExposureTime" );
try { try {
GenApi::CEnumerationPtr(nodemap.GetNode( "ExposureTimeMode" ))->FromString("Standard"); GenApi::INodeMap& nodemap = getNodemap(camindex);
} catch (...) { GenApi::INode* n = nodemap.GetNode( "ExposureTime" );
qWarning() << "Could not set exposure for cam0";
}
Pylon::CFloatParameter exp_time( n ); Pylon::CFloatParameter exp_time( n );
exp_time.SetValue( exposure_time ); exp_time.SetValue( exposure_time );
GenApi::CEnumerationPtr(nodemap.GetNode( "ExposureTimeMode" ))->FromString("Timed");;
} catch (...) {
qWarning() << "Could not set exposure for cam " << camindex;
}
} }
} }
return false; return false;
} }
uint32_t DualcamWrapper::sensorWidth(int camindex) {
qDebug() << "Reading SensorWidth from camera " << camindex;
assert(camindex >= 0 && camindex < 2);
uint32_t width = -1;
if (valid) {
GenApi::INodeMap &nodemap = getNodemap(camindex);
Pylon::CIntegerParameter pwidth( nodemap, "SensorWidth" );
width = (uint32_t)pwidth.GetValue();
}
return width;
}
uint32_t DualcamWrapper::sensorHeight(int camindex) {
qDebug() << "Reading SensorHeight from camera " << camindex;
assert(camindex >= 0 && camindex < 2);
uint32_t height = -1;
if (valid) {
GenApi::INodeMap &nodemap = getNodemap(camindex);
Pylon::CIntegerParameter pheight( nodemap, "SensorHeight" );
height = (uint32_t)pheight.GetValue();
}
return height;
}
double DualcamWrapper::gain(int camindex) { double DualcamWrapper::gain(int camindex) {
qDebug() << "Reading Gain from camera " << camindex;
assert(camindex >= 0 && camindex < 2); assert(camindex >= 0 && camindex < 2);
double gain = -1.; double gain = -1.;
if (valid) { if (valid) {
@@ -173,14 +201,14 @@ bool DualcamWrapper::grabFrame(MyImage &img, int camindex) {
qDebug() << "grabFrame from camera " << camindex; qDebug() << "grabFrame from camera " << camindex;
if (valid) { if (valid) {
GenApi::INodeMap &nodemap = getNodemap(camindex); GenApi::INodeMap &nodemap = getNodemap(camindex);
qDebug() << "Setting width" << layout.rois[0].width; qDebug() << "Setting width" << layout.rois[camindex].width;
Pylon::CIntegerParameter(nodemap, "Width").SetValue(layout.rois[0].width); Pylon::CIntegerParameter(nodemap, "Width").SetValue(layout.rois[camindex].width);
qDebug() << "Setting height" << layout.rois[0].height; qDebug() << "Setting height" << layout.rois[0].height;
Pylon::CIntegerParameter(nodemap, "Height").SetValue(layout.rois[0].height); Pylon::CIntegerParameter(nodemap, "Height").SetValue(layout.rois[camindex].height);
qDebug() << "Setting xoffset" << layout.rois[0].x; qDebug() << "Setting xoffset" << layout.rois[camindex].x;
Pylon::CIntegerParameter(nodemap, "OffsetX").SetValue(layout.rois[0].x); Pylon::CIntegerParameter(nodemap, "OffsetX").SetValue(layout.rois[camindex].x);
qDebug() << "Setting yoffset" << layout.rois[0].y; qDebug() << "Setting yoffset" << layout.rois[camindex].y;
Pylon::CIntegerParameter(nodemap, "OffsetY").SetValue(layout.rois[0].y); Pylon::CIntegerParameter(nodemap, "OffsetY").SetValue(layout.rois[camindex].y);
camera->StartGrabbing(); camera->StartGrabbing();
camera->RetrieveResult( 5000, frame, Pylon::TimeoutHandling_ThrowException); camera->RetrieveResult( 5000, frame, Pylon::TimeoutHandling_ThrowException);
@@ -191,16 +219,30 @@ bool DualcamWrapper::grabFrame(MyImage &img, int camindex) {
} }
void DualcamWrapper::setROI() {
for (int camindex = 0; camindex < 2; camindex++){
qDebug() << "Setting ROI: w" << layout.rois[camindex].width << " h: "<< layout.rois[camindex].height << " x " << layout.rois[camindex].x << " y " << layout.rois[camindex].y;
try {
GenApi::INodeMap &nodemap = getNodemap(camindex);
Pylon::CIntegerParameter(nodemap, "Width").SetValue(layout.rois[camindex].width);
Pylon::CIntegerParameter(nodemap, "Height").SetValue(layout.rois[camindex].height);
Pylon::CIntegerParameter(nodemap, "OffsetX").SetValue(layout.rois[camindex].x);
Pylon::CIntegerParameter(nodemap, "OffsetY").SetValue(layout.rois[camindex].y);
} catch (const Pylon::GenericException &e) {
std::cerr << e.GetDescription() << std::endl;
}
}
}
void DualcamWrapper::resetCamera(int camindex) { void DualcamWrapper::resetCamera(int camindex) {
GenApi::INodeMap &nodemap = getNodemap( camindex ); GenApi::INodeMap &nodemap = getNodemap( camindex );
int64_t dfltWidth = 2048; uint32_t width = sensorWidth(camindex);
int64_t dfltHeight = 1536; uint32_t height = sensorHeight(camindex);
qDebug() << "resetting camera to default ROI (" << dfltWidth << ", " << dfltHeight << ")"; qDebug() << "resetting camera to default ROI (" << width << ", " << height << ")";
try { try {
// std::cerr << "MaxWidth: " << Pylon::CIntegerParameter(nodemap, "WidthMax").GetValue() << std::endl; Pylon::CIntegerParameter(nodemap, "Width").SetValue(width, false);
Pylon::CIntegerParameter(nodemap, "Width").SetValue(dfltWidth, false); Pylon::CIntegerParameter(nodemap, "Height").SetValue(height, false);
// std::cerr << "MaxHeight: " << Pylon::CIntegerParameter(nodemap, "HeightMax").GetValue() << std::endl;
Pylon::CIntegerParameter(nodemap, "Height").SetValue(dfltHeight, false);
Pylon::CIntegerParameter(nodemap, "OffsetX").SetValue(0); Pylon::CIntegerParameter(nodemap, "OffsetX").SetValue(0);
Pylon::CIntegerParameter(nodemap, "OffsetY").SetValue(0); Pylon::CIntegerParameter(nodemap, "OffsetY").SetValue(0);
} catch (const Pylon::GenericException &e) { } catch (const Pylon::GenericException &e) {
@@ -229,8 +271,9 @@ bool DualcamWrapper::openCameras(std::string &message) {
valid = false; valid = false;
return valid; return valid;
} }
resetCamera(0); // resetCamera(0);
resetCamera(1); // resetCamera(1);
setROI();
return valid; return valid;
} }
@@ -259,3 +302,23 @@ GenApi::INodeMap& DualcamWrapper::getNodemap(int camindex){
GenApi::INodeMap &nodemap = cameras[camindex].GetNodeMap(); GenApi::INodeMap &nodemap = cameras[camindex].GetNodeMap();
return nodemap; return nodemap;
} }
void DualcamWrapper::enableSoftwareTrigger(int camindex){
qDebug() << "Enabling software trigger for camera " << camindex;
GenApi::INodeMap &nodemap = getNodemap( camindex );
Pylon::CEnumParameter(nodemap, "TriggerMode").SetValue("On");
Pylon::CEnumParameter(nodemap, "TriggerSource").SetValue("Software");
// Pylon::CEnumParameter(nodemap, "TriggerActivation").SetValue("LevelHigh");
}
void DualcamWrapper::disableSoftwareTrigger(int camindex){
qDebug() << "Disabling software trigger for camera " << camindex;
GenApi::INodeMap& nodemap = getNodemap(camindex);
Pylon::CEnumParameter(nodemap, "TriggerMode").SetValue("Off");
}
bool DualcamWrapper::softwareTriggerEnabeled(int camindex){
qDebug() << "Checking software trigger for camera " << camindex;
GenApi::INodeMap& nodemap = getNodemap(camindex);
return Pylon::CEnumParameter(nodemap, "TriggerMode").GetValue() == "On";
}

View File

@@ -15,8 +15,9 @@ public:
DualcamWrapper(const CameraLayout &layout); DualcamWrapper(const CameraLayout &layout);
~DualcamWrapper(); ~DualcamWrapper();
ImageSettings getImageSettings(int camindex); ImageSettings getImageSettings(int camindex);
uint32_t sensorWidth(int camindex);
uint32_t sensorHeight(int camindex);
bool isOpen(); bool isOpen();
void terminate(); void terminate();
bool openCameras(std::string &message); bool openCameras(std::string &message);
@@ -29,12 +30,16 @@ public:
bool exposureTime(double exposure_time, int camindex=-1); bool exposureTime(double exposure_time, int camindex=-1);
double gain(int camindex); double gain(int camindex);
bool gain(double gain_db, int camindex=-1); bool gain(double gain_db, int camindex=-1);
void enableSoftwareTrigger(int camindex);
void disableSoftwareTrigger(int camindex);
bool softwareTriggerEnabeled(int camindex);
Pylon::CInstantCameraArray &getCameraArray(); Pylon::CInstantCameraArray &getCameraArray();
private: private:
void resetCamera(int camindex); void resetCamera(int camindex);
Pylon::CInstantCameraArray cameras; Pylon::CInstantCameraArray cameras;
GenApi::INodeMap& getNodemap(int camindex); GenApi::INodeMap& getNodemap(int camindex);
void setROI();
bool valid, withLayout; bool valid, withLayout;
CameraLayout layout; CameraLayout layout;

View File

@@ -9,11 +9,12 @@ void Grabber::run() {
camera->frameRate(static_cast<uint>(framerate)); camera->frameRate(static_cast<uint>(framerate));
camera->exposureTime(exposure); camera->exposureTime(exposure);
camera->gain(gain); camera->gain(gain);
ImageSettings settings = camera->getImageSettings();
Pylon::CInstantCamera *cam = camera->getCamera(); Pylon::CInstantCamera *cam = camera->getCamera();
Pylon::CGrabResultPtr frame; Pylon::CGrabResultPtr frame;
cam->StartGrabbing(); cam->StartGrabbing();
while (camera->isOpen() && !stop_request) { while (camera->isOpen() && !stop_request) {
MyImage *img = new MyImage(); MyImage *img = new MyImage(settings.width, settings.height);
cam->RetrieveResult( 5000, frame, Pylon::TimeoutHandling_ThrowException); cam->RetrieveResult( 5000, frame, Pylon::TimeoutHandling_ThrowException);
img->setFrame(frame); img->setFrame(frame);
buffer->push(img); buffer->push(img);

View File

@@ -1,20 +1,28 @@
#include "myimage.h" #include "myimage.h"
#include <chrono> #include <chrono>
#include "mylogger.h"
MyImage::MyImage() MyImage::MyImage(uint32_t width, uint32_t height): img_width(width), img_height(height)
{} {
buffer = new char[width * height];
}
MyImage::MyImage(Pylon::CGrabResultPtr ptr) { MyImage::MyImage(Pylon::CGrabResultPtr ptr) {
setFrame(ptr); setFrame(ptr);
} }
MyImage::~MyImage() {
delete[] buffer;
}
bool MyImage::setFrame(Pylon::CGrabResultPtr ptr) { bool MyImage::setFrame(Pylon::CGrabResultPtr ptr) {
qDebug() << "Setting frame from pointer";
bool valid = ptr.IsValid() && ptr->GetWidth() <= max_width && ptr->GetHeight() <= max_height; bool valid = ptr.IsValid() && ptr->GetWidth() <= max_width && ptr->GetHeight() <= max_height;
if (valid) { if (valid) {
img_index = ptr->GetID(); img_index = ptr->GetID();
img_width = ptr->GetWidth(); img_width = ptr->GetWidth();
img_height = ptr->GetHeight(); img_height = ptr->GetHeight();
memcpy(&buffer, ptr->GetBuffer(), ptr->GetImageSize()); memcpy(buffer, ptr->GetBuffer(), ptr->GetImageSize());
auto t = std::chrono::system_clock::now(); auto t = std::chrono::system_clock::now();
img_timestamp = std::chrono::system_clock::to_time_t(t); img_timestamp = std::chrono::system_clock::to_time_t(t);
} }
@@ -22,11 +30,14 @@ bool MyImage::setFrame(Pylon::CGrabResultPtr ptr) {
} }
bool MyImage::setFrame( Pylon::CPylonImage &img) { bool MyImage::setFrame( Pylon::CPylonImage &img) {
qDebug() << "Setting frame from Pylon image (" << img.GetWidth() << "x" << img.GetHeight() << ")";
bool valid = img.IsValid() && img.GetWidth() <= max_width && img.GetHeight() <= max_height; bool valid = img.IsValid() && img.GetWidth() <= max_width && img.GetHeight() <= max_height;
if (valid) { if (valid) {
img_width = img.GetWidth(); img_width = img.GetWidth();
img_height = img.GetHeight(); img_height = img.GetHeight();
memcpy(&buffer, img.GetBuffer(), img.GetImageSize()); memcpy(buffer, img.GetBuffer(), img.GetImageSize());
auto t = std::chrono::system_clock::now();
img_timestamp = std::chrono::system_clock::to_time_t(t);
} }
return valid; return valid;
} }
@@ -48,7 +59,7 @@ int64_t MyImage::index() {
} }
void *MyImage::data() { void *MyImage::data() {
return &buffer; return buffer;
} }
time_t MyImage::timestamp() { time_t MyImage::timestamp() {

View File

@@ -6,8 +6,9 @@
class MyImage class MyImage
{ {
public: public:
MyImage(); MyImage(uint32_t width, uint32_t height);
MyImage(Pylon::CGrabResultPtr ptr); MyImage(Pylon::CGrabResultPtr ptr);
~MyImage();
int width(); int width();
int height(); int height();
@@ -23,9 +24,9 @@ private:
uint32_t img_height = 0; uint32_t img_height = 0;
int64_t img_index = 0; int64_t img_index = 0;
time_t img_timestamp; time_t img_timestamp;
static const int max_width = 4096; static const int max_width = 5184;
static const int max_height = 1536; static const int max_height = 2048;
char buffer[max_width * max_height]; char *buffer; //[max_width * max_height];
}; };
#endif // MYIMAGE_H #endif // MYIMAGE_H

View File

@@ -61,8 +61,8 @@ PylonRecorder::PylonRecorder(QWidget *parent)
QPalette progressPalette = pressureBar->palette(); QPalette progressPalette = pressureBar->palette();
progressPalette.setBrush(QPalette::Highlight, QBrush(color)); progressPalette.setBrush(QPalette::Highlight, QBrush(color));
pressureBar->setPalette(progressPalette); pressureBar->setPalette(progressPalette);
QLabel *preassureLabel = new QLabel("Buffer preassure:", this); QLabel *pressureLabel = new QLabel("Buffer pressure:", this);
preassureLabel->setStyleSheet("QLabel{font-size: 11pt;font-family: Arial;font-weight: Bold}"); pressureLabel->setStyleSheet("QLabel{font-size: 11pt;font-family: Arial;font-weight: Bold}");
loadBar = new QProgressBar(this); loadBar = new QProgressBar(this);
loadBar->setRange(0, defaultBufferSize); loadBar->setRange(0, defaultBufferSize);
loadBar->setFixedSize(200, 25); loadBar->setFixedSize(200, 25);
@@ -87,9 +87,10 @@ PylonRecorder::PylonRecorder(QWidget *parent)
statusHeader->setStyleSheet("QLabel{font-size: 11pt;font-family: Arial; font-weight: Bold}"); statusHeader->setStyleSheet("QLabel{font-size: 11pt;font-family: Arial; font-weight: Bold}");
QLabel *fileHeader = new QLabel("Output file:"); QLabel *fileHeader = new QLabel("Output file:");
fileHeader->setStyleSheet("QLabel{font-size: 11pt;font-family: Arial; font-weight: Bold}"); fileHeader->setStyleSheet("QLabel{font-size: 11pt;font-family: Arial; font-weight: Bold}");
statusBar()->addWidget(camHeader); statusBar()->addWidget(camHeader);
statusBar()->addWidget(cameraConnectedLabel); statusBar()->addWidget(cameraConnectedLabel);
statusBar()->addWidget(preassureLabel); statusBar()->addWidget(pressureLabel);
statusBar()->addWidget(pressureBar); statusBar()->addWidget(pressureBar);
statusBar()->addWidget(loadLabel); statusBar()->addWidget(loadLabel);
statusBar()->addWidget(loadBar); statusBar()->addWidget(loadBar);
@@ -98,6 +99,7 @@ PylonRecorder::PylonRecorder(QWidget *parent)
statusBar()->addWidget(writingLabel); statusBar()->addWidget(writingLabel);
statusBar()->addWidget(fileHeader); statusBar()->addWidget(fileHeader);
statusBar()->addWidget(fileLabel); statusBar()->addWidget(fileLabel);
resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5); resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
detectCameras(); detectCameras();
createActions(); createActions();
@@ -206,6 +208,7 @@ bool PylonRecorder::loadFile(const QString &fileName) {
void PylonRecorder::setImage(const QImage &newImage) { void PylonRecorder::setImage(const QImage &newImage) {
qDebug() << "Setting image";
//FIXME figure out how to display both images. extract to extra class... //FIXME figure out how to display both images. extract to extra class...
image = newImage; image = newImage;
// (image.colorSpace().isValid()) // (image.colorSpace().isValid())
@@ -223,6 +226,7 @@ void PylonRecorder::setImage(const QImage &newImage) {
applyScaling(); applyScaling();
} }
this->update(); this->update();
qDebug() << "Setting image done";
} }
@@ -280,8 +284,8 @@ void PylonRecorder::saveAs() {
void PylonRecorder::print() { void PylonRecorder::print() {
QPixmap map = imageLabel->pixmap(Qt::ReturnByValue); const QPixmap *map = imageLabel->pixmap();
Q_ASSERT(!map.isNull()); Q_ASSERT(!map->isNull());
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog) #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
QPrintDialog dialog(&printer, this); QPrintDialog dialog(&printer, this);
@@ -289,11 +293,11 @@ void PylonRecorder::print() {
if (dialog.exec()) { if (dialog.exec()) {
QPainter painter(&printer); QPainter painter(&printer);
QRect rect = painter.viewport(); QRect rect = painter.viewport();
QSize size = map.size(); QSize size = map->size();
size.scale(rect.size(), Qt::KeepAspectRatio); size.scale(rect.size(), Qt::KeepAspectRatio);
painter.setViewport(rect.x(), rect.y(), size.width(), size.height()); painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
painter.setWindow(map.rect()); painter.setWindow(map->rect());
painter.drawPixmap(0, 0, map); painter.drawPixmap(0, 0, *map);
} }
#endif #endif
} }
@@ -434,6 +438,7 @@ void PylonRecorder::createActions() {
connect_camera_action->setStatusTip(tr("Connect to to camera and open device")); connect_camera_action->setStatusTip(tr("Connect to to camera and open device"));
disconnect_camera_action = camera_menu->addAction(disconnect_icon, tr("&disconnect"), this, &PylonRecorder::disconnectCamera); disconnect_camera_action = camera_menu->addAction(disconnect_icon, tr("&disconnect"), this, &PylonRecorder::disconnectCamera);
disconnect_camera_action->setStatusTip(tr("Disconnect from the camera device")); disconnect_camera_action->setStatusTip(tr("Disconnect from the camera device"));
disconnect_camera_action->setEnabled(false);
camera_menu->addSeparator(); camera_menu->addSeparator();
grab_still_action = camera_menu->addAction(snapshot_icon, tr("&grab still"), this, &PylonRecorder::grabStillFromPylon); grab_still_action = camera_menu->addAction(snapshot_icon, tr("&grab still"), this, &PylonRecorder::grabStillFromPylon);
grab_still_action->setStatusTip(tr("Grab single image from Pylon camera")); grab_still_action->setStatusTip(tr("Grab single image from Pylon camera"));
@@ -442,6 +447,9 @@ void PylonRecorder::createActions() {
grab_continuous_action->setShortcut(tr("Ctrl+Enter")); grab_continuous_action->setShortcut(tr("Ctrl+Enter"));
grab_stop_action = camera_menu->addAction(stop_icon, tr("&stop grabbing"), this, &PylonRecorder::stopRecording); grab_stop_action = camera_menu->addAction(stop_icon, tr("&stop grabbing"), this, &PylonRecorder::stopRecording);
grab_stop_action->setShortcut(tr("Ctrl+Shift+Enter")); grab_stop_action->setShortcut(tr("Ctrl+Shift+Enter"));
set_cam_identifier_action = camera_menu->addAction(tr("set identifier"), this, &PylonRecorder::setCameraIDs);
set_cam_identifier_action->setStatusTip(tr("Set human readable camera identifier or easier recognition."));
set_cam_identifier_action->setToolTip(tr("Set human readable camera identifier or easier recognition."));
selectStorageAction = new QAction(tr("storage location"), this); selectStorageAction = new QAction(tr("storage location"), this);
selectStorageAction->setStatusTip(tr("Select a storage location for the recorded videos")); selectStorageAction->setStatusTip(tr("Select a storage location for the recorded videos"));
@@ -534,20 +542,42 @@ void PylonRecorder::updateActions() {
zoomInAct->setEnabled(!fitToWindowAct->isChecked()); zoomInAct->setEnabled(!fitToWindowAct->isChecked());
zoomOutAct->setEnabled(!fitToWindowAct->isChecked()); zoomOutAct->setEnabled(!fitToWindowAct->isChecked());
normalSizeAct->setEnabled(!fitToWindowAct->isChecked()); normalSizeAct->setEnabled(!fitToWindowAct->isChecked());
disconnect_camera_action->setEnabled(deviceList.size() > 0); disconnect_camera_action->setEnabled(cameraOpened);
connect_camera_action->setEnabled(true); connect_camera_action->setEnabled(true);
grab_still_action->setEnabled(deviceList.size() > 0); grab_still_action->setEnabled(cameraOpened);
grab_continuous_action->setEnabled(cameraOpened && !grabbing); grab_continuous_action->setEnabled(cameraOpened && !grabbing);
// grab_continuous_action->setEnabled(!grabbing);
grab_stop_action->setEnabled(grabbing); grab_stop_action->setEnabled(grabbing);
set_cam_identifier_action->setEnabled(false);
} }
void PylonRecorder::setCameraIDs() {
if (deviceList.size() == 0) {
QMessageBox msgBox;
QString msg = "<p><b>No camera device found!</b></p><br><p>Connect camera and try again!</p>";
msgBox.setText(msg);
msgBox.exec();
qWarning() << msg.toStdString().c_str();
return;
}
cameraIdDialog = new CameraID(deviceList, this);
connect(cameraConfigDialog, SIGNAL(accepted()), SLOT(cameraIDAccepted()));
std::cerr <<"ping\n";
cameraIdDialog->exec();
}
void PylonRecorder::cameraIDAccepted() {
QString newid = cameraIdDialog->newID();
int deviceindex = cameraIdDialog->cameraIndex();
std::cerr << "New camera id " << newid.toStdString() << " index: " << deviceindex << std::endl;
delete(cameraIdDialog);
}
void PylonRecorder::scaleImage(double factor) { void PylonRecorder::scaleImage(double factor) {
QPixmap map = imageLabel->pixmap(Qt::ReturnByValue); const QPixmap *map = imageLabel->pixmap();
Q_ASSERT(!map.isNull()); Q_ASSERT(!map->isNull());
scaleFactor *= factor; scaleFactor *= factor;
imageLabel->resize(scaleFactor * map.size()); imageLabel->resize(scaleFactor * map->size());
adjustScrollBar(scrollArea->horizontalScrollBar(), factor); adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
adjustScrollBar(scrollArea->verticalScrollBar(), factor); adjustScrollBar(scrollArea->verticalScrollBar(), factor);
@@ -558,7 +588,7 @@ void PylonRecorder::scaleImage(double factor) {
void PylonRecorder::applyScaling(){ void PylonRecorder::applyScaling(){
imageLabel->resize(scaleFactor * imageLabel->pixmap(Qt::ReturnByValue).size()); imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());
} }
@@ -582,31 +612,33 @@ void PylonRecorder::adjustScrollBar(QScrollBar *scrollBar, double factor) {
void PylonRecorder::cameraConfiguration(){ void PylonRecorder::cameraConfiguration(){
d = new CamConfigurator(deviceList, this); qDebug() << "Configuring camera(s)";
connect(d, SIGNAL(accepted()), SLOT(cameraConfigurationAccepted())); cameraConfigDialog = new CamConfigurator(deviceList, this);
connect(d, SIGNAL(rejected()), SLOT(cameraConfigurationAborted())); connect(cameraConfigDialog, SIGNAL(accepted()), SLOT(cameraConfigurationAccepted()));
connect(cameraConfigDialog, SIGNAL(rejected()), SLOT(cameraConfigurationAborted()));
// QObject::connect(&d, SIGNAL(column_visibility_changed(QString, QString,bool)), this, SLOT(visible_columns_update(QString, QString,bool))); // QObject::connect(&d, SIGNAL(column_visibility_changed(QString, QString,bool)), this, SLOT(visible_columns_update(QString, QString,bool)));
d->exec(); cameraConfigDialog->exec();
} }
void PylonRecorder::cameraConfigurationAccepted() { void PylonRecorder::cameraConfigurationAccepted() {
qDebug() << "Cameras setting " << ((d->result()) ? "Accepted" : "Discarded"); qDebug() << "Camera configuration " << ((cameraConfigDialog->result()) ? "Accepted" : "Discarded");
this->layout = d->layout(); this->layout = cameraConfigDialog->layout();
camsconfigured = true; camsconfigured = true;
delete d; delete cameraConfigDialog;
} }
void PylonRecorder::cameraConfigurationAborted() { void PylonRecorder::cameraConfigurationAborted() {
qDebug() << "Camera configuration aborted!"; qDebug() << "Camera configuration aborted!";
camsconfigured = false; camsconfigured = false;
delete cameraConfigDialog;
} }
void PylonRecorder::connectCamera() { void PylonRecorder::connectCamera() {
this->layout = CameraLayout();
qDebug() << "connecting camera(s)"; qDebug() << "connecting camera(s)";
this->layout = CameraLayout();
if (deviceList.size() == 0) { if (deviceList.size() == 0) {
detectCameras(); detectCameras();
QMessageBox msgBox; QMessageBox msgBox;
@@ -621,6 +653,8 @@ void PylonRecorder::connectCamera() {
qDebug() << "cameras have not been properly configured!"; qDebug() << "cameras have not been properly configured!";
return; return;
} }
//Single Camera mode
if (layout.mode == CameraMode::single && layout.devices.size() == 1) { if (layout.mode == CameraMode::single && layout.devices.size() == 1) {
qDebug() << "single camera mode"; qDebug() << "single camera mode";
std::string cname = layout.devices[0]; std::string cname = layout.devices[0];
@@ -642,12 +676,15 @@ void PylonRecorder::connectCamera() {
statusBar()->showMessage(QString::fromStdString(message)); statusBar()->showMessage(QString::fromStdString(message));
updateActions(); updateActions();
} }
// Dual Camera mode
if (layout.mode == CameraMode::dual && layout.devices.size() == 2) { if (layout.mode == CameraMode::dual && layout.devices.size() == 2) {
qDebug() << "dual camera mode"; qDebug() << "dual camera mode";
std::string message; std::string message;
dualcam = new DualcamWrapper(layout); dualcam = new DualcamWrapper(layout);
bool success = dualcam->openCameras(message); bool success = dualcam->openCameras(message);
if (success) { if (success) {
qDebug() << "Dual cameras connected";
cameraConnectedLabel->setText("connected"); cameraConnectedLabel->setText("connected");
cameraConnectedLabel->setStyleSheet("QLabel { font-size: 10px;font-family: Arial;color: green;}"); cameraConnectedLabel->setStyleSheet("QLabel { font-size: 10px;font-family: Arial;color: green;}");
cameraOpened = true; cameraOpened = true;
@@ -750,8 +787,8 @@ void PylonRecorder::startSinglecamRecording() {
delete writer; delete writer;
writer = nullptr; writer = nullptr;
} }
writer = new Writer(buffer, 0); writer = new Writer(buffer);
connect(writer, SLOT(writingDone()), this, SLOT(writerDone())); connect(writer, SIGNAL(writingDone()), this, SLOT(writerDone()));
writer->setVideoSpecs(specs); writer->setVideoSpecs(specs);
QSettings s; QSettings s;
@@ -781,7 +818,7 @@ void PylonRecorder::startDualcamRecording() {
VideoSpecs specs = getVideoSpecs(settings); VideoSpecs specs = getVideoSpecs(settings);
specs.filename = filename; specs.filename = filename;
specs.format = VideoFormat::mp4; specs.format = VideoFormat::mp4;
qDebug() << "got video specifications"; qDebug() << "got video specifications " << specs.fps;
if (buffer != nullptr) { if (buffer != nullptr) {
buffer->clear(); buffer->clear();
delete buffer; delete buffer;
@@ -813,14 +850,14 @@ void PylonRecorder::startDualcamRecording() {
delete writer; delete writer;
writer = nullptr; writer = nullptr;
} }
writer = new Writer(buffer, 0); writer = new Writer(buffer);
connect(writer, SIGNAL(writingDone()), this, SLOT(writerDone())); connect(writer, SIGNAL(writingDone()), this, SLOT(writerDone()));
writer->setVideoSpecs(specs); writer->setVideoSpecs(specs);
qDebug() << "push metadata to writer"; // qDebug() << "push metadata to writer";
QSettings s; // QSettings s;
this->mdata.read(s); // this->mdata.read(s);
writer->setProjectMetadata(mdata); // writer->setProjectMetadata(mdata);
dryRun = dryRunCheckBox->isChecked(); dryRun = dryRunCheckBox->isChecked();
buffer->clear(); buffer->clear();
@@ -869,9 +906,7 @@ void PylonRecorder::stopRecording() {
stopRequest = true; stopRequest = true;
grab_stop_action->setEnabled(false); grab_stop_action->setEnabled(false);
qDebug() << "StopRecording: clear buffer!"; qDebug() << "StopRecording: clear buffer!";
if(buffer != nullptr) { if (dryRun){
buffer->clear();
if (dryRun)
writerDone(); writerDone();
} }
} }
@@ -893,8 +928,12 @@ void PylonRecorder::writerDone() {
} }
if (writer != nullptr) if (writer != nullptr)
writer->wait(10000); writer->wait(10000);
if(buffer != nullptr) {
buffer->clear();
}
writing = false; writing = false;
updateActions(); updateActions();
qInfo() << "writer is Done!"; qInfo() << "writer is Done!";
} }
@@ -907,6 +946,7 @@ void PylonRecorder::displayActivity() {
void PylonRecorder::displaySingleFrame() { void PylonRecorder::displaySingleFrame() {
qDebug() << "display single frame";
MyImage *img; MyImage *img;
size_t fc = 0; size_t fc = 0;
img = buffer->readLast(fc); img = buffer->readLast(fc);
@@ -914,7 +954,7 @@ void PylonRecorder::displaySingleFrame() {
QImage qimg(static_cast<uchar *>(img->data()), img->width(), img->height(), QImage::Format::Format_Grayscale8); QImage qimg(static_cast<uchar *>(img->data()), img->width(), img->height(), QImage::Format::Format_Grayscale8);
setImage(qimg); setImage(qimg);
}else { }else {
std::cerr << "Error reading last image" << std::endl; qDebug() << "Error reading last image";
} }
} }
@@ -960,7 +1000,8 @@ void PylonRecorder::displayBufferPressure() {
void PylonRecorder::grabStillFromPylon() { void PylonRecorder::grabStillFromPylon() {
qDebug() << "Grab still image form camera!"; qDebug() << "Grab still image form camera!";
if (singlecam != nullptr && singlecam->isOpen()) { if (singlecam != nullptr && singlecam->isOpen()) {
MyImage img; ImageSettings s = singlecam->getImageSettings();
MyImage img(s.width, s.height);
bool valid = singlecam->grabFrame(img); bool valid = singlecam->grabFrame(img);
if (valid) { if (valid) {
QImage qimg(static_cast<uchar *>(img.data()), img.width(), img.height(), QImage qimg(static_cast<uchar *>(img.data()), img.width(), img.height(),
@@ -970,7 +1011,7 @@ void PylonRecorder::grabStillFromPylon() {
} else { } else {
statusBar()->showMessage(tr("Camera is not open! Connect to camera first!")); statusBar()->showMessage(tr("Camera is not open! Connect to camera first!"));
} }
//FIXME does not work for single camera mode! //FIXME does not work for stereo camera mode!
qDebug() << "grabbing still image done!"; qDebug() << "grabbing still image done!";
} }

View File

@@ -13,9 +13,9 @@
#include "grabber.h" #include "grabber.h"
#include "dualcamgrabber.h" #include "dualcamgrabber.h"
#include "writer.h" #include "writer.h"
#include "opencvwriter.h"
#include "projectsettings.h" #include "projectsettings.h"
#include "camconfig.h" #include "camconfig.h"
#include "camids.h"
#include "util.h" #include "util.h"
#include <QImage> #include <QImage>
@@ -71,6 +71,8 @@ private slots:
void selectStorageLocation(); void selectStorageLocation();
void cameraConfigurationAccepted(); void cameraConfigurationAccepted();
void cameraConfigurationAborted(); void cameraConfigurationAborted();
void setCameraIDs();
void cameraIDAccepted();
private: private:
void createActions(); void createActions();
@@ -87,7 +89,6 @@ private:
VideoSpecs getVideoSpecs(const ImageSettings &settings); VideoSpecs getVideoSpecs(const ImageSettings &settings);
void startSinglecamRecording(); void startSinglecamRecording();
void startDualcamRecording(); void startDualcamRecording();
bool saveFile(const QString &fileName); bool saveFile(const QString &fileName);
void setImage(const QImage &newImage); void setImage(const QImage &newImage);
void scaleImage(double factor); void scaleImage(double factor);
@@ -122,8 +123,9 @@ private:
QString storageLocation = ""; QString storageLocation = "";
ProjectMetadata mdata; ProjectMetadata mdata;
Pylon::DeviceInfoList_t deviceList; Pylon::DeviceInfoList_t deviceList;
CamConfigurator *d;
Pylon::PylonAutoInitTerm autoInitTerm; Pylon::PylonAutoInitTerm autoInitTerm;
CamConfigurator *cameraConfigDialog;
CameraID *cameraIdDialog;
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer) #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
@@ -142,6 +144,7 @@ private:
QAction *grab_stop_action; QAction *grab_stop_action;
QAction *connect_camera_action; QAction *connect_camera_action;
QAction *disconnect_camera_action; QAction *disconnect_camera_action;
QAction *set_cam_identifier_action;
}; };
#endif #endif

View File

@@ -157,14 +157,43 @@ bool PylonWrapper::grabFrame(MyImage &img) {
camera->StartGrabbing(); camera->StartGrabbing();
camera->RetrieveResult( 5000, frame, Pylon::TimeoutHandling_ThrowException); camera->RetrieveResult( 5000, frame, Pylon::TimeoutHandling_ThrowException);
camera->StopGrabbing(); camera->StopGrabbing();
qDebug() << "grabFrame done";
} }
img.setFrame(frame); img.setFrame(frame);
return frame.IsValid(); return frame.IsValid();
} }
uint32_t PylonWrapper::sensorWidth() {
qDebug() << "Reading SensorWidth";
uint32_t width = -1;
if (valid) {
qDebug() << "SensorWidth available";
GenApi::INodeMap &nodemap = camera->GetNodeMap();
if (GenApi::IsAvailable(nodemap.GetNode("SensorWidth"))) {
Pylon::CIntegerParameter pwidth( nodemap, "SensorWidth" );
width = (uint32_t)pwidth.GetValue();
}
}
return width;
}
uint32_t PylonWrapper::sensorHeight() {
qDebug() << "Reading SensorHeight";
uint32_t height = -1;
if (valid){
GenApi::INodeMap &nodemap = camera->GetNodeMap();
if (GenApi::IsAvailable(nodemap.GetNode("SensorHeight"))) {
Pylon::CIntegerParameter pheight( nodemap, "SensorHeight" );
height = (uint32_t)pheight.GetValue();
}
}
return height;
}
void PylonWrapper::resetCamera() { void PylonWrapper::resetCamera() {
int64_t dfltWidth = 2048; uint32_t dfltWidth = sensorWidth();
int64_t dfltHeight = 1536; uint32_t dfltHeight = sensorHeight();
qDebug() << "resetting camera to default ROI (" << dfltWidth << ", " << dfltHeight << ")"; qDebug() << "resetting camera to default ROI (" << dfltWidth << ", " << dfltHeight << ")";
try { try {
GenApi::INodeMap& nodemap = camera->GetNodeMap(); GenApi::INodeMap& nodemap = camera->GetNodeMap();
@@ -179,6 +208,7 @@ void PylonWrapper::resetCamera() {
std::cerr << "An exception occurred." << std::endl << e.GetDescription() << std::endl; std::cerr << "An exception occurred." << std::endl << e.GetDescription() << std::endl;
valid = false; valid = false;
} }
qDebug() << "resetting camera to default ROI done";
} }
bool PylonWrapper::openCamera(std::string &message) { bool PylonWrapper::openCamera(std::string &message) {
@@ -232,3 +262,16 @@ void PylonWrapper::closeCamera() {
Pylon::CInstantCamera *PylonWrapper::getCamera() { Pylon::CInstantCamera *PylonWrapper::getCamera() {
return camera; return camera;
} }
QString PylonWrapper::userName() {
GenApi::INodeMap& nodemap = camera->GetNodeMap();
QString username = Pylon::CStringParameter(nodemap, "DeviceUserID").GetValue().c_str();
if (username.length() == 0) {
username = Pylon::CStringParameter(nodemap, "DeviceModelName").GetValue().c_str();
}
return username;
}
QString PylonWrapper::deviceName() {
return QString::fromStdString(fullName);
}

View File

@@ -27,8 +27,12 @@ public:
bool exposureTime(double exposure_time); bool exposureTime(double exposure_time);
double gain(); double gain();
bool gain(double gain_db); bool gain(double gain_db);
uint32_t sensorHeight();
uint32_t sensorWidth();
QString userName();
Pylon::CInstantCamera *getCamera(); Pylon::CInstantCamera *getCamera();
void resetCamera(); void resetCamera();
QString deviceName();
private: private:
Pylon::CInstantCamera *camera; Pylon::CInstantCamera *camera;

View File

@@ -1,9 +1,13 @@
#include "writer.h" #include "writer.h"
#include <chrono> #include <chrono>
#include <fstream> #include <fstream>
#include <pylon/VideoWriter.h> #include <pylon/VideoWriter.h>
#include <chrono>
using namespace std::chrono; using namespace std::chrono;
typedef high_resolution_clock Time;
typedef milliseconds ms;
typedef duration<float> fsec;
void Writer::setVideoSpecs(VideoSpecs specs) { void Writer::setVideoSpecs(VideoSpecs specs) {
videoSpecs = specs; videoSpecs = specs;
@@ -37,74 +41,24 @@ void Writer::run() {
// Releases all pylon resources. // Releases all pylon resources.
// PylonTerminate(); // PylonTerminate();
// Return with error code 1. // Return with error code 1.
emit writingDone(this->cam_number); emit writingDone();
return; return;
} }
qDebug() << "checks done!"; qDebug() << "checks done!";
Pylon::CVideoWriter videoWriter; Pylon::CVideoWriter videoWriter;
if (specs_valid) { if (specs_valid && videoSpecs.format != VideoFormat::raw) {
stop_request = false; stop_request = false;
stopNow = false; stopNow = false;
if (videoSpecs.format == VideoFormat::raw) { videoWriter.SetParameter((uint32_t)videoSpecs.width, (uint32_t)videoSpecs.height,
myFile.open(videoSpecs.filename, std::ios::out | std::ios::binary); videoSpecs.pixelType, (double)videoSpecs.fps, videoSpecs.quality);
myFile.write((char*)&videoSpecs.width, 4);
myFile.write((char*)&videoSpecs.height, 4);
} else {
qDebug() << "setting parameters for video";
videoWriter.SetParameter((uint32_t)videoSpecs.width, (uint32_t)videoSpecs.height, videoSpecs.pixelType, (double)videoSpecs.fps, videoSpecs.quality);
videoWriter.Open(videoSpecs.filename.c_str()); videoWriter.Open(videoSpecs.filename.c_str());
}
nix::File nix_file =nix::File::open(videoSpecs.filename + ".nix", nix::FileMode::Overwrite, "hdf5", nix::Compression::DeflateNormal);
nix::Block b = nix_file.createBlock("Recording", "nix.recording");
nix::Section s = nix_file.createSection("Recording", "nix.recording");
b.metadata(s);
nix::Value v(nix::util::timeToStr(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now())));
s.createProperty("date", v);
nix::Value fn(videoSpecs.filename);
s.createProperty("moviefile", fn);
nix::Section sw_sec = s.createSection("PylonRecorder", "nix.software");
sw_sec.createProperty("version", nix::Value(1));
nix::Section hw_sec = s.createSection("Basler ACA2040-120um", "nix.hardware.camera");
hw_sec.createProperty("type", nix::Value("monochrome"));
hw_sec.createProperty("manufacturer", nix::Value("Basler AG"));
nix::Property p = hw_sec.createProperty("framerate", nix::Value(static_cast<int>(videoSpecs.fps)));
p.unit("Hz");
nix::Property p1 = hw_sec.createProperty("exposure time", nix::Value(static_cast<int>(videoSpecs.exposureTime)));
p1.unit("us");
nix::Property p2 = hw_sec.createProperty("detector gain", nix::Value(static_cast<int>(videoSpecs.detectorGain)));
p2.unit("dB");
if (metadata_valid) {
writeMetadata(s);
}
nix::NDSize initial_shape(1, chunksize);
nix::DataArray frametimes = b.createDataArray("frametimes", "nix.imaging.frametimes", nix::DataType::String, initial_shape);
frametimes.label("time");
frametimes.appendSetDimension();
nix::DataArray frameindices = b.createDataArray("frameindex", "nix.imaging.frameid", nix::DataType::Int64, initial_shape);
frameindices.appendSetDimension();
std::vector<std::string> stamps_buffer(chunksize);
std::vector<int64_t> ids_buffer(chunksize);
nix::NDSize offset(1, 0);
nix::NDSize current_shape(initial_shape);
nix::NDSize chunk_shape(1, chunksize);
qDebug() << "preparations done, starting loop!"; qDebug() << "preparations done, starting loop!";
while ((!stop_request || buffer->bufferLoad() > 0) && !stopNow) { while ((!stop_request || buffer->bufferLoad() > 0) && !stopNow) {
if (buffer->bufferLoad() > 0 ) { if (buffer->bufferLoad() > 0 ) {
size_t framecount = 0; size_t framecount = 0;
MyImage *img = buffer->read(framecount); MyImage *img = buffer->read(framecount);
if (img != nullptr) { if (img != nullptr) {
if (videoSpecs.format == VideoFormat::raw) {
myFile.write((char*)img->data(), img->size());
} else {
Pylon::CPylonImage pyImage; Pylon::CPylonImage pyImage;
try { try {
pyImage.AttachUserBuffer(img->data(), videoSpecs.width * videoSpecs.height, videoSpecs.pixelType, videoSpecs.width, videoSpecs.height, 0, videoSpecs.orientation); pyImage.AttachUserBuffer(img->data(), videoSpecs.width * videoSpecs.height, videoSpecs.pixelType, videoSpecs.width, videoSpecs.height, 0, videoSpecs.orientation);
@@ -113,36 +67,15 @@ void Writer::run() {
std::cerr << "Writer::run: An exception occurred." << std::endl << e.GetDescription() << std::endl; std::cerr << "Writer::run: An exception occurred." << std::endl << e.GetDescription() << std::endl;
} }
} }
if (count < chunksize) {
stamps_buffer[count] = nix::util::timeToStr(img->timestamp());
ids_buffer[count] = img->index();
count ++;
} else {
frametimes.setData(nix::DataType::String, stamps_buffer.data(), chunk_shape, offset);
frameindices.setData(nix::DataType::Int64, ids_buffer.data(), chunk_shape, offset);
current_shape += initial_shape;
frametimes.dataExtent(current_shape);
frameindices.dataExtent(current_shape);
offset[0] += chunksize;
count = 0;
}
}
} else { } else {
while (buffer->bufferLoad() < 1 && !stop_request) { while (buffer->bufferLoad() < 1 && !stop_request) {
msleep(5); msleep(2);
} }
} }
} }
if (count > 0) { videoWriter.Close();
chunk_shape[0] = count;
frametimes.setData(nix::DataType::String, stamps_buffer.data(), chunk_shape, offset);
frameindices.setData(nix::DataType::Int64, ids_buffer.data(), chunk_shape, offset);
}
// videoWriter.Close();
myFile.close();
nix_file.close();
} else { } else {
std::cerr << "Got no video specifications, not writing!" << std::endl; qDebug() << "Got no video specifications, not writing!";
} }
emit writingDone(cam_number); emit writingDone();
} }

View File

@@ -15,8 +15,8 @@ class Writer : public QThread
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit Writer(ImageBuffer*buffer, int number, QObject *parent = nullptr) : explicit Writer(ImageBuffer*buffer, QObject *parent = nullptr) :
QThread(parent), buffer(buffer), cam_number(number) {} QThread(parent), buffer(buffer) {}
void setVideoSpecs(VideoSpecs specs); void setVideoSpecs(VideoSpecs specs);
void setProjectMetadata(ProjectMetadata mdata); void setProjectMetadata(ProjectMetadata mdata);
@@ -25,10 +25,9 @@ public:
signals: signals:
void terminated(); void terminated();
void writingDone(int cam); void writingDone();
private: private:
int cam_number;
ImageBuffer *buffer; ImageBuffer *buffer;
VideoSpecs videoSpecs; VideoSpecs videoSpecs;
ProjectMetadata metadata; ProjectMetadata metadata;