This example requires Qt5 >= 5.9 setup for building.
4#include "main_widget.hpp"
12#include <QElapsedTimer>
13#include <QGraphicsSceneMouseEvent>
15#include <QGraphicsRectItem>
17#include <cvb/image.hpp>
18#include <cvb/device_factory.hpp>
19#include <cvb/device.hpp>
20#include <cvb/async/single_stream_handler.hpp>
21#include <cvb/driver/driver.hpp>
22#include <cvb/shapefinder2/classifier_factory.hpp>
24MainWidget::MainWidget()
27 imageScene_ =
new CustomImageScene(
this);
32 imageView_->resize(800, 600);
34 imageView_->setDragMode(QGraphicsView::RubberBandDrag);
37 ctrlWidget_ =
new ControlWidget(
this);
38 addWidget(imageView_);
39 addWidget(ctrlWidget_);
45 streamHandler_ = CustomStreamHandler::Create(device_->Stream(), *
this);
47 ctrlWidget_->EnableGrabCheckBox(
true);
49 QObject::connect(
this, SIGNAL(SearchDone()),
this, SLOT(ShowSearchResult()));
54 device_->Stream()->GetSnapshot();
58void MainWidget::HandleLoad()
60 imageScene_->ClearScene();
63 ,
Cvb::UI::CvbToQt(Cvb::ExpandPath(Cvb::InstallPath() + CVB_LIT(
"tutorial/ShapeFinder/Images/SF2/Lusterterminal")))
64 ,
"CVB Emulator Image Lists (*.emu);;CVB Drivers (*.vin);;Images (*.bmp *.png *.tif *.tiff *.jpg)");
65 if (fileName.isEmpty())
68 if (fileName.contains(
".emu", Qt::CaseInsensitive))
69 fileName = fileName.replace(
"/",
"\\");
74 if (fileName.contains(
".bmp", Qt::CaseInsensitive) || fileName.contains(
".png", Qt::CaseInsensitive) || fileName.contains(
".tif", Qt::CaseInsensitive) || fileName.contains(
".jpg", Qt::CaseInsensitive))
77 imageView_->Refresh(image);
79 ctrlWidget_->EnableGrabCheckBox(
false);
87 streamHandler_ = CustomStreamHandler::Create(device_->Stream(), *
this);
89 ctrlWidget_->EnableGrabCheckBox(
true);
99void MainWidget::HandleGrab(
int state)
101 if (state == Qt::CheckState::Checked)
103 imageScene_->ClearScene();
106 streamHandler_->Run();
111 bool wait = imageView_->IsWaitForRepaintEnabled();
113 imageView_->SetWaitForRepaintEnabled(!wait);
115 streamHandler_->Finish();
117 imageView_->SetWaitForRepaintEnabled(wait);
122void MainWidget::HandleSnap()
124 device_->Stream()->GetSnapshot();
125 if (continuedSearch_)
128 imageScene_->ClearScene();
132void MainWidget::HandleSave()
136 ,
"Bitmap File (*.bmp);;CVB Emulator Image Lists (*.emu);;JPEG (*.jpg, *.jpeg);;Portable Network Graphic (*.png);;Tagged Image File Format (*.tif, *.tiff);;All Files (*.*)");
137 if (fileName.isEmpty())
143void MainWidget::HandleLoadModel()
145 imageScene_->ClearScene();
148 ,
Cvb::UI::CvbToQt(Cvb::ExpandPath(Cvb::InstallPath() + CVB_LIT(
"tutorial/ShapeFinder/Images/SF2/Lusterterminal")))
149 ,
"ShapeFinder2 models (*.sf2)");
150 if (fileName.isEmpty())
157void MainWidget::HandleSaveModel()
160 ,
Cvb::UI::CvbToQt(Cvb::ExpandPath(Cvb::InstallPath() + CVB_LIT(
"tutorial/ShapeFinder/Images/SF2/Lusterterminal")))
161 ,
"ShapeFinder2 models (*.sf2)");
162 if (fileName.isEmpty())
169void MainWidget::HandleTrain()
173 ctrlWidget_->SetTrainView(*selection_);
174 imageScene_->ClearScene();
179 ctrlWidget_->SetTrainView(*imageView_->Image());
180 auto aoi = imageView_->Image()->Bounds();
181 selectionRect_ =
Cvb::Rect<double>(aoi.Left(), aoi.Top(), aoi.Right(), aoi.Bottom());
186 double centerX = selectionRect_.Left() + ((selectionRect_.Right() - selectionRect_.Left()) / 2);
187 double centerY = selectionRect_.Top() + ((selectionRect_.Bottom() - selectionRect_.Top()) / 2);
189 Cvb::Rect<int> teachWindow(selectionRect_.Left() - centerX, selectionRect_.Top() - centerY, selectionRect_.Right() - centerX, selectionRect_.Bottom() - centerY);
201void MainWidget::HandleSearch()
205 QMessageBox::warning(
this,
"SF2 Search",
"Please create (train) or load a model/classifier first.");
213void MainWidget::HandleContSearch(
int state)
215 imageScene_->ClearScene();
217 if (state == Qt::Checked)
218 continuedSearch_ =
true;
220 continuedSearch_ =
false;
230void MainWidget::HandleSelection(
QRectF selection)
234 auto convertedArea = imageView_->Image()->ImageToPixelCoordinates(area);
241 selectionRect_ = boundingRect;
245void MainWidget::Search()
251 double relativeThreshold = 0.55;
252 int minimumThreshold = 20;
253 int coarseLocality = 10;
257 Cvb::Rect<int> aoi(selectionRect_.Left(), selectionRect_.Top(), selectionRect_.Right(), selectionRect_.Bottom());
258 searchResult_ = classifier_->SearchAll(imageView_->Image()->Plane(0), aoi, mode, relativeThreshold, minimumThreshold, coarseLocality);
262 searchResult_ = classifier_->SearchAll(imageView_->Image()->Plane(0), imageView_->Image()->Bounds(), mode, relativeThreshold, minimumThreshold, coarseLocality);
269void MainWidget::ShowSearchResult()
272 ctrlWidget_->SetResultInfo(searchResult_.size());
273 imageScene_->SetSearchResult(*imageView_->Image(), searchResult_);
277ControlWidget::ControlWidget(
QWidget* parent)
287 QObject::connect(openImgBtn, SIGNAL(clicked()), parent, SLOT(HandleLoad()));
289 grabCheckBox_ =
new QCheckBox(tr(
"Grab"));
290 QObject::connect(grabCheckBox_, SIGNAL(stateChanged(
int)), parent, SLOT(HandleGrab(
int)));
298 contSearchCheckBox_ =
new QCheckBox(tr(
"Continued Search"));
299 QObject::connect(contSearchCheckBox_, SIGNAL(stateChanged(
int)), parent, SLOT(HandleContSearch(
int)));
304 QObject::connect(loadModelBtn, SIGNAL(clicked()), parent, SLOT(HandleLoadModel()));
307 QObject::connect(saveModelBtn, SIGNAL(clicked()), parent, SLOT(HandleSaveModel()));
313 QObject::connect(searchBtn, SIGNAL(clicked()), parent, SLOT(HandleSearch()));
315 resultLabel_ =
new QLabel(tr(
"Number of search results: 0"));
322 gbLayout->
addWidget(resultLabel_, 2, 0, 1, -1);
325 mainLayout->addWidget(trainImageView_, 0, 0, 1, -1);
326 mainLayout->addWidget(openImgBtn, 1, 0, 1, 1);
327 mainLayout->addWidget(grabCheckBox_, 1, 1, 1, 1);
328 mainLayout->addWidget(snapBtn, 1, 2, 1, 1);
329 mainLayout->addWidget(saveBtn, 2, 0, 1, 1);
330 mainLayout->addWidget(contSearchCheckBox_, 2, 1, 1, -1);
331 mainLayout->addWidget(groupBox, 3, 0, 1, -1);
333 setLayout(mainLayout);
336void ControlWidget::EnableGrabCheckBox(
bool value)
338 grabCheckBox_->setEnabled(value);
341void ControlWidget::SetResultInfo(
size_t numResults)
344 resultLabel_->setText(count);
347void ControlWidget::SetTrainView(
const Cvb::Image & image)
350 trainImageView_->Refresh(image);
354CustomImageScene::CustomImageScene(
QWidget* parent)
355 :
Cvb::UI::ImageScene(parent)
363 searchResult_ = result;
366 for (
int i = 0; i < searchResult_.size(); i++)
382 this->addItem(textLabel);
384 text->
setPos(point.X() + 5, point.Y() + 2.5);
389void CustomImageScene::ClearScene()
398 this->ImageView()->setDragMode(QGraphicsView::RubberBandDrag);
401 pointStart_ =
event->scenePos();
407 pointEnd_ =
event->scenePos();
409 this->addRect(
QRectF(pointStart_, pointEnd_),
QPen(Qt::blue, 0));
411 emit SelectionDone(
QRectF(pointStart_, pointEnd_));
double Deg() const noexcept
Get the value in degrees.
Definition: angle.hpp:87
Structure that represents an area of interest in the image.
Definition: area_2d.hpp:21
static std::shared_ptr< T > Open(const String &provider, AcquisitionStack acquisitionStack=AcquisitionStack::PreferVin)
Opens a device with the given provider with its default board and port (if applicable).
Definition: decl_device_factory.hpp:50
static std::unique_ptr< Image > Load(const String &fileName)
Loads an image with the given file name.
Definition: detail_image.hpp:32
T Bottom() const noexcept
Gets bottom row of the rectangle (still inside the rectangle).
Definition: rect.hpp:151
T Top() const noexcept
Gets first row of the rectangle.
Definition: rect.hpp:111
T Right() const noexcept
Gets rightmost column of the rectangle (still inside the rectangle).
Definition: rect.hpp:131
T Left() const noexcept
Gets first column of the rectangle.
Definition: rect.hpp:91
Rectangle object.
Definition: rect_lt.hpp:24
Size2D< T > Size() const noexcept
Gets the size of the rectangle.
Definition: rect_lt.hpp:205
Point2D< T > Location() const noexcept
Gets the location of the top left corner of the rectangle.
Definition: rect_lt.hpp:226
ShapeFinder2 classifier factory object.
Definition: classifier_factory.hpp:27
std::unique_ptr< Classifier > Learn(const ImagePlane &plane, Point2D< double > position, Rect< int > teachWindow, const std::vector< Point2D< int > > &dontCarePoints) const
Creates a ShapeFinder2 classifier from plane 0 of the input image.
Definition: classifier_factory.hpp:261
static std::unique_ptr< Classifier > Create(const String &fileName)
Creates a classifier object loading a classifier file.
Definition: classifier.hpp:64
Search result as returned by the classifier.
Definition: search_result.hpp:24
double Quality() const noexcept
Quality measure of the result.
Definition: search_result.hpp:77
Angle Rotation() const noexcept
Rotation angle of the result.
Definition: search_result.hpp:97
double Y() const noexcept
Y position at which the object has been found.
Definition: search_result.hpp:67
double X() const noexcept
X position at which the object has been found.
Definition: search_result.hpp:57
Stores a pair of numbers that represents the width and the height of a subject, typically a rectangle...
Definition: size_2d.hpp:20
PrecisionMode
Controls precision over accuracy for ShapeFinder 1 type searches.
Definition: shapefinder2.hpp:47
@ CorrelationFine
In the CorrelationFine mode, after the initial edge model search a correlation and hill climbing will...
Cvb::String QtToCvb(const QString text) noexcept
Convenience converter for strings.
Definition: ui.hpp:239
QString CvbToQt(const Cvb::String &text) noexcept
Convenience converter for strings.
Definition: ui.hpp:254
void setBrush(const QBrush &brush)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
void setPos(const QPointF &pos)
void setDefaultTextColor(const QColor &col)
QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString number(int n, int base)