[PYTHON] Eine Geschichte, die die elektronische Bewertung von Prüfungen mit Bilderkennung unterstützt

Willkommen zum 23. Tag des Yuruyuru New Graduate Advent Calendar 2019. Ich bin @NamedPython, ein frisch Absolvent mit einem losen Abschluss: Freude:

Heute geht es um meine versteckte Leistung ** Bilderkennung mit OpenCV **.

Ich hatte mich im Voraus entschlossen, über Bilderkennung zu schreiben, aber es war schwierig, etwas Neues zu finden, deshalb habe ich mein Bestes versucht, es in der Schulklasse zu schreiben, aber ich habe es nirgendwo angeboten ~~ ** Antwortbogen Ich werde hier eine Aufzeichnung der Flächenextraktion hinterlassen **: bleistift2:

Was hast du versucht zu machen?

Ich sagte, es sei eine Klasse, aber der Name der Klasse lautet ** Programmieranwendung **, und wir arbeiten als Team, um Probleme durch Softwareentwicklung zu lösen, wobei wir das einbeziehen, was wir normalerweise im Unterricht lernen, und die Fähigkeiten unserer Schüler. ist.

Was ist dann das Thema der Problemlösung?

** Erleichtere es dir, deine Prüfungen elektronisch zu bewerten **: bete:

Es war das. Erstens ist es zum Zeitpunkt des elektronischen Scorings noch ziemlich jung, aber wenn Sie die Anforderungen zusammenfassen

Es war so.

Mannschaft

Eigentlich ein Jahr vor dieser Klasse,

--Backend API, Webfront @NamedPython --iOS @Taillook

Wir haben das stärkste Team gebildet und große Kritik erhalten. Infolgedessen war die Anzahl der Teammitglieder begrenzt: Stirnrunzeln2:

Trotzdem zog ich @Taillook und einen anderen guten Klassenkameraden zusammen, um ein Team von drei Personen zu bilden.

Lösung

Mit dem oben erwähnten Team-Team habe ich den Typ gezogen, der iOS schreiben kann.

Da es eine große Sache ist, habe ich ein System mit der folgenden Konfiguration vorgeschlagen, mit dem Sie iOS von allem zu allem fahren können (extrahiert aus der Präsentation der endgültigen Ankündigung). Vielen Dank für die Implementierung rund um iOS, @Taillook.

image.png

Ich habe mein Bestes mit Keynote für diese Figur gegeben. Die Schriftarten sind ** M + ** und ** Tsukushi B Maru Gothic **.

Erkennungsübersicht

Zielbild

Zu diesem Zeitpunkt erhielt ich ein aktuelles Antwortblatt zur Überprüfung des Betriebs, aber ich hatte das Gefühl, dass die Rechte, es hierher zu bringen, grau waren, also nutzte ich die Macht von ** Pages craftsman **, um eine Probe zu generieren.

image.png

Implementierung

Nun, es ist fast langweilig, also Dawn und der Quellcode. Wir haben eine Docker-Datei wie FROM jjanzic / docker-python3-opencv vorbereitet, damit Sie sie überall entwickeln können. Am Ende war der Bilderkennungsteil übertrieben, weil ich ihn vollständig entwickelt habe.

Der Inhalt von Docker ist wie folgt.

source.py


import os
import cv2
import numpy as np

DIR = os.path.dirname(os.path.abspath(__file__))

image = cv2.imread(f'{DIR}/image/sample_answer_sheet.png')
if image is None:
    print("File not found.")
    exit()


def write_out(img, name):
    cv2.imwrite(f'{DIR}/image/result/{name}.png', img)


def extract_inside(contours, hierarchy, debug=False):
    extracted = []
    contours_drawed = image.copy()
    if debug:
        print(f'len: {len(contours)}')
        print(hierarchy)

    for index in range(len(contours)):
        if hierarchy[0, index, 2] != -1 or cv2.contourArea(contours[index]) < 8000:
            continue
        extracted.append(contours[index])

        if debug:
            cv2.drawContours(contours_drawed, contours, index, (255, 0, 255), 10)

        print(f'{index} : {cv2.contourArea(contours[index])}')

    if debug:
        write_out(contours_drawed, 'out_contours')

    return extracted


width, height = image.shape[:2]

extracted = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)[:, :, 1]

write_out(extracted, 'after_cvt')

ret, thrshld_ex = cv2.threshold(extracted, 0, 255, cv2.THRESH_OTSU)

write_out(thrshld_ex, 'thrshld')

kernel = np.ones((3, 1), np.uint8)
thrshld_ex = cv2.morphologyEx(thrshld_ex, cv2.MORPH_OPEN, kernel)

write_out(thrshld_ex, 'thrshld_ex')

_, contours, hierarchy = cv2.findContours(thrshld_ex, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

inside_contours = extract_inside(contours, hierarchy, True)

print(f'extracted {len(inside_contours)} countours')

clr_img_cp = image.copy()
for circle in inside_contours:
    colors = []
    av_color = 0
    M = cv2.moments(circle)
    center_of_circle = (int(M['m10']/M['m00']), int(M['m01']/M['m00']))
    cnt = 0
    for approx in circle:
        if cnt == 20:
            break
        cv2.circle(clr_img_cp, (approx[0, 0] - 1, approx[0, 1] - 1), 1, (255, 0, 255), 1)
        colors.append(image[approx[0, 1] - 1, approx[0, 0] - 1])
        cnt += 1
    cav = np.mean(colors, axis=0)
    cv2.circle(clr_img_cp, center_of_circle, 100, cav, 20)

write_out(clr_img_cp, 'out')

Es sieht so aus, wenn ich das, was ich zuvor in der Erkennungszusammenfassung geschrieben habe, in den Quellcode lege. Nachdem ich so ein Prototyping mit "Python" durchgeführt hatte, portierte ich es auf "Objective-C" und ließ es von @Taillook mit Swift überbrücken.

Ergebnis

Die Ergebnisse jedes der vier Prozesse werden veröffentlicht.

In HSV-Farbraum konvertieren und nur S extrahieren

extract_s_of_hsv.py


cv2.cvtColor(image, cv2.COLOR_BGR2HSV)[:, :, 1] # 0: H, 1: S, 2: V

image.png

Zu diesem Zeitpunkt ist es fast binärisiert. Es ist zu viel.

Binarisierung durch "Diskriminierungsanalysemethode"

Geben Sie einfach "cv2.THRESH_OTSU" an. Einfach.

thresold_with_otsu.py


cv2.threshold(extracted, 0, 255, cv2.THRESH_OTSU)

image.png

Wenn es ein wenig Rauschen gibt, wenden Sie "Morphology EX" an, um das Rauschen zu entfernen.

Seitenerkennung

OpenCV ist schon erstaunlich. findContours ist unglaublich. Ich habe die Zeitung vorerst gelesen, aber sie ist zu pervers, um selbst die strukturellen Informationen der Seiten zu erkennen.

find_contours_with_structure.py


_, contours, hierarchy = cv2.findContours(thrshld_ex, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

In "Hierarchie" wird ** gespeichert, welche Indexseite in "Konturen" ** neben der Indexseite ** oder ** enthalten ist **. Es ist zu viel.

image.png

Die Seiten werden durch eine Reihe von Punkten dargestellt und sind lila gezeichnet.

Seitenfarbe extrahieren + zeichnen

Dies ist ein Push. Vielen Dank an numpy, dass es so einfach ist, die Farben zu mitteln.

sampling_color_and_averaging_and_plotting.py


clr_img_cp = image.copy()
for circle in inside_contours:
    colors = []
    av_color = 0
    M = cv2.moments(circle)
    center_of_circle = (int(M['m10']/M['m00']), int(M['m01']/M['m00']))
    cnt = 0
    for approx in circle:
        if cnt == 20:
            break
        cv2.circle(clr_img_cp, (approx[0, 0] - 1, approx[0, 1] - 1), 1, (255, 0, 255), 1)
        colors.append(image[approx[0, 1] - 1, approx[0, 0] - 1])
        cnt += 1
    cav = np.mean(colors, axis=0)
    cv2.circle(clr_img_cp, center_of_circle, 100, cav, 20)

image.png

Der Mittelpunkt der Figur wird bestimmt und dort ein Kreis mit der Durchschnittsfarbe gezeichnet. (Wenn Sie sich dieses Bild genau ansehen, sind die Zielpixel von 20 Samples lila gefärbt.) Es fühlt sich gut an mit fast der gleichen Farbe wie die Seite.

Zusammenfassung

Also habe ich hier einen Gedenkgottesdienst für das Bildverarbeitungsprogramm gemacht, das ich als Student gemacht habe: Sarg:

Es war ein Spiegelbild aus meiner Sicht, aber ich hoffe, Sie können dies lesen und die Möglichkeit von "Python" + "OpenCV" spüren.

Die einzige Einschränkung ist, dass "OpenCV" verwendet werden kann, indem aus vielen Fällen gelernt wird, ohne die Theorie zu kennen, aber ich denke, dass die Theorie der erste Schritt ist, um den kürzesten Weg für die Anwendung von Mitteln zur Lösung von Problemen abzuleiten. Daher ist ** Informationstechnik wichtig **. Ich habe nur die Last-Minute-Theorie, weil ich leicht und leicht war.

Das Folgende kann jedoch mit Sicherheit gesagt werden.

darüber. Eigentlich habe ich "OpenCV" von "Rust" ausprobiert, bevor ich diesen Artikel geschrieben habe, aber es war nicht gut im Vergleich zur Benutzerfreundlichkeit von "Python" + "OpenCV". Nun, ich bin es nicht gewohnt, "Rust" zu implementieren, daher ist es vielleicht nicht hilfreich, aber: yum:

Es ist "Python", ist es nicht langsam? Es scheint eine Geschichte zu geben, aber ohne Zeichnung geht es um ** 0,3 [Sek] **. Es ist nur eine "C-Bindung". Toll. Selbst auf der Fahrrad-Shopping-Site cyma-cyma-, an der ich beteiligt bin, habe ich irgendwie die Motivation zur Bilderkennung gewonnen, deshalb möchte ich meine Stärke demonstrieren.

@shimura_atsushi hat 2 Artikel in Ateam cyma Adventskalender 2019 geschrieben. Wenn Sie also interessiert sind, bitte.

abschließend

Yuruyuru New Graduate 1. Klasse Adventskalender 2019, wie war dein 23. Tag?

Am 24. Tag ist der Front-End-Ingenieur @ cheez921 an der Reihe, der auch das Back-End versteht. Duell, Standby!

Gutes ** Weihnachten **, gutes ** Jahresende **, gutes ** neues Jahr **, gutes ** Bilderkennung **.

Recommended Posts

Eine Geschichte, die die elektronische Bewertung von Prüfungen mit Bilderkennung unterstützt
Die Geschichte, ein Modul zu erstellen, das E-Mails mit Python überspringt
Eine Geschichte, die die Gegenwart von Qiita mit Qiita API + Elasticsearch + Kibana visualisiert
Ich habe versucht, Bilder mit CIFAR-10 mit Keras-Learning- zu erkennen.
Ich habe versucht, Bilder von CIFAR-10 mit Keras-Bilderkennung zu erkennen.
Die Geschichte der Erstellung einer Webanwendung, die umfangreiche Lesungen mit Django aufzeichnet
Eine Geschichte, die den Aufwand für Betrieb / Wartung reduziert
Bilderkennung mit Keras
Die Geschichte, eine harte Zeit mit der gemeinsamen Menge HTTP_PROXY = ~ zu haben
Erstellen Sie einen Chatbot, der die kostenlose Eingabe mit Word2Vec unterstützt
Eine Geschichte, die die Lieferung von Nico Nama analysierte.
Eine Geschichte, die stolperte, als ich mit Transformer einen Chat-Chat-Bot erstellte
Technologie, die Jupiter unterstützt: Traitlets (Geschichte des Entschlüsselungsversuchs)
Die Geschichte, wie man mit discord.py einen Fragenkasten-Bot erstellt
Anwendung der CNN2-Bilderkennung
Bilderkennung mit Keras + OpenCV
Ein Überblick über DELG, eine neue Methode zum Extrahieren von Bildmerkmalen, die mit Kaggle Aufmerksamkeit erregt
Eine Geschichte, bei der es mir schwer fiel, Grafiken mit matplotlib anzuzeigen
Die Geschichte des Erstellens eines Bots, der aktive Mitglieder in einem bestimmten Slack-Kanal mit Python anzeigt
Eine Geschichte, die mit der Installation der maschinellen Lernbibliothek JAX zusammenhängt
[Statistik] Erfassen Sie das Bild der zentralen Polbegrenzungstheorie mit einem Diagramm
Die Geschichte, einen Standardtreiber für db mit Python zu erstellen.
Die Geschichte der Erstellung einer Website, auf der die Veröffentlichungsdaten von Büchern aufgeführt sind
Die Geschichte, ein Tool zum Laden von Bildern mit Python zu erstellen ⇒ Speichern unter
Bilderkennung von Früchten mit VGG16
Die Geschichte des Exportierens eines Programms
So rufen Sie eine POST-Anfrage auf, die Japanisch (Shift-JIS) mit Anfragen unterstützt
Technologie, die einen Geldwerfdienst unterstützt, der ein Blog mit einem Tag monetarisieren kann
Die Geschichte eines Parksensors in 10 Minuten mit dem GrovePi + Starter Kit
Die Geschichte, wie man mit Python einen 100-Yen-Frühstücks-Bot für die Universität macht
Erstellen Sie mithilfe des TensorFlow-Faltungsnetzwerks einen Klassifikator mit einer Handschrifterkennungsrate von 99,2%
Die Geschichte der Entwicklung einer WEB-Anwendung, die automatisch Fangkopien generiert [MeCab]
Die Geschichte einer Soundkamera mit Touch Designer und ReSpeaker
Die Geschichte, ein Paket zu erstellen, das den Betrieb von Juman (Juman ++) & KNP beschleunigt