Common Vision Blox 15.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Friends Modules Pages
Polimago/CVBpy/QmlCookieClassification

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

classification.py:

import os, sys
import cvb
if sys.version_info >= (3, 11):
from PySide6 import QtCore
from PySide6.QtCore import QObject, Qt, QUrl, Property, Signal, Slot
else:
from PySide2 import QtCore
from PySide2.QtCore import QObject, Qt, QUrl, Property, Signal, Slot
from result_model import ResultModel, PolimagoResult
# Global params
GRID_STEP = 0.6
THRESHOLD = 0.0
LOCALITY = 1.0
class Classification(QtCore.QObject):
def __init__(self, device, result_model):
super().__init__()
self._device = device
self._stream = device.stream()
self._model = result_model
self._search = cvb.polimago.SearchPredictor(os.path.join(cvb.install_path(), "tutorial", "Polimago", "Images", "Cookies", "Cookies.psc"))
self._classification = cvb.polimago.ClassificationPredictor(os.path.join(cvb.install_path(), "tutorial", "Polimago", "Images", "Cookies", "CookieType.pcc"))
self._source = ""
self._search_predictor = ""
self._classification_predictor = ""
self.notify_source.connect(self.source_changed)
self.notify_search_predictor.connect(self.search_predictor_changed)
self.notify_classification_predictor.connect(self.classification_predictor_changed)
@Slot()
def snap(self):
# clear the result
self._model.update([None] * 0)
self._image, wait_status = self._stream.get_timed_snapshot(1000)
if (wait_status != cvb.WaitStatus.Ok):
return None
# refresh image view
self._model.refresh(self._image)
@Slot()
def classify(self):
if self._search == 0 or self._classification == 0:
sys.stderr.write('No search predictor or classification predictor was loaded.\n')
return None
# 1. find items
search_res, calls = self._search.grid_search(self._image, self._image.bounds, GRID_STEP, THRESHOLD, LOCALITY)
polimago_results = [None] * 0
for res in search_res:
# only use results with quality >= 0.3
if res.quality >= 0.3:
# 2. classify the items
pos = cvb.Point2D(res.x, res.y)
clf_res, confidence_distribution = self._classification.classify(self._image, pos)
polimago_results.append(PolimagoResult(pos, res.quality, clf_res))
# 3. show result
self._model.update(polimago_results)
def source(self):
return self._source
def set_source(self, imageSource):
self._source = imageSource
self.notify_source.emit()
def search_predictor(self):
return self._search_predictor
def set_search_predictor(self, searchPredictor):
self._search_predictor = searchPredictor
self.notify_search_predictor.emit()
def classification_predictor(self):
return self._classification_predictor
def set_classification_predictor(self, classificationPredictor):
self._classification_predictor = classificationPredictor
self.notify_classification_predictor.emit()
@Signal
def notify_source(self):
pass
@Signal
def notify_search_predictor(self):
pass
@Signal
def notify_classification_predictor(self):
pass
@Slot()
def source_changed(self):
# clear the result
self._model.update([])
# clear predictors
self._search = 0
self._classification = 0
# close current device
self._device.close()
# open new device / image
path = self._source.toLocalFile()
if path.endswith(".vin"):
self._device = cvb.DeviceFactory.open(
path, cvb.AcquisitionStack.Vin)
self._stream = self._device.stream()
self.snap()
elif path.endswith(".bmp"):
self._image = cvb.Image(path)
self._model.refresh(self._image)
@Slot()
def search_predictor_changed(self):
if not self.search_predictor().isEmpty():
self._search = cvb.polimago.SearchPredictor(self.search_predictor().toLocalFile())
@Slot()
def classification_predictor_changed(self):
if not self.classification_predictor().isEmpty():
self._classification = cvb.polimago.ClassificationPredictor(self.classification_predictor().toLocalFile())
imageSource = Property(QUrl, source, set_source)
searchPredictor = Property(QUrl, search_predictor, set_search_predictor)
classificationPredictor = Property(QUrl, classification_predictor, set_classification_predictor)
Union[cvb.GenICamDevice, cvb.VinDevice, cvb.EmuDevice, cvb.VideoDevice, cvb.NonStreamingDevice] open(str provider, int acquisition_stack=cvb.AcquisitionStack.PreferVin)
str install_path()

main.py:

# @brief Example for pattern classification using Polimago search in QML environment.
import os, sys
import cvb
import cvb.ui
from result_model import ResultModel
from classification import Classification
if sys.version_info >= (3, 11):
from PySide6.QtCore import QObject, QUrl, QAbstractListModel, Qt, QModelIndex
from PySide6.QtQml import QQmlApplicationEngine, qmlRegisterType
from PySide6.QtGui import QGuiApplication, QIcon
else:
from PySide2.QtCore import QObject, QUrl, QAbstractListModel, Qt, QModelIndex
from PySide2.QtQml import QQmlApplicationEngine, qmlRegisterType
from PySide2.QtGui import QGuiApplication, QIcon
if __name__ == "__main__":
app = QGuiApplication([])
app.setOrganizationName('STEMMER IMAGING')
app.setOrganizationDomain('https://www.stemmer-imaging.com/')
app.setApplicationName('Polimago Python tutorial')
# tell Windows the correct AppUserModelID for this process (shows icon in the taskbar)
if sys.platform == 'win32':
import ctypes
myappid = u'stemmerimaging.commonvisionblox.pycookieclassification.0'
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
app.setWindowIcon(QIcon('Tutorial-Python_32x32.png'))
# load the device
os.path.join(cvb.install_path(), "drivers", "CVMock.vin"),
cvb.AcquisitionStack.Vin)
# setup QML interface objects
image_controller = cvb.ui.ImageController()
result_model = ResultModel(image_controller)
# main classification object
classification = Classification(device, result_model)
# register QML components for an image display
engine = QQmlApplicationEngine()
context = engine.rootContext()
# create a controller object to communicate with QML
context.setContextProperty("mainImage", image_controller)
# create a Minos result model to communicate with QML for overlays
context.setContextProperty("resultModel", result_model)
# create a Minos search object to communicate with QML (grab, snap)
context.setContextProperty("classification", classification)
# load main QML file
engine.load(os.path.join(os.path.dirname(os.path.abspath(__file__)), "main.qml"))
# do a first snap at startup
classification.snap()
app.exec_()
None register(cls, str uri="CvbQuick", int version_major=1, int version_minor=0, str qml_name="ImageLabel")
None register(cls, str uri="CvbQuick", int version_major=1, int version_minor=0, str qml_name="ImageView")

result_model.py:

import os
import cvb
import cvb.ui
if sys.version_info >= (3, 11):
from PySide6.QtCore import QObject, QAbstractListModel, Qt, QModelIndex, Property, Signal, Slot
else:
from PySide2.QtCore import QObject, QAbstractListModel, Qt, QModelIndex, Property, Signal, Slot
class PolimagoResult(object):
def __init__(self, pos, pos_quality, clf_res):
self._pos = pos
self._pos_quality = pos_quality
self._name = clf_res.name
self._color_quality = clf_res.quality
def position(self):
return self._pos
def name(self):
return self._name
def position_quality(self):
return self._pos_quality
def color_quality(self):
return self._color_quality
class ResultModel(QAbstractListModel):
LineText = Qt.UserRole
StartPosition = Qt.UserRole + 1
Quality = Qt.UserRole + 2
def __init__(self, image_controller, parent=None):
super(ResultModel, self).__init__(parent)
self._image_controller = image_controller
self._results = [None] * 0
def update(self, polimago_results):
self._results = polimago_results
self.layoutChanged.emit()
def roleNames(self):
roles = dict()
roles[ResultModel.LineText] = b"lineText"
roles[ResultModel.StartPosition] = b"startPosition"
roles[ResultModel.Quality] = b"quality"
return roles
def rowCount(self, parent = QModelIndex()):
return len(self._results)
def data(self, index, role = Qt.DisplayRole):
if not index.isValid():
return None
result = self._results[index.row()]
if role == ResultModel.LineText:
return result.name()
elif role == ResultModel.StartPosition:
return cvb.ui.cvb_to_qt_point(result.position())
elif role == ResultModel.Quality:
return result.position_quality()
else:
return None
@Slot()
def refresh(self, image):
self._image_controller.refresh(image)
Union[PySide2.QtCore.QPointF, PySide6.QtCore.QPointF] cvb_to_qt_point(cvb.Point2D point)