获取图像(640x384)并将其转换为ASCII字符串的程序

你还记得"老"的互联网吗?在网络浏览器出现之前,当一切都有强烈的Unix味道的时候?当时有一种叫做ASCII艺术的东西,也就是用ASCII字母来创造一个图像。下面是一个获取图像(640x384)并将其转换为ASCII字符串的程序。我想为一个
T—恤衫
您需要将字体目录中的"Courier new"字体复制到与脚本相同的目录中,并添加一个需要转换的图像:

选择 | 换行 | 行号
  1. import Image, ImageDraw
  2. import ImageFont
  3. import math
  4.  
  5. # funny useless program
  6.  
  7. lu = []
  8. for i in range(125-32):
  9.  lu.append(chr(i+33))
  10. i2 = Image.new("RGBA",(64,64))
  11. ii = Image.open("mona.png") # change this to your own picture, but it needs to be 640x384!
  12. im = Image.new("RGBA",(64,64))
  13. d = ImageDraw.Draw(im)
  14. f = ImageFont.truetype("courbi.ttf",13)
  15.  
  16. str=""
  17. for v in range(24):
  18.  print v
  19.  for k in range(80):
  20.   chr = ""
  21.   maxdiff = 0xffffff
  22.   for e in lu:
  23.    d.rectangle([0,0,64,64], fill=0)
  24.    d.text((0,0),e,font=f,fill=0xffffff)
  25.    diff = 0
  26.    r0 = 0
  27.    g0 = 0
  28.    b0 = 0
  29.    for a in range(16):
  30.     for b in range(8):
  31.      c =  im.getpixel((b,a))[0]
  32.      c0 = (ii.getpixel((b+(k*8),a+(v*16)))[0] + ii.getpixel((b+(k*8),a+(v*16)))[1] + ii.getpixel((b+(k*8),a+(v*16)))[2])/3.0
  33.      r0+= ii.getpixel((b+(k*8),a+(v*16)))[0]
  34.      g0+= ii.getpixel((b+(k*8),a+(v*16)))[1]
  35.      b0+= ii.getpixel((b+(k*8),a+(v*16)))[2]
  36.  
  37.      diff+=abs(c-c0)
  38.    if(diff < maxdiff):
  39.     maxdiff = diff
  40.     chr = e
  41.  
  42.   r0*=1.0
  43.   g0*=1.0
  44.   b0*=1.0
  45.   r0/=(16.0*8.0)
  46.   g0/=(16.0*8.0)
  47.   b0/=(16.0*8.0)
  48.   ir0 = int(r0)
  49.   ig0 = int(g0)
  50.   ib0 = int(b0)
  51.  
  52.   r1 =  hex(ir0)
  53.   r1 = r1[2:len(r1)]
  54.   g1 = hex(ig0)
  55.   g1 = g1[2:len(g1)]
  56.   b1 = hex(ib0)
  57.   b1 = b1[2:len(g1)]
  58.  
  59.   if(chr == " "):
  60.    chr="&nbsp;"
  61.  
  62.   str+="<td width=\"8px\"><font size=\"1px\" color=\"#"+r1+g1+b1+"\">"+chr+"</font></td>"
  63.  str="<tr>"+str+"</tr>"
  64.  
  65. str= "<html><body bgcolor=\"#000000\"><table width=\"640px\" height=\"386px\">"+str+"</table></body></html>"
  66. f = open("mona.txt","w")
  67. f.write(str)
  68. f.close()
  69.  

该程序将其输出为.html文件,但它应该很容易修改,因此它将输出txt。
-赞誉

# 回答1


我已经修改了您的代码,做了一些不同的事情。
它极大地加快了速度。我把6分钟缩短到了1秒。我还让它在命令行解析器的基础上运行,所以你现在可以把它放在你的网站上或任何你想要的地方。如果我没记错的话,这里面有几个问题(我写这篇文章大约有6个月了)。请随意调整它,并将其带回给每个人。它还在算法中使用真实亮度(如果需要)。

选择 | 换行 | 行号
  1. '''
  2.     Inspired by -Kudos code from http://bytes.com/topic/python/insights/874180-ascii-art-creator
  3.     Pretty much a rewrite, but I give kudos complete props for posting this and making it fun and easy
  4. '''
  5.  
  6.  
  7. import sys,os
  8. import Image, ImageDraw
  9. import ImageFont
  10. import math
  11. import time, random
  12. from optparse import OptionParser
  13.  
  14.  
  15. # funny useless program
  16. t0                             = time.time();
  17. VERBOSE_LEVEL                = 1;
  18. MIN_LUM_DEFAULT             = .1;
  19. MAX_LUM_DEFAULT             = 1.0;
  20. OFFSET_LUM_DEFAULT            = 0;
  21. OUTPUT_FONT_SIZE_DEFAULT    = 3;
  22. CHARMAP_DEFAULT                = 'luminance';
  23.  
  24. ROWS_DEFAULT                 = 24
  25. COLS_DEFAULT                 = 80
  26.  
  27. MAX_RGB                        = 255
  28. MAX_F_RGB                    = float(MAX_RGB)
  29.  
  30. def normalizePixel( rgb ):
  31.     return rgb[0]/MAX_F_RGB,rgb[1]/MAX_F_RGB,rgb[2]/MAX_F_RGB
  32.  
  33. def getLuminancePixel( rgb ):
  34.     nR,nG,nB = normalizePixel( rgb )
  35.     return nR*0.299 + nG*0.587 + nB*0.114
  36.  
  37. def output( val, vLevel=0 ):
  38.     if vLevel <= VERBOSE_LEVEL:
  39.         print ( val )
  40.  
  41. def main( args ):
  42.  
  43.     global VERBOSE_LEVEL;
  44.  
  45.     parser = OptionParser()
  46.     parser.add_option("-f", "--file", action='append', dest="files", help="process these files", metavar="LIST")
  47.     parser.add_option(        "--characters", action="store", dest="characters", help="characters to use")
  48.     parser.add_option(        "--character_map", action="store", dest="characterMap", help="maps characters: luminance, order, random")
  49.     parser.add_option("-r", "--rows", action="store", dest="rows", help="number of rows")
  50.     parser.add_option("-c", "--columns", action="store", dest="columns", help="number of columns")
  51.     parser.add_option(        "--min_luminance", action="store", dest="minLuminance", help="min luminance value to clip at black")
  52.     parser.add_option(        "--max_luminance", action="store", dest="maxLuminance", help="max luminance value to clip at white")
  53.     parser.add_option(        "--offset_luminance", action="store", dest="offsetLuminance", help="offset luminance value")
  54.     parser.add_option(        "--output_font_size", action="store", dest="outputFontSize", help="output font size in px")
  55.     parser.add_option('-v', "--verbose", action="store", dest="verbose", help="verbosity: 0=None, 1=completion output, 2=image info, 3=pixel blending info")
  56.  
  57.     (options, args) = parser.parse_args( args )
  58.  
  59.     files             = options.files;
  60.     characters         = options.characters;
  61.     characterMap    = options.characterMap;
  62.     rows            = options.rows;
  63.     columns            = options.columns;
  64.     minLum            = options.minLuminance;
  65.     maxLum            = options.maxLuminance;
  66.     offsetLum        = options.offsetLuminance;
  67.     outputFontSize    = options.outputFontSize;
  68.     verbose            = options.verbose;
  69.  
  70.     errors = [];
  71.     # SANITY CHECKS
  72.  
  73.     if verbose:
  74.         try:
  75.             VERBOSE_LEVEL = int(verbose);
  76.         except:
  77.             VERBOSE_LEVEL = VERBOSE_LEVEL;
  78.  
  79.     if not files:
  80.         errors.append('Failed to get files: make sure you specify files to use');
  81.     if not characters:
  82.         characters = []
  83.         for i in range( 125-32):
  84.             characters.append( chr( i + 33) );
  85.     else:
  86.         characters = str(characters);
  87.  
  88.     if characterMap:
  89.         if characterMap.lower() in ('luminance','order','random'):
  90.             characterMap = characterMap.lower();
  91.         else:
  92.             characterMap = CHARMAP_DEFAULT;
  93.     else:
  94.         characterMap = CHARMAP_DEFAULT;
  95.  
  96.     try:
  97.         rows = int(rows);
  98.     except:
  99.         rows = ROWS_DEFAULT;
  100.     try:
  101.         columns = int(columns);
  102.     except:
  103.         columns = COLS_DEFAULT;
  104.  
  105.     try:
  106.         minLum     = float( minLum)
  107.     except:
  108.         minLum = MIN_LUM_DEFAULT
  109.     try:
  110.         maxLum     = float( maxLum)
  111.     except:
  112.         maxLum = MAX_LUM_DEFAULT
  113.  
  114.     try:
  115.         offsetLum     = int( offsetLum)
  116.     except:
  117.         offsetLum = OFFSET_LUM_DEFAULT
  118.  
  119.     try:
  120.         outputFontSize     = int( outputFontSize)
  121.     except:
  122.         outputFontSize = OUTPUT_FONT_SIZE_DEFAULT
  123.  
  124.     if errors:
  125.         for err in errors:
  126.             output( 'ERROR: %s'%err, 0);
  127.         return -1;
  128.  
  129.     output( 'verbose: %s'%verbose    , 3 );
  130.     output( 'files: %s'%files        , 3 );
  131.     output( 'characters: %s'%characters    , 3 );
  132.     output( 'character_map: %s'%characterMap    , 3 );
  133.     output( 'rows: %s'%rows    , 3 );
  134.     output( 'columns: %s'%columns    , 3 );
  135.     output( 'minLum: %s'%minLum    , 3 );
  136.     output( 'maxLum: %s'%maxLum    , 3 );
  137.     output( 'offsetLum: %s'%offsetLum    , 3 );
  138.     output( 'outputFontSize: %s'%outputFontSize    , 3 );
  139.  
  140.     imgChr = Image.new("RGBA",(64,64))
  141.     drwObj = ImageDraw.Draw(imgChr)
  142.     fntObj = ImageFont.truetype("courbi.ttf",13)
  143.  
  144.  
  145.     # build the value table
  146.     lumLUT_Tmp         = list();
  147.     lumLUT         = list();
  148.     lumToCharTmp     = dict();
  149.     maxLum         = 0.0;
  150.     minLum         = 1.0;
  151.     for ch in characters:
  152.  
  153.         w,h = fntObj.getsize(ch)
  154.         drwObj.rectangle([0,0,64,64], fill=0)
  155.         drwObj.text((0,0),ch,font=fntObj,fill=0xffffff)
  156.         diff = 0
  157.         r0 = 0
  158.         g0 = 0
  159.         b0 = 0
  160.  
  161.         lum = 0;
  162.         for a in range(16):
  163.             for b in range(8):
  164.                 lum += getLuminancePixel( imgChr.getpixel((b,a)) )
  165.         lum = lum/(16*8)
  166.         lumLUT_Tmp.append( lum )
  167.         lumToCharTmp[lum] = ch ;
  168.  
  169.         if lum > maxLum:
  170.             maxLum = lum;
  171.         if lum < minLum:
  172.             minLum = lum;
  173.  
  174.         output( ('ch: %s\t(%sx%s) lum:%s'%(ch,w,h,lum)), 3);
  175.     lumToChar     = dict();
  176.     for lum in lumLUT_Tmp:
  177.         nLum = (lum-minLum)/(maxLum-minLum);
  178.         lumToChar[nLum] = lumToCharTmp[lum];
  179.         lumLUT.append( nLum );
  180.  
  181.     lumLUT.sort();
  182.  
  183.     for file in files:
  184.         tImage = time.time()
  185.         imgSrc = Image.open(file) 
  186.         iw,ih = imgSrc.size;
  187.         cellW = iw/columns;
  188.         cellH = ih/rows;
  189.         #~ print '\n%sx%s  %sx%s'%(cellW,cellH, iw, ih)
  190.         sVal=""
  191.         index=0
  192.         for x in range(rows):
  193.             for y in range(columns):
  194.                 ch = ""
  195.                 maxdiff = 0xffffff
  196.  
  197.                 iLum = 0;
  198.                 r = 0;
  199.                 g = 0;
  200.                 b = 0;
  201.                 for xCell in range(cellH):
  202.                     for yCell in range(cellW):
  203.                         color = imgSrc.getpixel((yCell+(y*cellW),xCell+(x*cellH)));
  204.                         r += color[0]
  205.                         g += color[1]
  206.                         b += color[2]
  207.  
  208.                 # average        
  209.                 r = r/(cellH*cellW*1.0);
  210.                 g = g/(cellH*cellW*1.0);
  211.                 b = b/(cellH*cellW*1.0);
  212.  
  213.                 hexColor = '%.2x%.2x%.2x'%( r+offsetLum,g+offsetLum,b+offsetLum );
  214.  
  215.                 # normalize
  216.                 iLum += getLuminancePixel( (r,g,b) )
  217.  
  218.                 #~ r /= MAX_F_RGB;
  219.                 #~ g /= MAX_F_RGB;
  220.                 #~ b /= MAX_F_RGB;
  221.  
  222.                 if characterMap == 'luminance' :
  223.                     ix = 0;
  224.                     for lum in lumLUT:
  225.                         if iLum < MIN_LUM_DEFAULT:
  226.                             ch = ' ';
  227.                             break;
  228.                         if iLum > MAX_LUM_DEFAULT:
  229.                             ch = lumToChar[lumLUT[-1]];
  230.                             break;
  231.                         if lum > iLum:
  232.                             try:
  233.                                 ch = lumToChar[lumLUT[ix]];
  234.                             except:
  235.                                 ch = lumToChar[lumLUT[0]]
  236.                             break;
  237.                         ix+=1;
  238.  
  239.                 elif characterMap == 'order':
  240.                     if index >= len(characters):
  241.                         index=0;
  242.                     ch = characters[index];
  243.                 elif characterMap == 'random':
  244.                     ch = characters[int(random.random()*len(characters))];
  245.  
  246.                 index+=1
  247.                 if(ch == " "):
  248.                     ch="&nbsp;"
  249.                 #~ output( 'Character: %s'%ch, 3);
  250.                 output( ('character: %s\trow:%s column:%s\tlum: %s\tr:%s g:%s b:%s\thex_color:%s'%(ch,x,y,iLum,r,g,b,hexColor)), 3);
  251.                 sVal += '''<font size="%spx" color="#%s">%s</font></td>'''%(outputFontSize,hexColor,ch);
  252.             sVal += '<br/>';
  253.         sVal= "<html><body bgcolor=\"#000000\"><pre>"+sVal+"</pre><br/>\n<img src=\"%s\"/>\n</body></html>"%file
  254.         try:
  255.             f = open("%s.html"%file,"w")
  256.             f.write(sVal)
  257.             f.close()
  258.         except:
  259.             output('Failed to write file: %s'%file, 0 );
  260.  
  261.         output( ('%s  (%sx%s : %sx%s)'%(file,iw,ih,cellW,cellH)).center(50,'.'), 2)
  262.         output( 'IMAGE PROCESS TIME: %s (sec)\t%s'%((time.time()-tImage),os.path.basename(file)), 1);
  263.  
  264.     output( '%s\nTOTAL PROCESS TIME: %s (sec)'%('-'*100, (time.time()-t0) ), 1);
  265.  
  266. if __name__=='__main__':
  267.     args = sys.argv;
  268.  
  269.     args += [
  270.         #~ '--file','./angry_birds.jpg',
  271.         #~ '--characters','-+=@!?%$#^&*()[]{}_\\/><,.`~',
  272.         #~ '-r','80', '-c','260',
  273.         #~ '--output_font_size','1',
  274.         #~ '--character_map','random',
  275.         #~ '--character_map','order',
  276.         #~ '-v', '3',
  277.  
  278.     ]
  279.  
  280.     sys.exit( main( args ) );
  281.  
  282.  

标签: python

添加新评论