Jan gewinnt die Code Competition

IT-Talents: Hallo Jan, herzlichen Glückwunsch zu Deinem ersten Platz bei der Code Competition „Mustererkennung“! Erzähl den anderen IT-Talenten doch kurz etwas über Dich.

Jan: Ich bin 19 Jahre alt und jetzt in den letzten Wochen meiner Schulzeit, da ich dieses Jahr das Abitur abschließe. Ich habe vor ca. 6 Jahren mit dem Programmieren angefangen und bin immer auf der Suche nach spannenden Aufgaben und Herausforderungen.

IT-Talents: Was hat Dich motiviert, an der Competition teilzunehmen und wie bist Du auf den Wettbewerb aufmerksam geworden?

Jan: Ich habe vor einem halben Jahr von einem Schulkamerad von der it-talents Seite erzählt bekommen. Seitdem schaue ich immer mal wieder vorbei und gucke was es so Neues gibt, wobei mich diese Code Competition besonders angesprochen hat. Daraufhin habe ich relativ schnell mit dem Programmieren angefangen und mich immer weiter damit beschäftigt.

IT-Talents: Wie bist Du an die Lösung der Aufgabenstellung herangegangen? Hattest Du schon Erfahrung mit Algorithmen zur Mustererkennung?

Jan: Erfahrung mit dem Thema hatte ich noch nicht wirklich. Es gab dann zunächst einen “Crashkurs” in Bildverarbeitung mit YouTube-Videos und verschiedenen Internetseiten um mich mit gängigen Methoden und Algorithmen vertraut zu machen, die mir möglicherweise bei dem Problem helfen könnten. Dabei bin ich dann auch relativ schnell auf die Bildverarbeitungsbibliothek OpenCV gekommen, die fast alle nötigen Algorithmen zur Verfügung stellt und sich super zur Anschauung anbietet.

IT-Talents: Welche Probleme sind bei der Entwicklung der Software aufgekommen? Wie lange hat die Entwicklung gedauert?

Jan: Vor allem die Einarbeitung in das Thema und ein grobes Verständnis der Methoden zum Lösen waren sehr demotivierend, da diese oft deutlich tieferes mathematisches Verständnis fordern und ziemlich komplex sind. Außerdem waren Tests während dem Programmieren immer wieder fehlerhaft und haben Zweifel am Funktionieren der Software verursacht.

IT-Talents: Und was hast Du durch die Entwicklung gelernt?

Jan: Während der Entwicklung war vor allem die Dokumentation des Projekt für mich sehr wichtig, da ich diese meist vernachlässige. Dabei habe ich unter anderem Doxygen und Markdown als gängige Mittel zur Dokumentation kennengelernt. Außerdem waren natürlich die vielen Bildverarbeitungsalgorithmen sehr spannend und haben mein Wissen in diese Richtung deutlich erweitert.

IT-Talents: Zu guter Letzt: Was würdest Du Dir thematisch gerne einmal als Code Competition wünschen?

Jan: Ich glaube einen konkreten Wunsch habe ich nicht. Ich lasse mich dann lieber überraschen und schaue mal was noch so kommt.

IT-Talents: Vielen Dank für Deine Teilnahme, das Interview und viel Spaß mit Deinem Gewinn 😉

Wie sieht Jan’s Programm aus?
#include "mainwindow.h" #include "ui_mainwindow.h"  MainWindow::MainWindow(QWidget *parent) :     QMainWindow(parent),     ui(new Ui::MainWindow) {     ui->setupUi(this);     init();     initGui();     setConnections();     registerTemplateMatcher(); }  MainWindow::~MainWindow() {     delete ui; }  void MainWindow::init() {     // Instanzen erzeugen, auf die die Pointer verweisen sollen     // Memorymanagment wird durch parent (this) übernommen -> Deallokieren nicht nötig     _matching_progressbar = new QProgressBar(this);     _image_manager = new ImageIOManager(this);     _template_matching_processor = new TemplateMatchingProcessor(this);     // Pointer auf ImageManager auch an TemplateMatchingProcessor übergeben     _template_matching_processor->setImageManager(_image_manager); }  void MainWindow::initGui() {     // Ladebalken in Statusbar hinzufügen (nicht möglichen im Designer)     ui->statusBar->addPermanentWidget(_matching_progressbar,1);     // ladebalken erstmal deaktiveren     ui->statusBar->setVisible(false);     // Vorschau zurücksetzten (->Scrollbar deaktiveren)     updateUnfilteredImages();     // Vorschau zurücksetzten (->Scrollbar deaktiveren)     updateFilteredImages(); }  void MainWindow::setConnections() {     // Alle Verbindungen der Objecte und Widgets untereinander herstellen      QObject::connect(ui->filter_widget, &FilterWidget::templateMatcherChanged,                      _template_matching_processor, &TemplateMatchingProcessor::setTemplateMatcher);     QObject::connect(ui->filter_widget, &FilterWidget::imagesShouldCotainTemplate,                      _template_matching_processor, &TemplateMatchingProcessor::imagesShouldContainTemplate);     QObject::connect(ui->apply_filter_button, &QPushButton::clicked,                      this, &MainWindow::startMatching);     QObject::connect(_template_matching_processor, &TemplateMatchingProcessor::matchingStatusChanged,                      this, &MainWindow::setMatchingStatus);     QObject::connect(_template_matching_processor, &TemplateMatchingProcessor::matchingFinished,                      this, &MainWindow::matchingFinished);     QObject::connect(ui->import_images_button, &QPushButton::clicked,                      this, &MainWindow::importImagesDialog);     QObject::connect(ui->clear_all_button, &QPushButton::clicked,                      this, &MainWindow::clearImages);     QObject::connect(ui->export_images_button, &QPushButton::clicked,                      this, &MainWindow::exportImagesDialog);     QObject::connect(ui->unfiltered_scrollbar, &QScrollBar::valueChanged,                      this, &MainWindow::unfilteredImagesScroll);     QObject::connect(ui->filtered_scrollbar, &QScrollBar::valueChanged,                      this, &MainWindow::filterImageScroll);     QObject::connect(ui->stop_filtering_button, &QPushButton::clicked,                      _template_matching_processor, &TemplateMatchingProcessor::stopMatching); }  void MainWindow::registerTemplateMatcher() {     // Es wird ein neues Filter Objekt instanziert und der Pointer an das FilterWidget übergeben     ui->filter_widget->registerTemplateMatcher(new CorrelationTemplateMatcher(this));     ui->filter_widget->registerTemplateMatcher(new FeatureTemplateMatcher(this)); }  void MainWindow::dragEnterEvent(QDragEnterEvent *event) {     // Drop akzeptieren     event->acceptProposedAction(); }  void MainWindow::dropEvent(QDropEvent *event) {     // Daten des DropEvents holen     const QMimeData* mime_data = event->mimeData();     // nur wenn DropEvent Urls enthält diese weiter überprüfen     // (Dateien, werden nur als Urls bei DropEvents übergeben)     if (mime_data->hasUrls()) {         // Überprüfen, in welches Widget die Dateien gedropped wurden         if (ui->unfiltered_gbox->rect().contains( ui->unfiltered_gbox->mapFromParent(event->pos()) )) {              // DropEvent annehmen             event->acceptProposedAction();             // Urls holen             QList urls =  mime_data->urls();             QStringList filenames;             // aus Url konkreten Dateipfad (als String) machen             for (QUrl url : urls) {                 if (url.isLocalFile()) {                     filenames += url.toLocalFile();                 }             }             // ImageManager Dateipfade zum Importieren übergeben             _image_manager->importImages(filenames,ui->import_recursive_checkbox->isChecked());             // Vorschau im Programm aktualisieren             updateUnfilteredImages();          } else if (ui->filtered_gbox->rect().contains( ui->filtered_gbox->mapFromParent(event->pos()) )) {              // Daten holen             QList urls =  mime_data->urls();             // Überprüfen ob nur eine Url übergebn wurde             if (urls.size()==1) {                 // weitere Infos zur übergebenen Url                 QFileInfo info(urls.first().toLocalFile());                 // Überprüfen ob Url auf Ordner verweist                 if (info.isDir()) {                     event->acceptProposedAction();                     // gefilterte Bilder in diesen Ordner exportieren                     _image_manager->exportImages(info.absoluteFilePath());                 }             }          }     } }  void MainWindow::importImagesDialog() {     // Urls per Dateidialog holen     QList urls = QFileDialog::getOpenFileUrls(this,"Bild laden");     // Überprüfen ob min. 1 Datei ausgwählt wurde     if (urls.size()) {         QStringList filenames;         // Urls zu Dateipfaden (Strings) konvertieren         for (QUrl url : urls) {             if (url.isLocalFile()) {                 filenames += url.toLocalFile();             }         }         // ImageManager Dateipfade zum Importieren übergeben         _image_manager->importImages(filenames,ui->import_recursive_checkbox->isChecked());         // Vorschau aktualiesieren         updateUnfilteredImages();     } }  void MainWindow::clearImages() {     // Bilder aus ImageManager löschen     _image_manager->clearAll();     // Vorschau aktualisieren     updateUnfilteredImages(); }  void MainWindow::exportImagesDialog() {     // Dateidialog zum Auswahlen eines Ordner öffnen     QString dirname = QFileDialog::getExistingDirectory(this, "Bilder in Ordner speichern");     // Überprüfen ob Ordner ausgewählt wurde     if (dirname.size()) {         // ImageManager Ordner zum exportieren übergeben         _image_manager->exportImages(dirname);     } }  void MainWindow::updateUnfilteredImages() {     int unfiltered_count = _image_manager->unfilteredImagesCount();     // Wenn mehr als 1 Bild Scrollbar anzeigen     ui->unfiltered_scrollbar->setVisible(unfiltered_count>1);     // Überprüfen ob min. 1 Bild vorhanden ist     if (unfiltered_count) {         // Scrollbar-Grenzen anpassen         ui->unfiltered_scrollbar->setMinimum(0);         ui->unfiltered_scrollbar->setMaximum(unfiltered_count-1);         // Erstes Bild in Vorschau anzeigen         ui->unfiltered_image_label->setImage(_image_manager->unfilteredImage(0));     } else {         // Vorschau aufräumen         ui->unfiltered_image_label->clear();     } }  void MainWindow::updateFilteredImages() {     int filtered_count = _image_manager->filteredImagesCount();     // Wenn mehr als 1 Bild Scrollbar anzeigen     ui->filtered_scrollbar->setVisible(filtered_count>1);     // Überprüfen ob min. 1 Bild vorhanden ist     if (filtered_count) {         // Scrollbar-Grenzen anpassen         ui->filtered_scrollbar->setMinimum(0);         ui->filtered_scrollbar->setMaximum(filtered_count-1);         // Erstes Bild in Vorschau anzeigen         ui->filtered_image_label->setImage(_image_manager->filteredImage(0));     } else {         // Vorschau aufräumen         ui->filtered_image_label->clear();     } }  void MainWindow::unfilteredImagesScroll(int index) {     // Vorschaubild anhand der Scrollbar Position (-> index) anpassen     ui->unfiltered_image_label->setImage(_image_manager->unfilteredImage(index)); }  void MainWindow::filterImageScroll(int index) {     // Vorschaubild anhand der Scrollbar Position (-> index) anpassen     ui->filtered_image_label->setImage(_image_manager->filteredImage(index)); }  void MainWindow::startMatching() {     // Alte gefilterten Bilder löschen     _image_manager->clearFilteredImages();     // Vorschau löschen     updateFilteredImages();     // Ladebalken anzeigen     ui->statusBar->setVisible(true);     // Matching Vorgang starten     _template_matching_processor->startMatching(); }  void MainWindow::setMatchingStatus(int status) {     // Matching Vorgang mit neuem status aktualisieren     _matching_progressbar->setValue(status); }  void MainWindow::matchingFinished() {     // Ladebalken deaktivieren     ui->statusBar->setVisible(false);     // Vorschau aktualisieren     updateFilteredImages(); } 

Beginne damit, deinen Suchbegriff oben einzugeben und drücke Enter für die Suche. Drücke ESC, um abzubrechen.

Zurück nach oben