PPM Bild zu ASCII Kunst in Python

Ich muss ein Programm machen, das in einer Datei von der Kommandozeile liest und es an ASCII Art verdeckt. Ich benutze PPM-Format und hier ist ein Link zum Projekt .

Hier ist was ich bisher habe

import sys def main(filename): image = open(filename) #reads through the first three lines color = image.readline().splitlines() size_width, size_height = image.readline().split() max_color = image.readline().splitlines() #reads the body of the file pixels = image.read().split() red = 0 green = 0 blue = 0 r_g_b_value = [] #pulls out the values of each tuple and coverts it to its grayscale value for i in pixels: if i != "\n" or " ": if len(i) == 3: red = int(i[0]) * .3 green = int(i[1]) * .59 blue = int(i[2]) * .11 elif len(i) == 2: red == int(i[0]) * .3 green == int(i[1]) *.59 blue == 0 elif len(i) == 1: red == int(i[0]) * .3 green == 0 blue == 0 r_g_b_value = [red + green + blue] character = [] for j in len(r_g_b_value): if int(j) <= 16: character = " " elif int(j) > 16 and int(j) <= 32: character = "." elif int(j) > 32 and int(j) <= 48: character = "," elif int(j) > 48 and int(j) <= 64: charcter = ":" elif int(j) > 64 and int(j) <= 80: character = ";" elif int(j) > 80 and int(j) <= 96: character = "+" elif int(j) > 96 and int(j) <= 112: character = "=" elif int(j) > 112 and int(j) <= 128: character = "o" elif int(j) > 128 and int(j) <= 144: character = "a" elif int(j) > 144 and int(j) <= 160: character = "e" elif int(j) > 160 and int(j) <= 176: character = "0" elif int(j) > 176 and int(j) <= 192: character = "$" elif int(j) > 192 and int(j) <= 208: character = "@" elif int(j) > 208 and int(j) <= 224: character = "A" elif int(j) > 224 and int(j) <= 240: character = "#" else: character = "M" grayscale = character print(grayscale) main(sys.argv[1]) 

Ich bekomme einen Fehler, der sagt, dass 'int' Objekt ist nicht iterable, gibt es eine einfache Möglichkeit, dies zu beheben und wie würde jemand empfehlen, drucken dies aus, während die Erhaltung des Bildes.

Und das letzte, was mir nicht sicher ist, ist, wie man die Breite und die Höhe des Bildes bewahrt.

Jede Hilfe wäre sehr dankbar.

3 Solutions collect form web for “PPM Bild zu ASCII Kunst in Python”

Sie können image-to-ansi.py für die Konvertierung verwenden.

Zuerst download image-to-ansi.py :

 wget https://gist.githubusercontent.com/klange/1687427/raw/image-to-ansi.py 

Speichern Sie dieses Skript als ppmimage.py :

 # Parses a PPM file and loads it into image-to-ansi.py import re, itertools sep = re.compile("[ \t\r\n]+") def chunks(iterable,size): """ http://stackoverflow.com/a/434314/309483 """ it = iter(iterable) chunk = tuple(itertools.islice(it,size)) while chunk: yield chunk chunk = tuple(itertools.islice(it,size)) """ Emulates the Image class from PIL and some member functions (`getpixel`, `size`). """ class Image: """ This class emulates the PIL Image class, and it can parse "plain" PPM's. You can use PIL instead. """ @staticmethod def fromstdin(): return Image() def __init__(self): # http://netpbm.sourceforge.net/doc/ppm.html self.entities = sep.split("\n".join(list(filter(lambda x: not x.startswith("#"), sys.stdin.read().strip().split("\n"))))) self.size = tuple(list(map(int,self.entities[1:3]))) self.high = int(self.entities[3]) # zb 255 self.pixels = list(map(lambda x: tuple(map(lambda y: int(int(y) / self.high * 255), x)), list(chunks(self.entities[4:], 3)))) def getpixel(self, tupl): x = tupl[0] y = tupl[1] pix = self.pixels[y*self.size[0]+x] return pix image_to_ansi = __import__("image-to-ansi") # __import__ because of minuses in filename. From https://gist.github.com/1687427 if __name__ == '__main__': import sys #import Image im = Image.fromstdin() # use Image.open from PIL if using PIL for y in range(im.size[1]): for x in range(im.size[0]): p = im.getpixel((x,y)) h = "%2x%2x%2x" % (p[0],p[1],p[2]) short, rgb = image_to_ansi.rgb2short(h) sys.stdout.write("\033[48;5;%sm " % short) sys.stdout.write("\033[0m\n") sys.stdout.write("\n") 

Sie können das Skript so testen (dies setzt voraus, dass Sie imagemagick und imagemagick installiert haben):

convert -resize $(($COLUMNS*2))x$(($LINES*2)) logo: pnm:- | pnmtoplainpnm | python3 ppmimage.py

Auf meiner Maschine sieht es so aus:

ImageMagick-Logo in Xterm gezeigt

Hier haben Sie Ihren Code geändert und funktioniert.
Es ist nicht optimal, es berücksichtigt nicht die Anwesenheit von mehr oder weniger Kommentare in der Kopfzeile und es gibt keine Ausnahmebehandlung, aber es ist ein Anfang.

 import sys import numpy as np RGBS = range(16, 255, 16) CHARS = [' ', '.', ',', ':', ';', '+', '=', 'o', 'a', 'e', '0', '$', '@', 'A', '#'] FACTORS = [.3, .59, .11] def main(filename): image = open(filename) #reads header lines color = image.readline() _ = image.readline() size_width, size_height = image.readline().split() max_color = image.readline() size_width = int(size_width) max_color = int(max_color) #reads the body of the file data = [int(p) for p in image.read().split()] #converts to array and reshape data = np.array(data) pixels = data.reshape((len(data)/3, 3)) #calculate rgb value per pixel rgbs = pixels * FACTORS sum_rgbs = rgbs.sum(axis=1) rgb_values = [item * 255 / max_color for item in sum_rgbs] grayscales = [] #pulls out the value of each pixel and coverts it to its grayscale value for indx, rgb_val in enumerate(rgb_values): #if max width, new line if (indx % size_width) == 0 : grayscales.append('\n') for achar, rgb in zip(CHARS, RGBS): if rgb_val <= rgb: character = achar break else: character = 'M' grayscales.append(character) print ''.join(grayscales) main('test.ppm') 

Dies sind die ppm-Figur und die ASCII Art Ergebnis

Bildbeschreibung hier eingeben

Und die micro ppm Datei habe ich für das Beispiel verwendet:

 P3 # test.ppm 4 4 15 0 0 0 0 0 0 0 0 0 15 0 15 0 0 0 0 15 7 0 0 0 0 0 0 0 0 0 0 0 0 0 15 7 0 0 0 15 0 15 0 0 0 0 0 0 0 0 0 

Ich schrieb eines von diesen in C # vor einer Weile und ich berechnete den Charakter mit dieser Formel zu verwenden:

 index_into_array = (int)(r_g_b_value * (chars_array_length / (255.0))); 

Wie für die Breite und Höhe, könnten Sie durchschnittlich alle zwei Zeilen der vertikalen Pixel, um die Höhe zu halbieren.

Bearbeiten 1: als Antwort auf Kommentar: Die Grundidee ist, dass es Ihren RGB-Wert von 0 bis 255 auf 0 auf die Länge des Arrays skaliert und das als Index verwendet.

Bearbeiten 2: Aktualisiert, um zu korrigieren, dass ich Ihre Graustufen Normalisierung ignorierte.

  • Verwenden von win32com mit Multithreading
  • Verwendung von input / raw_input in python 2 und 3
  • Maskierung der eingebauten Variable mit ihrem magischen Verhalten?
  • Warum ist dieser Python-Generator immer wieder den gleichen Wert?
  • Listenliste der Listenelemente in anderen Listenposten anzeigen
  • Wie berechnen Sie gleitenden Durchschnitt in Python 3?
  • Python RandomForest - Unbekannter Label Error
  • Schnellere Alternative zur Verwendung der `map` Funktion
  • Rufen Sie eine Python-Datei in einem SML-Programm an?
  • Ausgabe von Binärdaten aus CGI in Python 3
  • Rock Paper Schere in Python
  • Python ist die beste Programmiersprache der Welt.