J'ai fait un programme de création automatique AA. Si vous passez une image avec l'un des «mot-clé», «URL» et «chemin du fichier», elle sera automatiquement convertie en AA.
Bonjour. C'est moi, un bot d'article ennuyeux depuis de nombreuses années. L'autre jour, mon avis comme un Don silencieux était inhabituellement orange. Étonnamment, il semble que ** l'enthousiaste enthousiaste de Jason Stasam ** nous ait suivis. J'ai vu à plusieurs reprises que vous écriviez un article merveilleux rempli d'amour et de courage, mais dans cet article, l'espace No. 1 Idol ** Nikonii ** était à l'écran, donc je vais aussi écrire un article sur Jason Stasam! J'ai mis un point d'honneur à réfléchir. ~~ (mystère) ~~ ** [Cette balise](https://qiita.com/tags/%e3%82%b8%e3%82%a7%e3%82%a4%e3%82%bd%e3%83%b3%e3% 83% bb% e3% 82% b9% e3% 83% 86% e3% 82% a4% e3% 82% b5% e3% 83% a0), je veux que vous soyez populaire! ** **
<détails> <résumé> En plus de Jason </ résumé>
Cela étant dit, je l'aime tellement que chaque fois que je regarde le film de Jason, je fais de l'entraînement musculaire pendant seulement trois jours.
Je les aime tous, mais ce que je préfère, ce sont les dépenses inutiles de Jason Stasam (?) SPY, n'est-ce pas?
C'est bien d'être cool comme un mécanicien, mais décoller comme une adrénaline! muscle! explosion! les poils du torse! J'aime être stupide comme Fu ● k off !!, personnellement.
Même si ce n'est pas le personnage principal comme la mini-mini stratégie et l'arraché, il a une forte présence, et si quelque chose, c'est le plus cool, le travail est resserré et relâché, et je pense que c'est une personne vraiment incroyable.
Je suis seul parce qu'il n'y a pas beaucoup de gens qui peuvent comprendre l'histoire des peintures occidentales à mon âge.
En passant, je recommande M. Bratpit.
C'est solide, mais c'est un très bon travail, alors venez au «Fight Club».
Je suis désolé de polluer le tag avec un si mauvais article.
Mais ** [cette balise](https://qiita.com/tags/%e3%82%b8%e3%82%a7%e3%82%a4%e3%82%bd%e3%83%b3% e3% 83% bb% e3% 82% b9% e3% 83% 86% e3% 82% a4% e3% 82% b5% e3% 83% a0), je veux que vous soyez populaire! **(Deuxième fois)
Vous pouvez voir les articles qui créent automatiquement «AA» avec «Python».
En faisant référence à ce domaine, nous allons l'implémenter avec Pillow
et Numpy
.
Référence 1 ・ Référence 2
Cette fois, je dessinerai un système de teintes AA. En organisant simplement les caractères les plus proches de la luminosité de chaque pixel, vous pouvez enfin créer quelque chose comme ça. La largeur est de 80 caractères, ce qui est juste la taille d'un petit terminal de fenêtre, mais vous pouvez l'ajuster librement pour l'agrandir. Si vous l'agrandissez, la résolution augmentera inévitablement et la finition sera magnifique. comment c'est? Si vous regardez cela lorsque vous êtes fatigué et que vous vous arrêtez, n'entendez-vous pas cette belle voix? What the f●ck are you doing? Get back to work or I will beat the shit out of you! ** (Je ne connais pas la conformité car c'est une voix qui est reproduite dans mon cerveau) ** 100 fois plus énergique, travail croustillant, élevage d'entreprise. Cette fois, c'est un tel projet.
Quoi qu'il en soit, c'est cool de le voir dans AA.
$ uname -a
Linux raspberrypi 5.4.51-v7l+ #1333 SMP Mon Aug 10 16:51:40 BST 2020 armv7l GNU/Linux
$ python -V
Python 3.7.3
$ pip list
Package Version
------------------- ---------
beautifulsoup4 4.9.2
numpy 1.19.2
Pillow 7.2.0
pip 20.2.3
requests 2.24.0
Comme mentionné ci-dessus, il n'y a pas de précédent si seule la création automatique de la teinte AA est effectuée, j'ai donc apporté quelques modifications. Je peux le dire moi-même, mais je pense que c'est devenu plus facile à utiliser.
Attribuez les caractères à utiliser en fonction de la luminosité des pixels. Les caractères utilisés cette fois ne sont que les caractères ASCII d'origine pour améliorer la compatibilité.
jason2aa.py
from PIL import Image, ImageDraw, ImageFont #Oreiller de chargement
import numpy as np #Chargement de numpy
width = 80 #Largeur (nombre de caractères)
font = ImageFont.truetype('DejaVuSansMono.ttf', 16) #Police utilisée pour la création de cartes (par défaut Razzpie)
characters = list('!"#$%&\'(*+,-./0123456789:;<=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[^_`abcdefghijklmnopqrstuvwxyz{|~ ') #Chaîne de caractères à utiliser (chaîne de caractères ASCII)
img_gray = 'hogehoge.png' #Image à convertir
#Fonction de normalisation (0 dans la liste des nombres passés-Normalise à 255 et retourne)
def normalize(l):
l_min = min(l) #Valeur minimale dans la liste
l_max = max(l) #Valeur maximale dans la liste
return [(i - l_min) / (l_max - l_min) * 255 for i in l] #Normaliser chaque élément
#Fonction de calcul de densité (liste des caractères passés{Densité de 256 pas:lettre}Renvoie comme un tableau de dictionnaire de
def calc_density():
l = [] #Déclarez un tableau vide pour mettre la densité
for i in characters: #Répéter pour tous les personnages
im = Image.new('L', (24,24), 'black') #24px en échelle de gris*Création d'images monochromes noires 24px
draw = ImageDraw.Draw(im) #Convertir l'image créée en objet ImageDrow
draw.text((0,0), i, fill='white', font=font) #Dessinez du texte en blanc sur l'image
l.append(np.array(im).mean()) #Ajouter la moyenne de luminosité de l'image où les caractères sont dessinés dans le tableau
normed = normalize(l) #Normaliser le tableau contenant la luminosité de chaque caractère à 256 niveaux
dict = {key: val for key, val in zip(normed, characters)} # {Luminance:lettre}Créer un tableau de dictionnaire de
return sorted(dict.items(), key=lambda x:x[0]) #Trie le tableau du dictionnaire par luminosité et renvoie
maps = calc_density() #Obtenez un tableau de dictionnaire pour la luminosité de chaque caractère
density_map = np.array([i[0] for i in maps]) #Extraire uniquement la luminosité et la mettre dans un tableau numpy
charcter_map = np.array([i[1] for i in maps]) #Extraire uniquement les caractères et les mettre dans un tableau numpy
imarray = np.array(img_gray) #Tableau Numpy de luminosité par pixel de l'image
index = np.searchsorted(density_map, imarray) #Trouvez le caractère avec la luminosité la plus proche de la luminosité du pixel et indexez-le dans un tableau numpy
aa = charcter_map[index] #Index de fantaisie du tableau numpy de caractères dans le tableau numpy ci-dessus
C'est presque un excellent article ici rond pakuri (désolé), mais le comportement lors de l'attribution des caractères a été amélioré.
L'opération est un peu lourde, mais la fonction numpy.searchsorted
peut être utilisée pour exprimer la nuance plus précisément.
En conséquence, il devient plus facile de capturer les contours lors de la conversion d'images.
La fonction numpy.searchsorted
renverra l'index de l'élément le plus proche de la cible à partir du tableau de référence si vous passez le tableau de référence
comme premier argument et la cible
comme deuxième argument. [^ 1]
Puisque le tableau de référence doit être trié et que l'index est renvoyé, le traitement périphérique tel que la création de carte est implémenté de force à l'aide du tableau de dictionnaire.
Après conversion de deux tableaux en type dictionnaire et tri par clé (luminosité), luminosité et caractères Il est à nouveau stocké dans deux tableaux, la luminosité et les lettres.
Si vous l'utilisez comme une application, il est préférable de supprimer cette fonction et de corriger la carte pour un traitement plus léger.
Si vous utilisez numpy pour organiser la luminosité de chaque pixel de l'image et la passer à la fonction numpy.searchsorted
, vous obtiendrez un tableau ** qui stocke les index des caractères avec une luminosité similaire. À
Si vous exportez ceci par n'importe quelle méthode, AA sera complété.
Je vais lancer un mot-clé au professeur Google et tirer l'image en grattant.
Comme ce sera de toute façon AA, la qualité d'image est suffisante avec la qualité Samne, donc c'est facile à mettre en œuvre.
En passant, vous pouvez transmettre q = mot-clé1 + mot-clé2
comme mot-clé de recherche à l'enseignant Google et tbm = isch
comme spécification de recherche d'images.
<img>
(image)src
(URL de l'image)jason2aa.py
from bs4 import BeautifulSoup #Bibliothèque pour jouer avec des nœuds html
import requests #Contrôle la communication http"Convient aux humains"Bibliothèque
import tempfile #Bibliothèque qui gère les fichiers temporaires
import re #Bibliothèque d'expressions régulières
import sys #Une bibliothèque qui peut fonctionner plus haut que Python
#Fonction de recherche / acquisition d'image (renvoie l'URL transmise sous forme d'image)
def get_image(destination):
try: #Comme il n'est pas terminé localement, il est possible de supposer une erreur et d'incorporer la gestion des exceptions
html = requests.get(destination).text #Envoyez une requête http et convertissez la réponse au format texte
soup = BeautifulSoup(html,'lxml') #Spécifiez un excellent lxml pour l'analyseur (en xml si une erreur se produit)
links = soup.find_all('img') #balise html<img>Découvrez et extrayez tout
for i in range(10): #Répétez jusqu'à 10 fois car vous ne pourrez peut-être pas prendre l'image
link = links[random.randrange(len(links))].get('src') #Au hasard<img>Du tag"src"Extraire un
if re.match('https?://[\w/:%#\$&\?\(\)~\.=\+\-]+', link): #Confirmez que la chaîne de caractères extraite est une URL
image = requests.get(link) #Téléchargez l'image du lien extrait
image.raise_for_status() #Détecter une erreur de demande (telle que 404)
break #Je l'ai normalement, alors je passe par la boucle
elif i >= 9: #Je l'ai répété 10 fois, donc je suis sorti de la boucle
raise Exception('Oh dear. Couldn\'t find any image.\nWhy don\'t you try with my name?') #Lancer une erreur à l'exception supérieure et une erreur personnalisée
except Exception as e: #Attrapez l'erreur
print('Error: ', e) #Message d'erreur standard
sys.exit(1) #Le code de fin se termine par 1 (anormal)
fd, temp_path = tempfile.mkstemp() #Créer un fichier temporaire
with open(temp_path, 'wb') as f: #Ouvrir le fichier temporaire
f.write(image.content) #Ecrire une image dans un fichier temporaire
return temp_path #Renvoie un fichier temporaire
url = 'https://www.google.com/search?q=Jason+Statham&tbm=isch&safe=off&num=100&pws=0' #Recherchez l'image de Jason Stasam avec l'enseignant de Google
file_path = get_image(url) #Stocker le chemin de l'image acquise dans une variable
Vous pouvez gratter très doucement. Quand j'ai implémenté la même chose en PHP, cela a pris du temps, donc je l'ai trouvé pratique.
Notez que la bibliothèque requests
est une implémentation de niveau HTTP, donc même si la réponse lorsque vous exécutez requests.get () ʻest
404 Not found, aucune erreur ne se produira. Cependant, il s'agit d'une erreur en termes de grattage, vous devez donc séparer les cas par vous-même. Heureusement, tous les codes d'état autres que ceux de leur 200, tels que
404, peuvent être considérés comme anormaux, donc si vous appliquez une fonction pratique appelée
rise_for_status () à la réponse, une erreur sera générée lorsque le code de statut n'est pas dans vos 200. Vous pouvez récupérer cette erreur avec ʻexcept
et la classer par nombre.
J'ai joué avec pour qu'il puisse être utilisé comme une application.
L'aide s'affiche en tapant jason2aa.py -h
.
Okey, here is the fuckin' help.
Usase: jason2aa.py keyword keyword .. [option]
[Options]
-w Width of AA (The number of characters)
-p Path to image file
-b Return Black and white reversed image
-h Show this help (or -help)
If I was you, I'm sure I can handle such a bullshit app without the help.
Because, I'm a true man.
Je parle de Jason Stasam, alors j'ai demandé à Jason Stasam dans mon cerveau de m'aider avec un message pour que je ne sois pas "dupe". Veuillez essayer de cracher diverses erreurs. Par exemple, si vous passez une largeur d'écran qui n'est pas ʻint () ` Je vais le retourner comme ça lol Bien entendu, si le mot de recherche ou la passe n'est pas passé, l'image de Jason Stasam sera renvoyée.
La largeur est définie comme étant la largeur totale de la taille de la fenêtre du terminal par défaut.
Il est implémenté dans ʻos.get_terminal_size (). Columns en se référant à [cet article](https://www.lifewithpython.com/2017/10/python-terminal-size.html). Je voulais réduire le nombre de bibliothèques à charger, donc je l'ai implémenté avec ʻos
.
Le chemin passé est traité de manière à ne pas causer d'erreur autant que possible, mais veuillez me le faire savoir si une erreur se produit.
Nous avons également introduit l'inversion noir et blanc.
Il est censé être utilisé dans un terminal, mais lors de l'écriture sur le Web, etc., il s'agit essentiellement d'un arrière-plan blanc, il est donc inversé avec l'option -b
.
Il est nécessaire d'augmenter le ** contraste ** pour améliorer la finition avec la teinte AA. Si le contraste est faible, ** noir ** («espace») et ** blanc ** («M») ne peuvent pas être utilisés et le contour n'est pas clair. Comme AA a un petit nombre d'étapes d'expression de densité, il est difficile de savoir ce qu'est l'image à moins que le contour ne soit clair. Cette fois, grâce au module, j'ai simplement augmenté le contraste, puis je l'ai mis à l'échelle des gris, mais il semble qu'une méthode pour clarifier la nuance lors de la conversion en niveaux de gris soit également bonne.
cont = ImageEnhance.Contrast(img) #Créer un objet Pillow Enhancer
img_gray = cont.enhance(2.5).convert('L') #Double le contraste et le convertit en échelle de gris
<détails> <résumé> Échelle de gris profonde </ résumé>
Je connais cet article, mais il semble qu'il existe différentes méthodes de conversion même si cela s'appelle l'échelle de gris.
Celui de gauche est en niveaux de gris avec Pillow
, et celui de droite est en niveaux de gris avec ** processus de décoloration ** de ʻOpenCV`.
Il est difficile de voir la différence dans cette image, mais si vous regardez autour du costume et du t-shirt en Y, vous pouvez voir que ** le noir et blanc est mis en valeur ** sur le côté droit.
Celle de droite semble être une méthode axée sur le maintien du contraste. En termes simples, la mise à l'échelle des gris est une tentative d'exprimer la sensation de couleur humaine avec des nuances de noir et blanc, mais que les machines doivent reconnaître * * Il semble qu'il vaut mieux maintenir le contraste ** que le sens humain.
Il est intéressant de noter que ce domaine semble être profondément lié à la reconnaissance d'image, etc. à mesure que vous creusez plus profondément.
En parlant de reconnaissance d'image opportune en moi, c'est «EyeSight», mais c'est probablement un processus très compliqué.
Cependant, lorsque je touche la fin du traitement d'image de cette manière, je pense qu'il s'agit simplement d'un réglage de paramètre si le traitement compliqué est également étudié.
Parce que c'est simple, c'est une technologie merveilleuse dont on ne peut dire que le résultat de l'expérience accumulée au fil des décennies, y compris les programmes environnants.
Si vous avez une bibliothèque, vous pouvez la copier. Je ne sais pas s'il y a une demande, mais je l'ai postée sur GitHub. «Je veux faire fleurir le terminal! Si vous êtes une personne, veuillez l'utiliser.
jason2aa.py
#!/usr/bin/python3.7
from PIL import Image, ImageDraw, ImageFont, ImageEnhance
from bs4 import BeautifulSoup
import numpy as np
import requests
import tempfile
import os
import re
import sys
import random
is_direct = False
is_local = False
background = 'black'
color = 'white'
width = os.get_terminal_size().columns
font = ImageFont.truetype('DejaVuSansMono.ttf', 16)
characters = list('!"#$%&\'(*+,-./0123456789:;<=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[^_`abcdefghijklmnopqrstuvwxyz{|~ ')
def get_image(destination):
try:
html = requests.get(destination)
html.raise_for_status()
soup = BeautifulSoup(html.text,'lxml')
links = soup.find_all('img')
for i in range(10):
link = links[random.randrange(len(links))].get('src')
if re.match('https?://[\w/:%#\$&\?\(\)~\.=\+\-]+', link):
image = requests.get(link)
image.raise_for_status()
break
elif i >= 9:
raise Exception('Oh dear. Couldn\'t find any image.\nWhy don\'t you try with my name?')
except Exception as e:
print('Error: ', e)
sys.exit(1)
fd, temp_path = tempfile.mkstemp()
with open(temp_path, 'wb') as f:
f.write(image.content)
return temp_path
def normalize(l):
l_min = min(l)
l_max = max(l)
return [(i - l_min) / (l_max - l_min) * 255 for i in l]
def calc_density():
l = []
for i in characters:
im = Image.new('L', (24,24), background)
draw = ImageDraw.Draw(im)
draw.text((0,0), i, fill=color, font=font)
l.append(np.array(im).mean())
normed = normalize(l)
dict = {key: val for key, val in zip(normed, characters)}
return sorted(dict.items(), key=lambda x:x[0])
arg = sys.argv
if '-h' in arg or '-help' in arg:
print(' Okey, here is the fuckin\' help.\n'
'\n'
' Usase: jason2aa.py keyword keyword .. [option]\n'
'\n'
' [Options]\n'
' -w Width of AA (The number of characters, less than 10000)\n'
' -p Path to image file\n'
' -b Return Black and white reversed image\n'
' -h Show this help (or -help)\n'
'\n'
' If I was you, I\'m sure I can handle such a bullshit app without help.\n'
' Because, I\'m a true man.')
sys.exit(0)
if '-b' in arg:
b_index = arg.index('-b')
for i in range(1):
arg.pop(b_index)
background = 'white'
color = 'black'
if '-w' in arg:
w_index = arg.index('-w')
try:
w_temp = int(arg.pop(w_index + 1))
if w_temp > 0 and w_temp < 10000:
width = w_temp
else:
raise Exception
arg.pop(w_index)
except Exception:
print('Watch it! You passed me a invalid argument as width.\nI replaced it with default width.')
for i in range(1):
arg.pop(w_index)
if '-p' in arg:
p_index = arg.index('-p')
try:
path = arg.pop(p_index + 1)
arg.pop(p_index)
if re.match('https?://[\w/:%#\$&\?\(\)~\.=\+\-]+', path):
try:
image = requests.get(path)
image.raise_for_status()
fd, temp_path = tempfile.mkstemp()
with open(temp_path, 'wb') as f:
f.write(image.content)
is_direct = True
file_path = temp_path
except Exception as e:
raise Exception(e)
else:
if os.path.exists(path):
is_local = True
file_path = path
else:
raise Exception('There ain\'t any such file. Are you fucking with me?')
except Exception as e:
print(e, '\nThe above error blocked me accessing the path.\nBut, don\'t worry. Here is the my photo.')
url = 'https://www.google.com/search?q=Jason+Statham&tbm=isch&safe=off&num=100&pws=0'
file_path = get_image(url)
else:
if len(arg) <= 1:
arg = ['Jason', 'Statham']
else:
arg.pop(0)
url = 'https://www.google.com/search?q=' + '+'.join(arg) + '&tbm=isch&safe=off&num=100&pws=0'
file_path = get_image(url)
for i in range(10):
try:
img = Image.open(file_path)
except Exception:
print('Oh, fuck you! I couldn\'t open the file.\n'
'It\'s clearly your fault, cuz the path wasn\'t to image file.\n'
'But, possibly, it\'s caused by error like 404. Sorry.')
sys.exit(1)
if img.mode == 'RGB':
cont = ImageEnhance.Contrast(img)
img_gray = cont.enhance(2.5).convert('L').resize((width, int(img.height*width/img.width//2)))
break
elif is_local or is_direct:
print('Shit! I could only find only useless image.\nYou pass me files containing fuckin\' alpha channel, aren\'t you?.')
sys.exit(1)
elif i >= 9:
print('Damm it! I could only find only useless image.\nMaybe, fuckin\' alpha channel is contained.')
sys.exit(1)
else:
os.remove(file_path)
file_path = get_image(url)
maps = calc_density()
density_map = np.array([i[0] for i in maps])
charcter_map = np.array([i[1] for i in maps])
imarray = np.array(img_gray)
index = np.searchsorted(density_map, imarray)
aa = charcter_map[index]
aa = aa.tolist()
for i in range(len(imarray)):
print(''.join(aa[i]))
if not is_local:
os.remove(file_path)
sys.exit(0)
Je suis une personne inexpérimentée, donc j'ai joué avec Python
pour la première fois.
J'ai aimé écrire dans une langue très facile à utiliser et familière.
Vous pouvez découvrir combien de AA peuvent être créés automatiquement en cherchant sur le Web, mais quand je l'ai fait moi-même, il était intéressant de le voir sous un angle différent, comme la conception des allocations. Aussi, quand j'ai le temps, j'aimerais écrire ** AA ** du ** système de dessin de ligne ** en utilisant pleinement «CV2» et «détection de contour».
Si vous avez des conseils ou des suggestions, je vous serais reconnaissant de bien vouloir me le faire savoir. Jusqu'à la fin Merci d'avoir lu!
<détails> <résumé> Un par un </ résumé> (Je ne pense pas (rires)) Merci à un certain programmeur qui m'a donné l'opportunité de faire quelque chose d'un peu ludique. Je pense que des articles sur des sujets familiers (?) Comme Jason Stasam peuvent être l'occasion pour des personnes qui n'ont rien à voir avec la programmation d'avoir un aperçu de la face arrière du logiciel. Il est indissociable des appareils électroniques, et à l'ère actuelle où de nombreuses couches de technologie sont intimement liées, il est très significatif de toucher un aperçu de la technologie qui nous soutient même si nous ne sommes pas dans une position directement liée. Je pense. En touchant un peu la programmation, j'ai souvent l'impression que cela a une grande influence sur ma façon de penser les choses du quotidien. (Qiita est une plate-forme pour les programmeurs, donc le but est complètement différent.) J'espère que même un script de bas niveau peut aider quelqu'un. Merci beaucoup.
[^ 1]: Le comportement exact est différent, veuillez donc vous référer au Document officiel pour plus de détails.
Recommended Posts