[Python] J'ai écrit un code simple qui génère automatiquement AA (Ascii Art)

introduction

Tout le monde, vous connaissez ** AA (Ascii Art) **. C'est un savoir-faire, n'est-ce pas? Une fois votre image préférée, votre personnage préféré ou vous-même? Avez-vous déjà voulu faire des AA? Cette fois, je n'irai pas aussi loin que l'artisan AA, mais j'ai écrit un code qui ** génère facilement des AA ** à partir de mon image préférée en utilisant mes personnages préférés, alors j'aimerais vous le présenter. Je vais.

À titre d'exemple, le code présenté dans cet article peut être utilisé pour les conversions suivantes. Editeur d'image: Irasutoya

Méthode

Les AA fabriqués par des artisans AA expriment souvent efficacement les contours avec / etc. et expriment des illustrations avec un petit nombre de caractères, mais cette fois, je veux le faire avec la force brute sans faire des choses aussi compliquées pense. La méthode est simple, ** Appliquez les caractères par ordre de densité à 256 niveaux de luminosité sur l'échelle de gris **. Allons-y.

la mise en oeuvre

Tout d'abord, lisez l'image source de la conversion en échelle de gris et faites-en un tableau Numpy.

AA.py


from PIL import Image
import numpy as np

file_path = "./hogehoge.png "
imag = Image.open(file_path).convert('L')
imarray = np.asarray(imag)

À ce stade, la valeur stockée dans ʻimarray` est un entier de 0 à 255 (2 ^ 8 étapes). C'est la seule préparation côté image.

Ensuite, triez les caractères à utiliser par ordre de densité. Je vais le faire, mais je ne sais pas comment gérer les fichiers de polices, et même si je le fais, je ne peux pas penser à un moyen de mesurer la densité des images au format vectoriel. La méthode que j'ai proposée était de la coller une fois sur une image (raster), puis de la comparer en trouvant la somme ou la moyenne de celle-ci.

AA.py


from PIL import ImageDraw,ImageFont

def make_map(str_list):
    l = []
    font = ImageFont.truetype('msgothic.ttc', 20) #"C:\Windows\Fonts"Dans votre police préférée (ou écrivez à partir du chemin)#S'il n'y a pas d'erreur, c'est OK tel quel
    for i in str_list:
        im = Image.new("L",(20,20),"white") #Créer une image de fond blanc du ciel
        draw = ImageDraw.Draw(im)
        draw.text((0,0),i,font=font) #Insérer des caractères
        l.append(np.asarray(im).mean()) #Tableau Numpy pour calculer et stocker la valeur moyenne
    l_as = np.argsort(l) #Indice de type croissant d'indice de densité
    lenl = len(l)
    l2256 = np.r_[np.repeat(l_as[:-(256%lenl)],256//lenl),np.repeat(l_as[-(256%lenl):],256//lenl+1)] #Ajustez le nombre d'éléments à 256
    chr_map = np.array(str_list)[l2256] #Liste de caractères triée par densité
    return chr_map

Si vous passez une liste de caractères dans cette fonction, elle triera par densité et la renverra sous forme de tableau Nampy.

Au fait, il y a une fonction que j'aime personnellement le Nampy array qui, si vous passez un tableau qui stocke un index comme index, il récupérera l'élément spécifié ( fancy index). Pour donner un exemple

python


import numpy as np

arr=np.array(["Ah","je","U","e","Oh"])
print(arr[[1,1,4,3,2,0]])

production


['je' 'je' 'Oh' 'e' 'U' 'Ah']

** Hmm, j'adore Numpy. ** ** --Parler tranquille-

Cette fois, en utilisant cette fonction, vous pouvez ** le plier en une fois **.

AA.py


str_list = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +-*/%'"+'"!?#&()~^|@;:.,[]{}<>_0123456789') #Préparez les personnages que vous souhaitez utiliser
chr_map = make_map(str_list) #Trier par densité,
aa = chr_map[imarray] #Sorte de fantaisie! !! !!

Oui, cela seul complète les données converties en AA en ** ʻaa` **.

Après cela, vous pouvez l'écrire dans un fichier TXT ou le sortir en standard pour qu'il soit facile à voir.

AA.py


aa = aa.tolist() #Convertir en liste
out_path="./aa.txt"
with open(out_path,"w") as f:
    for i in range(len(imarray)):f.write(''.join(aa[i])+"\n")

Ou

AA.py


aa = aa.tolist()
for i in range(len(imarray)):print(''.join(aa[i]))

c'est tout. C'était facile.

finalement

Modifiez la taille de sortie et sélectionnez pleine largeur / demi-largeur (Référence: [Python] Conversion mutuelle entre pleine largeur et demi-largeur sur une seule ligne (alphabet + numéro + symbole)) Je vais lister ceux qui sont résumés dans la fonction en ajoutant des fonctions détaillées telles que

AA.py


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

def make_map(str_list):
    l=[]
    font = ImageFont.truetype('msgothic.ttc', 20)
    for i in str_list:
        im = Image.new("L",(20,20),"white")
        draw = ImageDraw.Draw(im)
        draw.text((0,0),i,font=font)
        l.append(np.asarray(im).mean())
    l_as=np.argsort(l)
    lenl=len(l)
    l2256=np.r_[np.repeat(l_as[:-(256%lenl)],256//lenl),np.repeat(l_as[-(256%lenl):],256//lenl+1)]
    chr_map=np.array(str_list)[l2256]
    return chr_map

def output(chr_map,imarray,isOutText,out_path):
    aa=chr_map[imarray].tolist()
    if isOutText:
        with open(out_path,"w") as f:
            for i in range(len(imarray)):f.write(''.join(aa[i])+"\n")
    else:
        for i in range(len(imarray)):print(''.join(aa[i]))

def make_AA(file_path,str_list="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +-*/%'"+'"!?#&()~^|@;:.,[]{}<>_0123456789',width=150,isOutText=False,out_path="aa.txt",isFW=False):
    imag=Image.open(file_path).convert('L')
    if isFW:str_list=list(str_list.translate(str.maketrans({chr(0x0021 + i): chr(0xFF01 + i) for i in range(94)})))
    else:str_list=list(str_list)
    imarray=np.asarray(imag.resize((width,width*imag.height//imag.width//(2-int(isFW)))))
    output(make_map(str_list),imarray,isOutText,out_path)

C'est la fonction que make_AA () exécute à partir d'ici lorsqu'elle est utilisée. Les arguments sont file_path: le chemin de l'image d'origine, str_list: la chaîne de caractères à utiliser (chaîne de caractères au lieu de la liste), width: le nombre de caractères horizontaux (la verticale est automatiquement ajustée), ʻisOutText : Si True, il sera généré dans le fichier TXT. (False par défaut), ʻout_path: Destination de sortie du fichier TXT et nom de fichier lorsque isOutText est True, ʻisFW: Défini sur Truelorsque des caractères pleine largeur sont inclus ou lorsque vous voulez sortir en pleine largeur S'il vous plaît (abréviation de pleine largeur) Il peut être utilisé sans spécifier autre chose quefile_path` (dans ce cas, la sortie standard fait 150 caractères de large).

Résumé

C'est facile, mais j'ai introduit un programme pour faire des AA. Au fait, si vous augmentez le contraste de l'image originale en tant que prétraitement, la finition sera rafraîchissante. J'espère que cela vous sera utile. Je vous serais reconnaissant de bien vouloir nous faire part de vos impressions et de vos conseils.

Recommended Posts

[Python] J'ai écrit un code simple qui génère automatiquement AA (Ascii Art)
Un mémo que j'ai écrit un tri rapide en Python
J'ai fait un simple blackjack avec Python
J'ai écrit un code pour convertir quaternion en angle de graissage de type z-y-x avec Python
Créons une base de données clients où le code QR est automatiquement émis en Python
Lecture de code de faker, une bibliothèque qui génère des données de test en Python
[Python] J'ai créé un code de scraping web qui acquiert automatiquement le titre de l'actualité et l'URL de Nihon Keizai Shimbun.
J'ai écrit une classe en Python3 et Java
J'ai écrit une animation que le système linéaire rétrécit avec du code sale mortel
Plug-in Vim qui formate automatiquement les styles Python
J'ai créé un programme pour convertir des images en art ASCII avec Python et OpenCV
[Mac] Je souhaite créer un serveur HTTP simple qui exécute CGI avec Python
mong - J'ai essayé de porter le code qui génère de manière aléatoire le nom du conteneur Docker vers Python -
J'ai écrit du code Python pour créer un diagramme de dépendance de table (vue) (PlantUML) à partir de SQL
Écrivons du code python qui analyse le code go et génère du code go
J'ai créé une VM qui exécute OpenCV pour Python
Un mémo que j'ai touché au magasin de données avec python
J'ai senti que j'avais porté le code Python en C ++ 98.
J'ai écrit un script Python qui exporte tous mes articles à l'aide de l'API Qiita v2
J'ai écrit un code qui dépasse le taux de récupération de 100% dans la prédiction des courses de chevaux en utilisant LightGBM (partie 2)
J'ai essayé de créer un générateur qui génère une classe conteneur C # à partir de CSV avec Python
[Python] J'ai écrit un test de "Streamlit" qui facilite la création d'applications de visualisation.
J'ai fait un jeu de frappe simple avec tkinter de Python
Un code de tri de chaîne qui utilise un algorithme qui génère une permutation.
J'ai écrit rapidement un programme pour étudier la DI avec Python ①
python Extraction de condition de la liste que j'oublie souvent
J'ai créé une application de livre simple avec python + Flask ~ Introduction ~
J'ai essayé "un programme qui supprime les déclarations en double en Python"
Créez le code qui renvoie "A et prétendant B" en python
Je viens d'écrire le matériel original pour l'exemple de code python
J'ai écrit un script qui divise l'image en deux
[Python] J'ai essayé de créer un programme simple qui fonctionne sur la ligne de commande en utilisant argparse
J'ai écrit python en japonais
J'ai fait un texte Python
J'ai fait un circuit simple avec Python (AND, OR, NOR, etc.)
J'ai fait un package qui peut comparer des analyseurs morphologiques avec Python
Je souhaite utiliser un caractère générique que je souhaite décortiquer avec Python remove
[Python] Un mémo que j'ai essayé de démarrer avec asyncio
J'ai écrit le code pour écrire le code Brainf * ck en python
J'ai écrit une fonction pour charger le script d'extension Git en Python
[Python] J'ai créé une visionneuse d'images avec une fonction de tri simple.
J'ai fait un shuffle qui peut être réinitialisé (inversé) avec Python
J'ai écrit un script pour extraire les liens de pages Web en Python
[Python] J'ai écrit une API REST en utilisant AWS API Gateway et Lambda.
J'ai fait un programme qui calcule automatiquement le zodiaque avec tkinter
[python] J'ai créé une classe qui peut écrire rapidement une arborescence de fichiers
J'ai écrit un tri-arbre qui peut être utilisé pour l'implémentation de dictionnaire à grande vitesse en langage D et Python