Common Vision Blox 15.0
Loading...
Searching...
No Matches
Image Manager/Cvb++/QtStatisticsDisplay

This example program is located in your CVB installation under %CVB%Tutorial/Image Manager/Cvb++/QtStatisticsDisplay.

main.cpp:

// The QtStatisticsDisplay example shows a statistics display with a stream from a GenICam device with
// Qt.
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
#include "main_widget.hpp"
#include <QIcon>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
app.setWindowIcon(QIcon(":/CVB_Qt_App.png"));
MainWidget mainWidget;
mainWidget.show();
mainWidget.resize(1024, 640);
return app.exec();
}

main_widget.cpp:

#include "main_widget.hpp"
#include <QCheckBox>
#include <QComboBox>
#include <QDebug>
#include <QDesktopWidget>
#include <QFileDialog>
#include <QGroupBox>
#include <QMessageBox>
#include <QMutexLocker>
#include <QPushButton>
#include <QRadioButton>
#include <QWeakPointer>
#include <qmath.h>
#include <cvb/device_factory.hpp>
MainWidget::MainWidget()
: QWidget(), gbStatEntriesLayout_(new QVBoxLayout),
pbSnap_(new QPushButton("Sna&p", this)),
chkGrab_(new QCheckBox("&Grab", this)),
gbSelectedPort_(new QGroupBox("Selected Port", this)),
gbStatistics_(new QGroupBox("Statistic", this)),
cbSelectedPort_(new QComboBox(gbSelectedPort_)),
view_(new Cvb::UI::ImageView(this)),
device_(Cvb::DeviceFactory::Open(Cvb::InstallPath() +
CVB_LIT("drivers/CVMock.vin"),
Cvb::AcquisitionStack::Vin)),
streamH_(Cvb::Async::SingleStreamHandler::Create(device_->Stream())),
updateStatTimer_(new QTimer(this)) {
qDebug() << "Please wait for the setup to load...";
// Widgets we do not need to modify (only local)
QPushButton *pbOpen = new QPushButton("&Open Image", this);
QPushButton *pbOpenDev = new QPushButton("&Discover Devices", this);
QPushButton *pbSave = new QPushButton("&Save Image", this);
// Create layouts
QHBoxLayout *mainLayout = new QHBoxLayout;
QVBoxLayout *sideLayout = new QVBoxLayout;
QVBoxLayout *gbSelectedPortLayout = new QVBoxLayout;
// add the widgets to the side layout
sideLayout->addWidget(pbOpen);
sideLayout->addWidget(pbOpenDev);
sideLayout->addWidget(pbSave);
sideLayout->addWidget(chkGrab_);
sideLayout->addWidget(pbSnap_);
// Discover devices and fill list
onDiscover();
// Add horizontal statistics entries to stat. layout and attach to side layout
gbStatistics_->setLayout(gbStatEntriesLayout_);
sideLayout->addWidget(gbStatistics_);
// add a stretch
sideLayout->addStretch();
// add the combobox to the layout
gbSelectedPortLayout->addWidget(cbSelectedPort_);
// add the combobox to the group box layout
gbSelectedPort_->setLayout(gbSelectedPortLayout);
// add the group box to the side layout
sideLayout->addWidget(gbSelectedPort_);
// add the side layout to the main layout
mainLayout->addLayout(sideLayout);
// add a stretch
mainLayout->addStretch();
// add the display
mainLayout->addWidget(view_);
// now use this layout
setLayout(mainLayout);
// Connections
connect(pbOpen, SIGNAL(clicked()), this, SLOT(onOpen()));
connect(pbOpenDev, SIGNAL(clicked()), this, SLOT(onDiscover()));
connect(pbSave, SIGNAL(clicked()), this, SLOT(onSave()));
connect(pbSnap_, SIGNAL(clicked()), this, SLOT(onSnaped()));
connect(chkGrab_, SIGNAL(stateChanged(int)), this, SLOT(onGrabChanged(int)));
connect(cbSelectedPort_, SIGNAL(currentIndexChanged(int)), this,
SLOT(onPortIndexChanged(const int)));
// Statistics timed update
connect(updateStatTimer_, SIGNAL(timeout()), SLOT(updateStatistics()));
updateStatTimer_->start(100);
// Second image view for stream handler to test
view_->SetUploadMode(Cvb::UI::UploadMode::Viewport);
view_->SetRenderEngine(Cvb::UI::RenderEngine::Raster);
view_->Refresh(device_->DeviceImage(), Cvb::UI::AutoRefresh::On);
view_->SetWaitForRepaintEnabled(false);
// Add statistics text
initalizeTooltip();
}
MainWidget::~MainWidget() {
// Stop the stream before destructing handlers
streamH_->Finish();
}
void MainWidget::onGrabChanged(int state) {
// Toggle grab
state == Qt::Unchecked ? streamH_->Finish() : streamH_->Run();
}
void MainWidget::onOpen() {
// Block all possibly recursive signals and update the UI according to the
// current image
SignalGuard guard(this);
try {
// Stop grab if running
if (streamH_->IsActive()) {
streamH_->Finish();
chkGrab_->setChecked(false);
}
// Open file dialog
QString filename = QFileDialog::getOpenFileName(
this, tr("Open Image"), QString("/"),
tr("CImages (*.bmp *.jpg *.png *.tif *.tiff)"));
if (!filename.isEmpty()) {
// Reset old image if it exists
if (img)
img.reset();
// Load new image
img = Cvb::Image::Load(filename.toStdString());
view_->Refresh(img, Cvb::UI::RefreshMode::UploadAndScheduleRepaint,
Cvb::UI::AutoRefresh::Off);
}
} catch (const Cvb::CvbException &e) {
std::cout << e.what() << "\nError opening image!" << std::endl;
}
}
void MainWidget::onDiscover() {
SignalGuard guard(this);
std::cout << "Discovering devices..." << std::endl;
discover_ =
Cvb::DeviceFactory::Discover(Cvb::Driver::DiscoverFlags::UpToLevelVin);
cbSelectedPort_->clear();
gbSelectedPort_->setEnabled(true);
for (const auto &device : discover_) {
Cvb::String devModel{"Unset"};
// Write device model name to list if available, else number each entry
if (device.TryGetProperty(Cvb::Driver::DiscoveryProperties::DeviceModel,
devModel))
cbSelectedPort_->addItem(QString::fromStdString(devModel),
static_cast<int32_t>(device.Index()));
else
cbSelectedPort_->addItem(QString("Device %1").arg(device.Index()),
static_cast<int32_t>(device.Index()));
}
cbSelectedPort_->setCurrentIndex(0);
loadDiscoveredDevice(0ul); // Load first device
}
void MainWidget::onSave() {
// Block all possibly recursive signals and update the UI according to the
// current image
SignalGuard guard(this);
// Stop grab if running
if (streamH_->IsActive()) {
streamH_->Finish();
chkGrab_->setChecked(false);
}
// Open file dialog
QString filename = QFileDialog::getSaveFileName(
this, tr("Save Image"), QString("~/"),
tr("CImages (*.bmp *.jpg *.png *.tif *.tiff)"));
if (!filename.isEmpty())
view_->Image()->Save(filename.toLatin1().toStdString());
}
void MainWidget::onSnaped() {
// Stop grab if running
if (streamH_->IsActive()) {
streamH_->Finish();
chkGrab_->setChecked(false);
}
auto waitResult = device_->Stream()->GetSnapshot();
if (waitResult.Image == nullptr)
throw std::runtime_error("Could not snap image.");
}
void MainWidget::onPortIndexChanged(const int index) {
// Load new device to tmp and check if exists
loadDiscoveredDevice(index);
}
void MainWidget::loadDiscoveredDevice(const unsigned long devNum) {
SignalGuard guard(this);
std::cout << "Loading device..." << std::endl;
// Stop grab if running
if (streamH_->IsActive()) {
streamH_->Finish();
chkGrab_->setChecked(false);
}
// Load first discovered device to tmp and check if exists
try {
discover_.at(devNum).AccessToken(), Cvb::AcquisitionStack::Vin)};
if (tmpDevPtr) {
std::cout << "Loading device " << discover_.at(devNum).AccessToken()
<< std::endl;
// Reset stream and device pointer
streamH_.reset();
device_.reset();
device_ = tmpDevPtr;
streamH_ = Cvb::SingleStreamHandler::Create(device_->Stream());
view_->Refresh(device_->DeviceImage(), Cvb::UI::AutoRefresh::On);
initializeStatistics();
}
} catch (const Cvb::CvbException &e) {
std::cout << e.what() << "\nError changing discovered device!" << std::endl;
}
}
void MainWidget::updateStatistics() {
SignalGuard guard(this);
unsigned long currentStat = 0;
for (auto const &stat : statisticsList_) {
// Update available statistic values
auto const statEnumName = std::get<0>(stat);
auto value = device_->Stream()->Statistics(statEnumName);
auto statValue = QString::number(value);
statValues_.at(currentStat)->setText(statValue);
++currentStat;
}
}
void MainWidget::initializeStatistics() {
std::cout << "Creating device statistic..." << std::endl;
using namespace Cvb::Driver;
// Clean statistics in case of repaint after device change
for (auto &valWdg : statValues_) {
gbStatEntriesLayout_->removeWidget(valWdg);
delete valWdg;
}
for (auto &nameWdg : statNames_) {
gbStatEntriesLayout_->removeWidget(nameWdg);
delete nameWdg;
}
for (auto &lay : gbHStatNameValLayout_) {
// delete lay;
gbStatEntriesLayout_->removeItem(lay);
delete lay;
}
// Set displayable statistics here
statisticsList_.clear();
statisticsList_.push_back(
tuple_element(StreamInfo::IsCameraDetected, "IsCameraDetected"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumBuffersAcquired, "NumBuffersAcquired"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumBuffersAnnounced, "NumBuffersAnnounced"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumBuffersPending, "NumBuffersPending"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersBeingFilled,
"NumBuffersBeingFilled"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumBuffersDelivered, "NumBuffersDelivered"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumBuffersLocked, "NumBuffersLocked"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumBuffersLost, "NumBuffersLost"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumBuffersLostLocked, "NumBuffersLostLocked"));
statisticsList_.push_back(tuple_element(StreamInfo::NumBuffersLostTransfer,
"NumBuffersLostTransfer"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumBuffersQueued, "NumBuffersQueued"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumPacketsReceived, "NumPacketsReceived"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumResends, "NumResends"));
statisticsList_.push_back(
tuple_element(StreamInfo::NumTriggersLost, "NumTriggersLost"));
// Fill out statistic display
statNames_.clear();
statValues_.clear();
gbHStatNameValLayout_.clear();
unsigned long currentStat = 0;
int unavailableStatisticPos = -1;
std::vector<int> delEntries{};
for (auto const &stat : statisticsList_) {
try {
++unavailableStatisticPos;
// Set available statistic values
auto const statEnumName = std::get<0>(stat);
auto value = device_->Stream()->Statistics(
statEnumName); // May throw exception when statistic is not available
std::string statValue = std::to_string(value);
statValues_.push_back(new QLabel(tr(statValue.c_str())));
statValues_.back()->setAlignment(Qt::AlignLeft);
statValues_.back()->updatesEnabled();
// Set available statistic names
statNames_.push_back(new QLabel(tr(std::get<1>(stat).c_str())));
// Add statistic name and value to horizontal layout
gbHStatNameValLayout_.push_back(new QHBoxLayout);
gbHStatNameValLayout_.at(currentStat)->addWidget(statNames_.back());
statValues_.back()->setAlignment(Qt::AlignRight);
gbHStatNameValLayout_.at(currentStat)->addWidget(statValues_.back());
// Add horizontal layout to vertical statistics layout
gbStatEntriesLayout_->addLayout(gbHStatNameValLayout_.at(currentStat));
++currentStat;
} catch (const std::exception &e) {
std::cout << "Removing statistic due to error: " << e.what() << std::endl;
// Store vector position of unavailable statistic
delEntries.push_back(unavailableStatisticPos);
}
}
// Remove unavailable statistics from statistic list
for (auto ri = delEntries.rbegin(); ri != delEntries.rend(); ++ri)
statisticsList_.erase(statisticsList_.begin() + *ri);
std::cout << "Done initializing" << std::endl;
}
void MainWidget::initalizeTooltip() {
// Mouse position information
view_->setMouseTracking(true);
QApplication::setOverrideCursor(Qt::ArrowCursor);
// Show mouse position and pixel data
view_->RegisterEventMouseMoved(
[&](Cvb::Point2D<int> mousePos, const std::vector<double> &pixelVal) {
Cvb::StringStream titleStream;
// Check if Image is RGB like or mono
if (pixelVal.size() == 3) {
titleStream << "(X:" << mousePos.X() << ", Y:" << mousePos.Y()
<< ") (R:" << qFloor(pixelVal[0])
<< ", G:" << qFloor(pixelVal[1])
<< ", B:" << qFloor(pixelVal[2]) << ")";
} else if (pixelVal.size() == 1) {
titleStream << "(X:" << mousePos.X() << ", Y:" << mousePos.Y()
<< ") (Mono:" << qFloor(pixelVal[0]) << ")";
} else {
titleStream << "(X:" << mousePos.X() << ", Y:" << mousePos.Y()
<< ") (Mono:";
for (auto &pix : pixelVal)
titleStream << qFloor(pix) << " | ";
titleStream << ")";
}
view_->setToolTip(QString::fromStdString(titleStream.str()));
});
}
void MainWidget::blockUI(const bool block) {
chkGrab_->blockSignals(block);
pbSnap_->blockSignals(block);
cbSelectedPort_->blockSignals(block);
view_->blockSignals(block);
gbSelectedPort_->blockSignals(block);
gbStatistics_->blockSignals(block);
updateStatTimer_->blockSignals(block);
}
static std::vector< DiscoveryInformation > Discover()
static std::shared_ptr< T > Open(const String &provider, AcquisitionStack acquisitionStack=AcquisitionStack::PreferVin)
static std::unique_ptr< Image > Load(const String &fileName)
T X() const noexcept
T Y() const noexcept
static std::unique_ptr< SingleStreamHandler > Create(const Driver::StreamPtr &stream)
std::string String
std::stringstream StringStream
std::shared_ptr< Device > DevicePtr

main_widget.hpp:

#ifndef MAINWIDGET_HPP_B6881A7A_C21F_488F_834C_2046B8CE3362
#define MAINWIDGET_HPP_B6881A7A_C21F_488F_834C_2046B8CE3362
#include <iostream>
#include <QApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QScopedPointer>
#include <QSharedPointer>
#include <QTimer>
#include <QToolTip>
#include <QVBoxLayout>
#include <QWidget>
#include <cvb/async/single_stream_handler.hpp>
#include <cvb/ui/image_view.hpp>
#include <tuple>
class QCheckBox;
class QGroupBox;
class QPushButton;
class QComboBox;
class QRadioButton;
class StatisticsDisplay;
typedef std::tuple<Cvb::Driver::StreamInfo, Cvb::String> tuple_element;
typedef std::vector<std::tuple<Cvb::Driver::StreamInfo, Cvb::String>>
tuple_list;
class MainWidget : public QWidget {
Q_OBJECT
public:
explicit MainWidget();
~MainWidget();
public Q_SLOTS:
void onGrabChanged(int state);
void onOpen();
void onDiscover();
void onSave();
void onSnaped();
void onPortIndexChanged(const int index);
void updateStatistics();
private:
void blockUI(const bool block);
void loadDiscoveredDevice(const unsigned long devNum);
void initializeStatistics();
void initalizeTooltip();
// RAII signal blocker
class SignalGuard {
public:
explicit SignalGuard(MainWidget *mainWidget) : mainWidget_(mainWidget) {
mainWidget_->blockUI(true);
}
~SignalGuard() { mainWidget_->blockUI(false); }
private:
MainWidget *mainWidget_;
};
std::vector<QHBoxLayout *> gbHStatNameValLayout_;
QVBoxLayout *gbStatEntriesLayout_;
QPushButton *pbSnap_;
QCheckBox *chkGrab_;
QGroupBox *gbSelectedPort_;
QGroupBox *gbStatistics_;
QComboBox *cbSelectedPort_;
Cvb::UI::ImageView *view_;
Cvb::DevicePtr device_;
std::vector<Cvb::Driver::DiscoveryInformation> discover_;
tuple_list statisticsList_;
QTimer *updateStatTimer_;
std::vector<QLabel *> statNames_;
std::vector<QLabel *> statValues_;
QLabel *mouseText_;
};
#endif
std::shared_ptr< SingleStreamHandler > SingleStreamHandlerPtr
std::shared_ptr< Image > ImagePtr