Der Umriss einer Karte (Nanaco-Karte) mit der gleichen Größe wie die Lizenz wird von ** OpenCV ** erkannt, und es wird eine ** Projektionskonvertierung ** durchgeführt, um den Inhalt der Karte besser lesbar zu machen **.
Bereit zum Lesen von Inhalten mit OCR (das Lesen von Inhalten wird im nächsten Artikel vorgestellt) ――Daher ich keine OCR mache, verwende ich stattdessen dieselbe Nanaco-Karte
** Von diagonal oben ** Die Karte, die ich genommen habe ...
→ Sie können jetzt ** den Winkel korrigieren und die Karte ** so anzeigen
→
Ich benutze Pipenv.
Pipenv
brew install pipenv
pipenv install numpy matplotlib opencv-contrib-python pyocr
pipenv install jupyterlab --dev
Drei Bilder mit der folgenden Konfiguration
--nanaco.jpeg
(auf einfachste Weise aufgenommen)
--nanaco_skew.jpeg
(so aufgenommen, dass die Form der Karte aus einem Winkel verzerrt ist)
--nanaco_in_hand.jpeg
(aufgenommen, während Sie es auf einem weißen Hintergrund in der Hand halten)
Ich werde versuchen. Der Quellcode verwendet das Jupyter-Notizbuch "card.ipynb".
.
├── Pipfile
├── Pipfile.lock
├── images
│ ├── nanaco.jpeg
│ ├── nanaco_in_hand.jpeg
│ └── nanaco_skew.jpeg
└── notebooks
└── card.ipynb
pipenv run jupyter lab
notebooks / card.ipynb
und führen Sie Folgendes in der Zelle aus (führen Sie alle anderen Skripte in der Zelle aus).%matplotlib inline
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('../images/nanaco_skew.jpeg')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
Ich bin neugierig auf die Skala von "matplotlib", aber es ist mir egal, aber die Koordinaten sind leicht zu verstehen, also werde ich so weitermachen, wie es diesmal ist.
#Graustufen
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(gray_img)
plt.gray()
In vielen Tutorials und Artikeln wurde der Schwellenwert für die Binärisierung auf einen Wert von etwa "200" fest codiert und so behandelt, als ob er manuell bestimmt worden wäre. In diesem Artikel habe ich ** Logik aufgenommen, die dynamisch (automatisch) den Schwellenwert bestimmt **
import numpy as np
#Nanaco ist 0.Über 2 sieht gut aus. Wenn Sie eine Lizenz haben, müssen Sie diese möglicherweise erneut einstellen
card_luminance_percentage = 0.2
# TODO:Leistungsausblick
def luminance_threshold(gray_img):
"""
Wert in Graustufen(Helligkeit genannt)Aber`x`Die Anzahl der oben genannten Punkte beträgt 20%Berechnen Sie das maximale x, das überschreitet
Jedoch,`100 <= x <= 200`Zu
"""
number_threshold = gray_img.size * card_luminance_percentage
flat = gray_img.flatten()
# 200 -> 100
for diff_luminance in range(100):
if np.count_nonzero(flat > 200 - diff_luminance) >= number_threshold:
return 200 - diff_luminance
return 100
threshold = luminance_threshold(gray_img)
print(f'threshold: {threshold}')
Die Schwellenwerte für die drei Bildtypen wurden diesmal wie folgt berechnet.
Zum Beispiel funktionierte es in "nanaco_skew.jpeg " nicht, wenn der Schwellenwert (üblicherweise) "200" war, wahrscheinlich aufgrund der Menge des reflektierten Lichts. Wenn Sie "138" verwenden, das aus dem obigen Quellcode berechnet wurde, können Sie später den Umriss der Karte erhalten.
nanaco.jpeg | nanaco_skew.jpeg | nanaco_in_hand.jpeg | |
---|---|---|---|
Binarisierungsschwelle | 200 | 138 | 199 |
Bild | ![]() |
![]() |
![]() |
_, binarized = cv2.threshold(gray_img, threshold, 255, cv2.THRESH_BINARY)
plt.imshow(cv2.cvtColor(binarized, cv2.COLOR_BGR2RGB))
contours, _ = cv2.findContours(binarized, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#Wählen Sie die mit der größten Fläche aus
card_cnt = max(contours, key=cv2.contourArea)
#Zeichnen Sie Konturen auf das Bild
line_color = (0, 255, 0)
thickness = 30
cv2.drawContours(img, [card_cnt], -1, line_color, thickness)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
Die Projektionskonvertierung (Winkelkorrektur) wird basierend auf den oben erfassten Konturinformationen durchgeführt.
#Ungefähre Kontur mit konvex
#Fester Wert von 0 für die Gesamtlänge der Kontur.Das Multiplizieren eines Koeffizienten von 1 reicht aus
#Es scheint, dass die Einstellung des Koeffizienten unter der Voraussetzung, dass die Karte bis zu einem gewissen Grad ordnungsgemäß kopiert wird, fast unnötig ist.(Kann für die OCR-Anpassung erforderlich sein)
epsilon = 0.1 * cv2.arcLength(card_cnt, True)
approx = cv2.approxPolyDP(card_cnt, epsilon, True)
#Kartenbreite(Da die Karte im Bild vertikal ist, werden Breite und Höhe während der Projektionskonvertierung umgekehrt.)
card_img_width = 2400 #Angemessener Wert
card_img_height = round(card_img_width * (5.4 / 8.56)) #Lizenzration(=Nanaco-Verhältnis)Berechnet durch Teilen durch
src = np.float32(list(map(lambda x: x[0], approx)))
dst = np.float32([[0,0],[0,card_img_width],[card_img_height,card_img_width],[card_img_height,0]])
projectMatrix = cv2.getPerspectiveTransform(src, dst)
#Da die Zeile früher überschrieben wurde, holen Sie sich das Bild erneut
img = cv2.imread('../images/nanaco_skew.jpeg')
transformed = cv2.warpPerspective(img, projectMatrix, (card_img_height, card_img_width))
plt.imshow(cv2.cvtColor(transformed, cv2.COLOR_BGR2RGB))
**erledigt! !! ** Die schrägen Buchstaben sind jetzt gerade!
Danach denke ich darüber nach, den Inhalt mit OCR unter Verwendung einer tatsächlichen Lizenz zu lesen, aber ich habe auch ein wenig mit dem aktuellen Nanaco versucht. Obwohl es notwendig ist, den zu lesenden Teil einzuschränken, ist dies grob getan.
Unter Verwendung des Bildes von "nanaco_in_hand.jpeg " habe ich OCR auf das zuletzt erhaltene Bild angewendet, wobei "pyocr" für das gesamte Bild verwendet wurde.
Sie können dies erreichen, indem Sie dasselbe Skript wie oben für nanaco_in_hand.jpeg
ausführen (leicht diagonal ...)
Ich habe versucht, dieses Bild mit "pyocr + tesseract" gemäß dem Tutorial in Text umzuwandeln. [^ ocr]
Innerhalb dieses Plans zur Verwendung der Nanaco-Karte
Weitere Informationen zur Verwendung der Kieferkarte finden Sie in der Mitgliedschaftsvereinbarung. Fünf
Akos Karte ist ein Mitgliedsshop mit der Nanaco-Markierung auf der rechten Seite. Sie können das elektronische Management und den elektronischen Manager auf der Karte verwenden.
Sie können Ihr Guthaben bestätigen.
Biegen Sie die Karte nicht, geben Sie ihr keinen großen Aufprall und lassen Sie sie nicht bei hohen Temperaturen oder wenn sie magnetisiert ist.
Akos Karte und der elektronische Manager auf der Karte sind nicht einlösbar.
Die maximale Gebühr für Akos Karte beträgt 50.000 Yen.
Die Ako-Karte kann nur von dem Mitglied verwendet werden, das die Mitgliedervereinbarung genehmigt und das Feld für den Namen des Mitgliedsbüros unterschrieben hat.
Das Eigentum an Akos Karte gehört der Aktiengesellschaft Seven Card Service und kann nicht verliehen oder an eine andere Person übergeben werden.
Ist es ein Ort, der schlampig ist, obwohl man es grob macht? Ich werde die Genauigkeit dieses Bereichs mit einer Lizenz verbessern und fortfahren. (Es ist ziemlich interessant, dass "●" als "A" erkannt wird)
[^ Binärisierung]: RGB-Bild mit Informationen zu jedem Punkt (256x256x256) → Konvertiert das Binärbild der Binärinformationen zu jedem Punkt (2 = 1/0). Dies ist ein Prozess, der die Konturextraktion erleichtert.
[^ opencv]: opencv-Contrib-Python
importiert das Contrib
-Modul zusätzlich zu Open-Python
. Es scheint, dass "cv2" für "opencv-python" in Ordnung ist. Soweit das offizielle Dokument ersichtlich ist, scheint es jedoch besser zu sein, diese Notation für neue Elemente zu verwenden. (Referenz: https://pypi.org/project/opencv-python/)
[^ ocr]: Dieser Artikel war ebenfalls hilfreich! Eine Installation wie tesseract ist erforderlich.