Common Vision Blox 15.0
Loading...
Searching...
No Matches
Polimago/Cvb++/QmlCookieClassification

This example program is located in your CVB installation under %CVB%Tutorial/Polimago/Cvb++/QmlCookieClassification.

classification.cpp:

#include "classification.hpp"
#include <QQmlComponent>
#include <QQmlEngine>
#include <cvb/area_2d.hpp>
#include <cvb/point_2d.hpp>
#include <cvb/ui/ui.hpp>
Classification::Classification(ResultModel &model)
: QObject(), controller_(model) {
connect(this, &Classification::NotifySource, this,
&Classification::OnSourceChanged);
connect(this, &Classification::NotifySearchPredictor, this,
&Classification::OnSearchPredictorChanged);
connect(this, &Classification::NotifyClassificationPredictor, this,
&Classification::OnClassificationPredictorChnaged);
// open default example
Cvb::InstallPath() + Cvb::String(CVB_LIT("drivers/CVMock.vin")),
Cvb::AcquisitionStack::Vin); // CVMock.vin loads Cookies example emu
Cvb::String(CVB_LIT("tutorial/Polimago/Images/Cookies/Cookies.psc")));
Cvb::String(CVB_LIT("tutorial/Polimago/Images/Cookies/CookieType.pcc")));
Snap();
}
void Classification::Snap() {
if (!device_)
return;
controller_.Update({});
auto waitResult = device_->Stream()->GetSnapshot();
if (waitResult.Status != Cvb::WaitStatus::Ok)
return;
image_ = waitResult.Image;
controller_.Refresh(image_);
}
void Classification::Classify() {
if (!image_ || !search_ || !classification_)
return;
auto redImage = image_->Plane(0).Map();
const auto gridStep = 0.6;
const auto threshold = 0.0;
const auto locality = 1.0;
std::vector<PolimagoResult> results;
// 1. find items
auto positions = search_->GridSearch(*redImage, redImage->Bounds(), gridStep,
threshold, locality);
auto end = std::remove_if(positions.begin(), positions.end(),
[](const Cvb::Polimago::SearchResult &position) {
return position.Quality() < .3;
});
// 2. classify the items
std::transform(positions.begin(), end, std::back_inserter(results),
[this](const Cvb::Polimago::SearchResult &pos) {
auto result = classification_->Classify(
*image_, Cvb::Point2D<int>{static_cast<int>(pos.X()),
static_cast<int>(pos.Y())});
return PolimagoResult(pos, result);
});
// 3. update to UI
controller_.Update(results);
}
void Classification::OnSourceChanged() {
image_.reset();
device_.reset();
search_.reset();
classification_.reset();
auto fileName = source_.toLocalFile();
auto path = Cvb::UI::QtToCvb(fileName);
if (fileName.endsWith(".vin")) {
device_ = Cvb::DeviceFactory::Open(path);
Snap();
} else if (fileName.endsWith(".bmp")) {
image_ = Cvb::Image::Load(path);
controller_.Update({});
controller_.Refresh(image_);
}
}
void Classification::OnSearchPredictorChanged() {
Cvb::UI::QtToCvb(searchPredictor_.toLocalFile()));
}
void Classification::OnClassificationPredictorChnaged() {
Cvb::UI::QtToCvb(classificationPredictor_.toLocalFile()));
}
static std::shared_ptr< T > Open(const String &provider, AcquisitionStack acquisitionStack=AcquisitionStack::PreferVin)
static std::unique_ptr< Image > Load(const String &fileName)
static std::unique_ptr< ClassificationPredictor > Load(const String &fileName)
static std::unique_ptr< SearchPredictor > Load(const String &fileName)
cvbres_t Snap(IMG Image)
Cvb::String QtToCvb(const QString text) noexcept
std::string String
String InstallPath()

classification.hpp:

#include <QObject>
#include <QVariant>
#include <cvb/async/single_stream_handler.hpp>
#include <cvb/device_factory.hpp>
#include <cvb/polimago/classification_predictor.hpp>
#include <cvb/polimago/search_predictor.hpp>
#include <cvb/ui/image_view_item.hpp>
#include <cvb/utilities/stop_watch.hpp>
#include "result_model.hpp"
class Classification final : public QObject
{
Q_OBJECT
Q_PROPERTY(QUrl source READ Source WRITE SetSource NOTIFY NotifySource);
Q_PROPERTY(QUrl searchPredictor READ SearchPredictor WRITE SetSearchPredictor
NOTIFY NotifySearchPredictor);
Q_PROPERTY(
QUrl classificationPredictor READ ClassificationPredictor WRITE
SetClassificationPredictor NOTIFY NotifyClassificationPredictor);
public:
Classification(ResultModel &model);
public Q_SLOTS:
void Snap();
void Classify();
private Q_SLOTS:
void OnSourceChanged();
void OnSearchPredictorChanged();
void OnClassificationPredictorChnaged();
private:
QUrl Source() const { return source_; }
void SetSource(const QUrl &source) {
if (source_ == source)
return;
source_ = source;
NotifySource();
}
QUrl SearchPredictor() const { return searchPredictor_; }
void SetSearchPredictor(const QUrl &searchPredictor) {
if (searchPredictor_ == searchPredictor)
return;
searchPredictor_ = searchPredictor;
NotifySearchPredictor();
}
QUrl ClassificationPredictor() const { return classificationPredictor_; }
void SetClassificationPredictor(const QUrl &classificationPredictor) {
if (classificationPredictor_ == classificationPredictor)
return;
classificationPredictor_ = classificationPredictor;
NotifyClassificationPredictor();
}
QUrl source_;
Cvb::DevicePtr device_;
Cvb::ImagePtr image_;
QUrl searchPredictor_;
std::unique_ptr<Cvb::Polimago::SearchPredictor> search_;
QUrl classificationPredictor_;
std::unique_ptr<Cvb::Polimago::ClassificationPredictor> classification_;
ResultModel &controller_;
Q_SIGNALS:
void NotifySource();
void NotifySearchPredictor();
void NotifyClassificationPredictor();
};
std::shared_ptr< Image > ImagePtr
std::shared_ptr< Device > DevicePtr

main.cpp:

// Example for pattern classification using Polimago search in QML environment.
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
#include <iostream>
#include <QGuiApplication>
#include <QIcon>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickView>
#include <cvb/ui/image_view_item.hpp>
#include "classification.hpp"
#include "result_model.hpp"
int main(int argc, char *argv[]) {
try {
QGuiApplication app(argc, argv);
app.setWindowIcon(QIcon(":/qttutorial.png"));
// setup QML interface objects
Cvb::UI::ImageController imageController;
ResultModel resultModel(imageController);
// main search object
Classification classification(resultModel);
// register QML components for an image display
Cvb::UI::ImageViewItem::Register();
Cvb::UI::ImageLabelItem::Register();
QQmlApplicationEngine engine;
auto context = engine.rootContext();
// create a controller object to communicate with QML
context->setContextProperty("mainImage", &imageController);
// create a result model to communicate with QML for overlays
context->setContextProperty("resultModel", &resultModel);
// create a classification object to communicate with QML (snap, count)
context->setContextProperty("classification", &classification);
// load main QML file
engine.load(QUrl::fromLocalFile("../main.qml"));
return app.exec();
} catch (const std::exception &error) {
std::cout << error.what() << std::endl;
}
}

result_model.cpp:

#include "result_model.hpp"
#include <QRect>
ResultModel::ResultModel(Cvb::UI::ImageController &controller)
: QAbstractListModel(), controller_(controller) {}
QHash<int, QByteArray> ResultModel::roleNames() const {
QHash<int, QByteArray> names;
names[LineText] = "lineText";
names[StartPosition] = "startPosition";
names[Quality] = "quality";
return names;
}
int ResultModel::rowCount(const QModelIndex &) const {
return static_cast<int>(results_.size());
}
QVariant ResultModel::data(const QModelIndex &index, int role) const {
if (!index.isValid())
return QVariant();
const auto &result = results_[index.row()];
switch (role) {
default:
return QVariant();
case LineText:
return result.Name();
case StartPosition:
return result.Position();
case Quality:
return result.PosQuality();
}
}

result_model.hpp:

#pragma once
#include <iomanip>
#include <mutex>
#include <vector>
#include <QAbstractListModel>
#include <QPoint>
#include <cvb/point_2d.hpp>
#include <cvb/polimago/classification_result.hpp>
#include <cvb/polimago/search_result.hpp>
#include <cvb/ui/image_view_item.hpp>
#include <cvb/ui/ui.hpp>
class PolimagoResult {
public:
PolimagoResult(const Cvb::Polimago::SearchResult &pos,
: position_(static_cast<float>(pos.X()), static_cast<float>(pos.Y())),
name_(Cvb::UI::CvbToQt(result.Name())), posQuality_(pos.Quality()),
colorQuality_(result.Quality()) {}
QPointF Position() const noexcept { return position_; }
QString Name() const noexcept { return name_; }
double PosQuality() const noexcept { return posQuality_; }
double ColorQuality() const noexcept { return colorQuality_; }
private:
QPointF position_;
QString name_;
double posQuality_;
double colorQuality_;
};
class ResultModel : public QAbstractListModel {
Q_OBJECT
friend class Classification;
enum ResultRoles {
LineText = Qt::UserRole,
StartPosition = Qt::UserRole + 1,
Quality
};
public:
explicit ResultModel(Cvb::UI::ImageController &controller);
void Update(const std::vector<PolimagoResult> &results) {
results_ = results;
layoutChanged();
}
void Refresh(const Cvb::ImagePtr &image) { controller_.Refresh(image); }
private:
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex & = QModelIndex()) const override;
QVariant data(const QModelIndex &index,
int role = Qt::DisplayRole) const override;
private:
Cvb::UI::ImageController &controller_;
std::vector<PolimagoResult> results_;
Q_SIGNALS:
};
void Refresh(void)