如何挽救鉴黄师的职业生涯 - Python绘制像素图


欢迎访问集智主站:集智,通向智能时代的引擎浏览器

注意!

本文全部代码都可在集智原贴中运行调试,有须要的同窗能够点击这里前往原贴
bash



01. ASCII艺术

ASCII的全称是American Standard Code for Information Interchange,即美国信息交换标准码。是由军用电报编码发展而来,并成为最通用的现代计算机编码系统。网络

在显卡还不能摧毁航母战斗群的年代,计算机还主要用来计算导弹弹道和卫星轨道,其图形处理能力是很是弱的,甚至还不现在天高级一点的示波器。但这并不能阻止人类对美的追求,正如四万年前的莽荒也没有耽误拉斯科洞窟壁画的诞生。编辑器

拉斯科洞窟壁画

在我刚上网那阵,有个流传很广的帖子,是教你观看命令行里的《星球大战》,而这部星战正是由ASCII编码中的字符构成的,这被称做ASCII art函数

ASCII星球大战

在斗图代替打字、点播变成直播甚至VR/AR的今天,图形的处理已经再也不是瓶颈,反而成为了新的增加点。道高一尺魔高一丈,技术的进步也带来了有害信息,好比广你们长朋友们特别关注的色情信息。刚开始色情的鉴定是由人工完成的,李迪同志就是在《暴走大事件》中扮演鉴黄师唐马儒而一炮走红。post

可是,基于人工智能的图像识别也在飞速进步,自动鉴黄已经投入实用,鉴黄师的职业前景就面临着严重的威胁!ui

02. 字符画

把一张照片转换为字符画,大体须要三步:编码

  1. 将图片尺寸压缩到字符画所能接受的量级;
  2. 彩色图转换为灰度图,灰度是一个0-255的数值;
  3. 创建灰度值与字符集之间的映射关系。

早年间以上步骤还须要专门作一个小软件来完成,而如今只须要简单的代码就能够直接在浏览器中实现。人工智能

典型的字符画,看窗口边框大概就知道年代

由于字符画的本质是“字符”,能够用文本编辑器打开,对于计算机来讲,他们和其余的字符没有任何区别,“画”的性质只是由人类的想象力后天赋予的。因此,若是你用字符画的形式传播春宫图,仍是须要唐马儒。url

03. Python扩展库

针对字符画生成的基础功能,Python已经内置了不少优秀的扩展库,能够在此基础上直接调用,而无需重复制造轮子。

  • 图库PIL(Python Imaging Library)

    基本的图像处理功能。

  • 网库urllib

    获取网络资源,以下载网上的图片。

from PIL import Image # 图像处理模块
from urllib import request #网络请求模块
复制代码

没有必要把0-255的灰度值一一对应为不一样的字符,通常十几个也就足够了。这里作以下定义:

ASCII_CHARS = [' ', '#', '?', '%', '.', '+', '.', '*', ':', ',', '@']
复制代码

这里将最低的灰度段映射为' '(空格),也就是原图中空白或接近空白的部分,在字符画中也会会变成空白;而原图的黑点则变成@

读者朋友能够在后文的开放代码环境中想要定义本身的字符,并能够传入任意网络图片作实验。

04. 图片预处理

4K屏已经逐渐普及,如今差很少的电脑显示器也能支持2K分辨率,若是把每一个像素点都变成一个字符,那出来的图片实在是太大了。

因此首先要对源图片进行压缩,再转换为灰度模式,即抛出色彩信息。

# 压缩图片
def scale_image(image, new_width=60):
    (original_width, original_height) = image.size # 获取原图尺寸
    aspect_ratio = original_height/float(original_width) * 0.5 # 计算高宽比,由于输出文本有2倍行距,因此乘0.5维持高宽比
    new_height = int(aspect_ratio * new_width)
    new_image = image.resize((new_width, new_height))
    return new_image

# 灰度模式
def convert_to_grayscale(image):
    return image.convert('L') # 调用image对象本身的.convert()方法
复制代码

05. 图片到字符

而后是创建图片(压缩后)像素点到字符集的映射关系。

def map_pixels_to_ascii_chars(image, range_width=25):

    # 将每一个像素根据其灰度值映射为一个字符,每一个字符对应25个灰度值
    pixels_in_image = list(image.getdata()) # 获取原图灰度值列表 
    pixels_to_chars = [ASCII_CHARS[int(pixel_value/range_width)] for pixel_value in pixels_in_image]
    # 对于每一个像素点,将其灰度值转换为列表ASCII_CHARS的索引
    return "".join(pixels_to_chars)[/amalthea_sample_code]
复制代码

最后综合前面几个函数,以文本形式输出字符画。

def convert_image_to_ascii(image, new_width=60):
    image = scale_image(image, new_width) # 调用scale_image()函数,压缩图片
    image = convert_to_grayscale(image) # convert_to_grayscale()函数,转换为灰度图

    pixels_to_chars = map_pixels_to_ascii_chars(image) # 映射至字符集
    len_pixels_to_chars = len(pixels_to_chars) # 获取字符集长度

    image_ascii = [pixels_to_chars[index: index + new_width] for index in range(0, len_pixels_to_chars, new_width)]

    return "\n".join(image_ascii)


def handle_image_conversion(image_filepath, new_width=60):
    image = Image.open(image_filepath) # Image.open()打开源图片
    image_ascii = convert_image_to_ascii(image, new_width) # 调用上面的convert_image_to_ascii()函数
    print(image_ascii) # 输出字符画
复制代码

06. 图源采集

接下来咱们能够将任意图片转换为字符画看看效果,为了充分发扬互联网精神,目前仅支持具备网络地址的图片(实际上是图片上传系统还没作好)。

下面来看一个实例,将一张QQ企鹅的图标转换为字符画,点击运行便可获得字符画。

from PIL import Image

ASCII_CHARS = [' ', '#', '?', '%', '.', '+', '.', '*', ':', ',', '@']


def scale_image(image, new_width=60):
    """Resizes an image preserving the aspect ratio. """
    (original_width, original_height) = image.size
    aspect_ratio = original_height/float(original_width) * 0.5
    new_height = int(aspect_ratio * new_width)

    new_image = image.resize((new_width, new_height))
    return new_image


def convert_to_grayscale(image):
    return image.convert('L')


def map_pixels_to_ascii_chars(image, range_width=25):

    pixels_in_image = list(image.getdata())    
    pixels_to_chars = [ASCII_CHARS[int(pixel_value/range_width)] for pixel_value in
            pixels_in_image]

    return "".join(pixels_to_chars)


def convert_image_to_ascii(image, new_width=60):
    image = scale_image(image, new_width)
    image = convert_to_grayscale(image)

    pixels_to_chars = map_pixels_to_ascii_chars(image)
    len_pixels_to_chars = len(pixels_to_chars)

    image_ascii = [pixels_to_chars[index: index + new_width] for index in
            range(0, len_pixels_to_chars, new_width)]

    return "\n".join(image_ascii)

def handle_image_conversion(image_filepath, new_width=60):
    image = Image.open(image_filepath)
    image_ascii = convert_image_to_ascii(image, new_width)
    print(image_ascii)

from urllib import request
    
image_file_path = 'image2ascii.jpg' # 图片的本地名称
image_url = "http://upload.wikimedia.org/wikipedia/en/thumb/9/9c/Tencent_QQ.png/64px-Tencent_QQ.png" # 图片的网络地址
request.urlretrieve(image_url, image_file_path) # 将网络图片下载到本地,并重命名
handle_image_conversion(image_file_path) # 启动handle_image_conversion()这个总函数

复制代码

07. 开放空间

上节的例子仍然保留了默认的字符集和默认图像宽度60,接下来的部分留给读者自由发挥,能够经过修改以下参数得到本身的字符画:

  • new_width:字符画的尺寸(宽的字符数)
  • ASCII_CHARS:字符集
  • image_url:网络图片地址,就是你想要转换的图片

操做示例:

当你在网上看到一张图片,右键-复制图片地址。

http://weibo.com/kaiser0730

将图片地址赋值予变量image_url,点击运行便可。

替换相应变量

from PIL import Image
from urllib import request

def scale_image(image, new_width=60):
    (original_width, original_height) = image.size
    aspect_ratio = original_height/float(original_width) * 0.5
    new_height = int(aspect_ratio * new_width)

    new_image = image.resize((new_width, new_height))
    return new_image

def convert_to_grayscale(image):
    return image.convert('L')

def map_pixels_to_ascii_chars(image, range_width=25):
    pixels_in_image = list(image.getdata())    
    pixels_to_chars = [ASCII_CHARS[int(pixel_value/range_width)] for pixel_value in
            pixels_in_image]

    return "".join(pixels_to_chars)

def convert_image_to_ascii(image, new_width=60):
    image = scale_image(image, new_width)
    image = convert_to_grayscale(image)
    pixels_to_chars = map_pixels_to_ascii_chars(image)
    len_pixels_to_chars = len(pixels_to_chars)
    image_ascii = [pixels_to_chars[index: index + new_width] for index in
            range(0, len_pixels_to_chars, new_width)]
    return "\n".join(image_ascii)

def handle_image_conversion(image_filepath, new_width=60):
    image = Image.open(image_filepath)
    image_ascii = convert_image_to_ascii(image, new_width)
    print(image_ascii)

image_file_path = 'image2ascii.jpg' # 图片的本地名称
new_width = 60 # 字符画宽几个字符 

ASCII_CHARS = [' ', '#', '?', '%', '.', '+', '.', '*', ':', ',', '@'] # 字符集

image_url =  "http://upload.wikimedia.org/wikipedia/en/thumb/9/9c/Tencent_QQ.png/64px-Tencent_QQ.png" # 图片的网络地址
request.urlretrieve(image_url, image_file_path) 

handle_image_conversion(image_file_path, new_width)
复制代码

摘掉眼镜看效果更佳。

Sublime编辑器里的成像效果


推荐阅读

“女生科技体验节” TensorFlow Workshop

这评论有毒!——文本分类的通常套路

我作了一个叫“瑟曦”的机器人,但是她动不动就想让格雷果爵士弄死我。

相关文章
相关标签/搜索