ASCII艺术导论
ASCII art是一种图形设计技术,它使用计算机进行演示,由95个可打印字符(总共128个)拼凑而成,这些字符由1963年的ASCII标准定义,并与ASCII兼容,带有专有扩展字符(超出标准7位ASCII的128个字符)。这个词通常也泛指基于文本的视觉艺术。ASCII艺术可以用任何文本编辑器创建,并且经常与自由形式的语言一起使用。大多数ASCII艺术的例子都需要固定宽度的字体(非比例字体,如传统打字机上的字体),比如Courier。已知的ASCII艺术最古老的例子包括1966年左右计算机艺术先驱肯尼斯·诺尔顿(Kenneth Knowlton)的作品,他当时在贝尔实验室工作。Ken Knowlton和Leon Harmon从1966年开始的《感知I研究》展示了他们早期ASCII艺术的一些例子。ASCII艺术的发明在很大程度上是因为早期的打印机通常缺乏图形能力,因此使用字符来代替图形标记。此外,为了标记来自不同用户的不同打印作业之间的分区,批量打印机通常使用ASCII艺术打印大型横幅,使分区更容易识别,以便计算机操作员或职员更容易区分结果。当图像无法嵌入时,早期的电子邮件中也使用了ASCII art。你可以找到更多关于他们的信息。[来源: 维基 .
工作原理:
以下是程序生成ASCII码的步骤 图片:
- 将输入图像转换为灰度。
- 将图像拆分为M×N个分幅。
- 更正M(行数)以匹配图像和字体纵横比。
- 计算每个图像块的平均亮度,然后为每个图像块查找合适的ASCII字符。
- 将ASCII字符串的行组合起来,并将它们打印到文件中,以形成最终图像。
要求
你将用python编写这个程序,我们将使用 枕头 这是Python图像库,用于读取图像、访问其底层数据、创建和修改图像以及科学模块 努比 计算平均值。
密码 首先定义用于生成ASCII艺术的灰度级别。然后,您将看到如何将图像分割为瓷砖,以及如何计算这些瓷砖的平均亮度。接下来,您将使用ASCII字符替换平铺,以生成最终输出。最后,您将为程序设置命令行解析,以允许用户指定输出大小、输出文件名等。
定义灰度级别和网格
作为创建程序的第一步,将用于将亮度值转换为ASCII字符的两个灰度级别定义为全局值。
>>>gscale1 = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~i!lI;:,"^`". " #70 levels of gray>>>gscale2 = "@%#*+=-:. " #10 levels of gray
u处的值gscale1是70级灰度渐变,v处的值gscale2是更简单的10级灰度渐变。这两个值都存储为字符串,字符范围从最暗到最亮。 现在已经有了灰度渐变,可以设置图像了。以下代码打开图像并将其拆分为网格:
# open image and convert to grayscale>>> image = Image.open(fileName).convert('L') # store dimensions>>> W, H = image.size[0], image.size[1] # compute width of tile>>> w = W/cols # compute tile height based on aspect ratio and scale>>> h = w/scale # compute number of rows>>> rows = int(H/h)
计算平均亮度 接下来,计算灰度图像中平铺的平均亮度。函数getAverageL()完成这项工作。
#Given PIL Image, return average value of grayscale value>>>def getAverageL(image): # get image as numpy array... im = np.array(image) # get shape... w,h = im.shape # get average... return np.average(im.reshape(w*h))
首先,图像块作为PIL图像对象传入。在第二步中,将图像转换为一个numpy数组,此时“im”将成为每个像素的二维亮度数组。在第三步中,存储图像的尺寸(宽度和高度)。第四步,numpy。average()使用numpy计算图像中亮度值的平均值。重塑()首先将二维数组的宽度和高度(w,h)转换为?在一维数组中,其长度是宽度乘以高度(w*h)的乘积。努比。average()调用然后对这些数组值求和并计算平均值。
从图像生成ASCII内容
# ascii image is a list of character strings>>> aimg = [] # generate list of dimensions>>> for j in range(rows):... y1 = int(j*h)... y2 = int((j+1)*h) # correct last tile... if j == rows-1:... y2 = H # append an empty string... aimg.append("")... for i in range(cols): # crop image to tile... x1 = int(i*w)... x2 = int((i+1)*w) # correct last tile... if i == cols-1:... x2 = W # crop image to extract tile... img = image.crop((x1, y1, x2, y2)) # get average luminance... avg = int(getAverageL(img)) # look up ascii char... if moreLevels:... gsval = gscale1[int((avg*69)/255)]... else:... gsval = gscale2[int((avg*9)/255)] # append ascii char to string... aimg[j] += gsval
在程序的这一部分中,ASCII图像首先存储为字符串列表,并在第一步初始化。接下来,迭代计算出的行图像分片数,在第二步和下一行,计算每个图像分片的开始和结束y坐标。虽然这些是?在进行点计算时,先将其截断为整数,然后再将其传递给图像裁剪方法。接下来,因为只有当图像宽度是列数的整数倍时,将图像分割为平铺才会创建相同大小的边缘平铺,所以通过将y坐标设置为图像的实际高度来校正最后一行中平铺的y坐标。这样做可以确保图像的上边缘不会被截断。在第三步,将空字符串添加到ASCII中,作为表示当前图像行的紧凑方式。下一步你要填写这个字符串。(将字符串视为字符列表。)在第四步和下一行中,计算每个磁贴的左右x坐标,在第五步中,按照校正y坐标的相同原因校正最后一个磁贴的x坐标。使用图像。裁剪()在第六步中,要提取图像平铺,然后将该平铺传递给上面定义的getAverageL()函数,请将平均亮度值从[0,255]缩小到[0,9](默认10级灰度渐变的值范围)。然后使用gscale2(存储的斜坡字符串)作为相关ASCII值的ASCII Art 95查找表。“八步”中的行与此类似,只是它仅在命令行?ag设置为使用70级坡道。最后,在最后一步将查找到的ASCII值gsval附加到文本行,代码循环直到所有行都被处理。 添加命令行界面并将ASCII艺术字符串写入文本文件 要添加命令行界面,请使用python内置模块 argparse . 最后,获取生成的ASCII字符串列表,并将这些字符串写入文本文件。
# open a new text file>>> f = open(outFile, 'w')# write each string in the list to the new file>>> for row in aimg:... f.write(row + '')# clean up>>> f.close()
然后添加这些部分来创建程序。下面给出了完整的代码。
python
# Python code to convert an image to ASCII image. import sys, random, argparse import numpy as np import math from PIL import Image # gray scale level values from: # 70 levels of gray gscale1 = "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`'. " # 10 levels of gray gscale2 = '@%#*+=-:. ' def getAverageL(image): """ Given PIL Image, return average value of grayscale value """ # get image as numpy array im = np.array(image) # get shape w,h = im.shape # get average return np.average(im.reshape(w * h)) def covertImageToAscii(fileName, cols, scale, moreLevels): """ Given Image and dims (rows, cols) returns an m*n list of Images """ # declare globals global gscale1, gscale2 # open image and convert to grayscale image = Image. open (fileName).convert( 'L' ) # store dimensions W, H = image.size[ 0 ], image.size[ 1 ] print ( "input image dims: %d x %d" % (W, H)) # compute width of tile w = W / cols # compute tile height based on aspect ratio and scale h = w / scale # compute number of rows rows = int (H / h) print ( "cols: %d, rows: %d" % (cols, rows)) print ( "tile dims: %d x %d" % (w, h)) # check if image size is too small if cols > W or rows > H: print ( "Image too small for specified cols!" ) exit( 0 ) # ascii image is a list of character strings aimg = [] # generate list of dimensions for j in range (rows): y1 = int (j * h) y2 = int ((j + 1 ) * h) # correct last tile if j = = rows - 1 : y2 = H # append an empty string aimg.append("") for i in range (cols): # crop image to tile x1 = int (i * w) x2 = int ((i + 1 ) * w) # correct last tile if i = = cols - 1 : x2 = W # crop image to extract tile img = image.crop((x1, y1, x2, y2)) # get average luminance avg = int (getAverageL(img)) # look up ascii char if moreLevels: gsval = gscale1[ int ((avg * 69 ) / 255 )] else : gsval = gscale2[ int ((avg * 9 ) / 255 )] # append ascii char to string aimg[j] + = gsval # return txt image return aimg # main() function def main(): # create parser descStr = "This program converts an image into ASCII art." parser = argparse.ArgumentParser(description = descStr) # add expected arguments parser.add_argument( '--file' , dest = 'imgFile' , required = True ) parser.add_argument( '--scale' , dest = 'scale' , required = False ) parser.add_argument( '--out' , dest = 'outFile' , required = False ) parser.add_argument( '--cols' , dest = 'cols' , required = False ) parser.add_argument( '--morelevels' ,dest = 'moreLevels' ,action = 'store_true' ) # parse args args = parser.parse_args() imgFile = args.imgFile # set output file outFile = 'out.txt' if args.outFile: outFile = args.outFile # set scale default as 0.43 which suits # a Courier font scale = 0.43 if args.scale: scale = float (args.scale) # set cols cols = 80 if args.cols: cols = int (args.cols) print ( 'generating ASCII art...' ) # convert image to ascii txt aimg = covertImageToAscii(imgFile, cols, scale, args.moreLevels) # open file f = open (outFile, 'w' ) # write to file for row in aimg: f.write(row + '' ) # cleanup f.close() print ( "ASCII art written to %s" % outFile) # call main if __name__ = = '__main__' : main() |
输入:
$python "ASCII_IMAGE_GENERATOR.py" --file data/11.jpg --cols 120
资源 1. 维基百科:ASCII_艺术 2.Python游乐场:Mahesh Venkitachalam为好奇的程序员设计的极客项目。 3. 灰度值 4. 本文的Github代码 本文由 Subhajit Saha .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。