Bienvenue au 23ème jour du Calendrier de l'Avent des nouveaux diplômés de Yuruyuru 2019. Je suis un jeune diplômé, @NamedPython
Aujourd'hui, c'est mon exploit caché ** Reconnaissance d'image avec OpenCV **.
J'avais décidé à l'avance d'écrire sur la reconnaissance d'image, mais il était difficile de trouver quelque chose de nouveau, alors j'ai fait de mon mieux pour l'écrire en classe, mais je ne l'ai proposé nulle part ~~ ** Feuille de réponses Je vais laisser un enregistrement de l'extraction de la zone ** ici: crayon2:
J'ai dit que c'était une classe, mais le nom de la classe est ** Application de programmation **, et travaillons en équipe pour résoudre des problèmes grâce au développement de logiciels, impliquant ce que nous apprenons habituellement en classe et les compétences de nos étudiants. est.
Alors, quel est le thème de la résolution de problèmes?
** Facilitez-vous la notation électronique de vos examens **: priez:
C'était ça. En premier lieu, au moment de la notation électronique, c'est assez maintenant et jeune, mais si vous résumez les exigences
C'était comme ça.
En fait, un an avant ce cours,
--Backend API, web front @NamedPython --iOS @Taillook --Android @ youta1119
Nous avons formé l'équipe la plus solide et avons reçu de vives critiques. En conséquence, le nombre de membres de l'équipe était limité: froncement de sourcils2:
Malgré tout, j'ai attiré @Taillook et un autre bon camarade de classe pour former une équipe de trois personnes.
Avec l'équipe de l'équipe mentionnée ci-dessus, j'ai tiré ** le gars qui peut écrire iOS **.
Comme c'est un gros problème, j'ai proposé un système avec la configuration suivante qui vous permet de piloter iOS de n'importe quoi à n'importe quoi (extrait de la présentation de l'annonce finale). Merci pour l'implémentation autour d'iOS, @Taillook.
J'ai fait de mon mieux avec Keynote pour ce chiffre. Les polices sont ** M + ** et ** Tsukushi B Maru Gothic **.
BGR
à l'espace HSV
et extraire uniquement S
(canal de saturation)findContours
--Depuis que plusieurs côtés sont détectés, structurer les côtés avec cv2.RETR_TREE
--Ceux avec plus de côtés à l'intérieur OU
Passer la zone en dessous d'un certain niveaux -1
, y -1
) du côté extraitÀ ce moment-là, j'ai reçu une véritable feuille de réponses pour la vérification des opérations, mais j'avais le sentiment que les droits autour de moi seraient gris pour l'apporter ici, alors j'ai utilisé le pouvoir des ** artisans de Pages ** pour générer un échantillon.
Eh bien, c'est presque ennuyeux, donc Dawn et le code source.
Nous avons préparé un Dockerfile
tel que FROM jjanzic / docker-python3-opencv
afin que vous puissiez le développer n'importe où. Au final, la partie reconnaissance d'image était exagérée car je l'ai entièrement développée.
Le contenu de Docker est le suivant.
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')
Cela ressemble à ceci lorsque je dépose ce que j'ai écrit dans le résumé de reconnaissance plus tôt dans le code source. Après avoir prototypé avec Python
comme celui-ci, je l'ai porté sur ʻObjective-C` et ai demandé à @Taillook de le relier à Swift.
--Convertir en espace colorimétrique «HSV» et extraire uniquement «S» --Validation par "méthode d'analyse de discrimination"
Les résultats de chacun des quatre processus sont affichés.
extract_s_of_hsv.py
cv2.cvtColor(image, cv2.COLOR_BGR2HSV)[:, :, 1] # 0: H, 1: S, 2: V
À ce stade, il est presque binarisé. C'est trop.
Spécifiez simplement cv2.THRESH_OTSU
. Facile.
thresold_with_otsu.py
cv2.threshold(extracted, 0, 255, cv2.THRESH_OTSU)
S'il y a un peu de bruit, appliquez la «morphologie EX» pour supprimer le bruit.
OpenCV est déjà incroyable. «findContours» est incroyable. J'ai lu le journal pour le moment, mais il est trop perverti pour reconnaître même les informations structurelles des côtés.
find_contours_with_structure.py
_, contours, hierarchy = cv2.findContours(thrshld_ex, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
Dans hierarchy
, ** quel côté d'index dans contours
est ** à côté du côté d'index ** ou ** est inclus ** est stocké. C'est trop.
Les côtés sont représentés par un ensemble de points et sont dessinés en violet.
C'est une poussée. Merci à numpy
pour avoir rendu si facile la moyenne des couleurs.
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)
Le centre de la figure est déterminé et un cercle y est dessiné avec la couleur moyenne. (En fait, si vous regardez attentivement cette image, les pixels cibles de 20 échantillons sont colorés en violet.) Cela fait du bien avec presque la même couleur que le côté.
Donc, j'ai fait un service commémoratif ici pour le programme de traitement d'image que j'ai fait quand j'étais étudiant: cercueil:
C'était une réflexion de mon point de vue, mais j'espère que vous pourrez lire ceci et sentir la possibilité de Python
+ ʻOpenCV`.
La seule mise en garde est que «OpenCV» peut être utilisé en apprenant de nombreux cas sans connaître la théorie, mais j'estime que la théorie est la première étape pour dériver la voie la plus courte pour appliquer des moyens pour résoudre des problèmes. Par conséquent, ** l'ingénierie de l'information est importante **. Je n'ai que la théorie de dernière minute parce que j'étais léger et léger.
Cependant, ce qui suit peut être dit à coup sûr.
―― ʻOpenCV est incroyable --
Python + ʻOpenCV
est facile à faire
numpy
à propos de ça. En fait, avant d'écrire cet article, j'ai essayé ʻOpenCV de
Rust, mais ce n'était pas bon comparé à la facilité d'utilisation de
Python + ʻOpenCV
. Eh bien, je ne suis pas habitué à implémenter Rust
, donc cela peut ne pas être utile, mais: yum:
C'est "Python", n'est-ce pas lent? Il semble y avoir une histoire, mais hors dessin, elle est d'environ ** 0,3 [sec] **. C'est juste une "liaison C". Génial. Même sur le site de vente de vélos cyma-cyma-, dont je suis impliqué dans le développement, je me sens plus motivé pour reconnaître les images, je voudrais donc montrer ma force.
@shimura_atsushi a écrit 2 articles dans Ateam cyma Advent Calendar 2019, donc si vous êtes intéressé, s'il vous plaît.
Yuruyuru New Graduate 1st Grade Advent Calendar 2019, comment s'est passé votre 23e jour?
Le 24ème jour est au tour de l'ingénieur front-end @ cheez921, qui comprend également le back-end. Duel, veille!
Bon ** Noël **, bon ** fin d'année **, bon ** nouvel an **, bon ** reconnaissance d'image **.