[PYTHON] Recherche de mots composés à phase identique avec opencv

introduction

Connaissez-vous un jeu de cartes appelé Topolo Memory? C'est un jeu dans lequel si vous trouvez une figure de la même phase écrite sur une carte, vous vous disputez la carte. Quand j'ai joué à ce jeu avec un ami, j'ai ajouté un jeu pour rechercher des idiomes avec la même phase, donc j'analyserai la solution de cela à l'aide d'opencv.

environnement

OS:macOSX Python: 3.6.8 opencv: 4.0.0.21 numpy: 1.15.0

veux dire

Utilisez le dictionnaire mecab comme dictionnaire. Recherche dans tous les dictionnaires de nomenclature (228297).

Extraction

Ouvrez les fichiers csv un par un et extrayez uniquement les mots-clés. Convertissez en numpy.array puis découpez. Connectez tout cela.

csvnoun.py


import csv
import codecs
import numpy as np
from functools import reduce
csvs = [
    "Noun.csv",
    "Noun.adjv.csv",
    "Noun.adverbal.csv",
    "Noun.demonst.csv",
    "Noun.nai.csv",
    "Noun.name.csv",
    "Noun.number.csv",
    "Noun.org.csv",
    "Noun.others.csv",
    "Noun.place.csv",
    "Noun.proper.csv",
    "Noun.verbal.csv"
]
filedelimitor = "~/mecab-ipadic-2.7.0-20070801/"
def csv_1(csv_file):
    with codecs.open(filedelimitor+csv_file, "r","euc_jp") as f:
        reader = csv.reader(f)
        csv_words = [k for k in reader]
        csv_words_np = np.array(csv_words)
        return(csv_words_np[:,0].tolist())

words = reduce(lambda x,y:x+y,[csv_1(k) for k in csvs])
print(words[0:10])
print("Quantité:",len(words))

Cela prend environ 2 secondes dans l'environnement de la main.

produire

Comme il est difficile de sortir des caractères japonais avec opencv, il est généré avec oreiller.

char_img.py


import cv2
from PIL import Image, ImageDraw, ImageFont
import numpy as np

img = Image.new("L",(500, 500),"white")
char = "Ah"
jpfont = ImageFont.truetype("/System/Library/Fonts/Hiragino Kaku Gothic W4.ttc",500)
draw = ImageDraw.Draw(img)
draw.text((0,0),char,font=jpfont,fill="black")
img_cv = np.array(img,dtype=np.uint8)

Si vous souhaitez l'exécuter sur un autre système que OSX, remplacez jpfont par une police appropriée.

une analyse

Depuis opencv a une fonction appelée cv2.findContours, utilisez ceci. Une fonction qui détecte le contour d'une image binaire. (Référence: http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_contours/py_contours_begin/py_contours_begin.html) Lorsque l'indicateur (deuxième argument) est défini sur RETR_TREE, la hiérarchie conserve toute la structure hiérarchique. Utilisez cette structure hiérarchique. la hiérarchie est stockée dans la structure [Next, Previous, First_Child, Parent]. Parmi ceux-ci, seul le parent est utilisé car la structure peut être trouvée en examinant tous les parents. La recherche à l'aide de First_child et Next nécessite moins de calculs, mais même les caractères complexes ne dépassent pas 20 parties, nous recherchons donc tout. Puisque cv2.findContours définit l'arrière-plan sur 0, celui avec 0 comme enfant est la ligne la plus externe. Puisque la partie ligne a un parent pair, comptez les éléments qui ont un index pair comme parent. Enfin, il convertit la chaîne caractère par caractère, la concatène, la trie et la renvoie pour la recherche.

string_topology.py


topology_dic = {}
jpfont = ImageFont.truetype("/System/Library/Fonts/Hiragino Kaku Gothic W4.ttc",500)

def char_topology(char):
    if char in topology_dic:
        return topology_dic[char]
    else:
        img = Image.new("L",(500, 500),"white")
        draw = ImageDraw.Draw(img)
        draw.text((0,0),char,font=jpfont,fill="black")
        img_cv = np.array(img,dtype=np.uint8)
        ret,thresh = cv2.threshold(img_cv,127,255,0)
        contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
        img_cv_con = np.zeros((500,500,3),np.uint8)
        cv2.drawContours(img_cv_con,contours,-1,(0,255,0),3)
        parent = [k[3] for k in hierarchy[0]]
        topology = [parent.count(k)
                    for k in range(len(parent)) if parent[k]%2 == 0]
        topology_dic[char] = topology
        return topology

def string_topology(string):
    topology = reduce(lambda x,y:x+y,[char_topology(k) for k in string])
    topology.sort()
    return topology

Chercher

Convertit la chaîne de liste en topologie et génère une correspondance.

search.py


in_topology = string_topology(sys.argv[1])
print(in_topology)
for k in words:
    if in_topology == string_topology(k):
        print(k)

code

Si vous les connectez tous, cela ressemblera à ceci.

same_topology.py


import cv2
import os
from PIL import Image, ImageDraw, ImageFont
import numpy as np
from functools import reduce
import csv
import codecs
import sys

csvs = [
    "Noun.csv",
    "Noun.adjv.csv",
    "Noun.adverbal.csv",
    "Noun.demonst.csv",
    "Noun.nai.csv",
    "Noun.name.csv",
    "Noun.number.csv",
    "Noun.org.csv",
    "Noun.others.csv",
    "Noun.place.csv",
    "Noun.proper.csv",
    "Noun.verbal.csv"
]
filedelimitor = "~/mecab-ipadic-2.7.0-20070801/"
def csv_1(csv_file):
    with codecs.open(filedelimitor+csv_file, "r","euc_jp") as f:
        reader = csv.reader(f)
        csv_words = [k for k in reader]
        csv_words_np = np.array(csv_words)
        return(csv_words_np[:,0].tolist())

words = reduce(lambda x,y:x+y,[csv_1(k) for k in csvs])

topology_dic = {}
jpfont = ImageFont.truetype("/System/Library/Fonts/Hiragino Kaku Gothic W4.ttc",500)

def char_topology(char):
    if char in topology_dic:
        return topology_dic[char]
    else:
        img = Image.new("L",(500, 500),"white")
        draw = ImageDraw.Draw(img)
        draw.text((0,0),char,font=jpfont,fill="black")
        img_cv = np.array(img,dtype=np.uint8)
        ret,thresh = cv2.threshold(img_cv,127,255,0)
        contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
        img_cv_con = np.zeros((500,500,3),np.uint8)
        cv2.drawContours(img_cv_con,contours,-1,(0,255,0), 3)
        parent = [k[3] for k in hierarchy[0]]
        topology = [parent.count(k)
                    for k in range(len(parent)) if parent[k]%2 == 0]
        topology_dic[char] = topology
        return topology

def string_topology(string):
    topology = reduce(lambda x,y:x+y,[char_topology(k) for k in string])
    topology.sort()
    return topology



in_topology = string_topology(sys.argv[1])
print(in_topology)
for k in words:
    if in_topology == string_topology(k):
        print(k)

Résultat de sortie


$ python topology.py Tokyo
[0, 0, 0, 1, 4]
Brochettes grillées
Support de lotus
Prends un cul
Branche
Extraction
Somme
Bel enfant
Atteindre
affaires futures
Cas
coït
Voiture d'incendie
Finesse
Argent de retour
fermoir
énorme projectile
...

Un mot composé qui a la même phase que le premier argument est sorti. Dans l'environnement de la main, il sera émis dans environ 30 secondes.

Supplément

Cette fois, nous n'avons pas traité les caractères tofu, mais ça devrait l'être (je pense que le dictionnaire ipa peut sortir sans devenir tofu ...). Il a été souligné que les "temps" et "loro" peuvent ne pas être du même type, mais du point de vue de la continuité, ils devraient être du même type. ~~ Peut-être. ~~ (Je pense que je n'ai pas de connaissances en mathématiques, alors j'apprécierais qu'un expert commente)

Recommended Posts

Recherche de mots composés à phase identique avec opencv
Rechercher le nom de la fonction OpenCV
Rechercher des fichiers avec l'extension spécifiée
Carte thermique pour la recherche de grille avec Matplotlib
[Python] Lire des images avec OpenCV (pour les débutants)
Raisonnement causal et recherche causale par Python (pour les débutants)
Recherche séquentielle avec Python
Détecter le retour du chat avec OpenCV
Binarisation avec OpenCV / Python
[Boto3] Rechercher des utilisateurs Cognito avec l'API List Users
Dichotomie avec python
Rechercher une base de données avec db.py
Augmentation des données avec openCV
OpenCV pour les débutants en Python
TopView facile avec OpenCV
Trébucher avec opencv3 de homebrew
Reconnaissance faciale avec OpenCV de Python
"Traitement Apple" avec OpenCV3 + Python3
Essayez la détection des bords avec OpenCV
Liste de recherche des éléments en double
Créer / rechercher / créer une table avec PynamoDB
Édition d'image avec python OpenCV
Capture de caméra avec Python + OpenCV
Recherche de bits complète avec Go
[Python] Utilisation d'OpenCV avec Python (basique)
Installation d'OpenCV3 pour Python3 @macOS
Binariser les données photo avec OpenCV
Rechercher des chaînes dans les fichiers
Chargement de la vidéo en boucle avec opencv
Recherche de bits complète avec Python
Je ne peux pas effectuer de recherche avec # google-map. ..
Rechercher numpy.array pour Vrai consécutif
Obtenez des fonctionnalités d'image avec OpenCV
Reconnaissance faciale / coupe avec OpenCV
Les moteurs de recherche fonctionnent avec python
Rechercher des tweets Twitter avec Python
Essayez OpenCV avec Google Colaboratory
Création d'un classificateur en cascade avec opencv
Rationalisez la recherche Web avec Python
Utiliser OpenCV avec Python @Mac
Reconnaissance d'image avec Keras + OpenCV
Détection de visage d'anime avec OpenCV
Créez une illusion rayée avec correction gamma pour Python3 et openCV3
Créez un effecteur pour la visioconférence avec Spout + OpenCV + dlib (Partie 1)