• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

教你用Python将自己喜欢的图片转成字符画,居然还有动态的

python 搞java代码 3年前 (2022-05-21) 15次浏览 已收录 0个评论

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理

以下文章一级Python技术 ,作者派森酱

前言

字符画是一种由字母,标点或其他字符组成的标记,它产生于互联网时代,在聊天软件中使用替换,此处我们看一下如何将自己喜欢的图片转成字符画。

 

静态图片

首先,我们来演示将静态图片转换为字符画,功能实现主要用到的Python库为OpenCV,安装使用 pip install opencv-python 命令即可。

功能实现的基本思路为:利用聚类将目标信息聚为3或5类,颜色最深的一类用数字密集度表示,阴影的一类用横杠(-)表示,明亮部分用空白表示。

主要代码实现如下:

<span>def</span> img2strimg(frame, K=5<span>):   
    </span><span>if</span> type(frame) !=<span> np.ndarray:
        frame </span>=<span> np.array(frame)
    height, width, </span>*_ =<span> frame.shape  
    frame_gray </span>=<span> cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    frame_array </span>= np.float32(frame_gray.reshape(-1<span>))
    criteria </span>= (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0<span>)
    flags </span>=<span> cv2.KMEANS_RANDOM_CENTERS
    </span><span>#</span><span> 得到 labels(类别)、centroids(矩心)</span>
    compactness, labels, centroids = cv2.kmeans(frame_array, K, None, criteria, 10<span>, flags)
    centroids </span>=<span> np.uint8(centroids)
    </span><span>#</span><span> labels 的数个矩心以随机顺序排列,所以需要简单处理矩心</span>
    centroids =<span> centroids.flatten()
    centroids_sorted </span>=<span> sorted(centroids)
    </span><span>#</span><span> 获得不同 centroids 的明暗程度,0 为最暗</span>
    centroids_index = np.array([centroids_sorted.index(value) <span>for</span> value <span>in</span><span> centroids])
    bright </span>= [abs((3 * i - 2 * K) / (3 * K)) <span>for</span> i <span>in</span> range(1, 1 +<span> K)]
    bright_bound </span>=<span> bright.index(np.min(bright))
    shadow </span>= [abs((3 * i - K) / (3 * K)) <span>for</span> i <span>in</span> range(1, 1 +<span> K)]
    shadow_bound </span>=<span> shadow.index(np.min(shadow))
    labels </span>=<span> labels.flatten()
    </span><span>#</span><span> 将 labels 转变为实际的明暗程度列表</span>
    labels =<span> centroids_index[labels]
    </span><span>#</span><span> 解析列表</span>
    labels_picked = [labels[rows * width:(rows + 1) * width:2] <span>for</span> rows <span>in</span> range(0, height, 2<span>)]
    canvas </span>= np.zeros((3 * height, 3 * width, 3<span>), np.uint8)
 </span><span>#</span><span> 创建长宽为原图三倍的白色画布</span>
    canvas.fill(255<span>)
    y </span>= 8
    <span>for</span> rows <span>in</span><span> labels_picked:
        x </span>=<span> 0
        </span><span>for</span> cols <span>in</span><span> rows:
            </span><span>if</span> cols <=<span> shadow_bound:
                cv2.putText(canvas, str(random.randint(</span>2, 9<span>)),
                            (x, y), cv2.FONT_HERSHEY_PLAIN, </span>0.45, 1<span>)
            </span><span>elif</span> cols <=<span> bright_bound:
                cv2.putText(canvas, </span><span>"</span><span>-</span><span>"</span><span>, (x, y),
                            cv2.FONT_HERSHEY_PLAIN, </span>0.4, 0, 1<span>)
            x </span>+= 6<span>
        y </span>+= 6
    <span>return</span> canvas

www#gaodaima.com来源gaodai#ma#com搞@代~码网搞代码

 

 

 

原图如下:

 

效果图如下:

 

GIF动图

接下来我们演示将GIF转为字符画,功能实现主要用到的Python库为imageio,Pillow,安装使用 pip install imageio/Pillow 命令即可。

功能实现的基本思路如下:

  • 将gif图片的每一帧细分为静态图片
  • 将所有静态图片变成字符画
  • 将所有字符画重新合成gif

主要代码实现如下:

<span>#</span><span> 拆分 gif 将每一帧处理成字符画</span>
<span>def</span><span> gif2pic(file, ascii_chars, isgray, font, scale):
    </span><span>"""</span><span>
    file: gif 文件
    ascii_chars: 灰度值对应的字符串
    isgray: 是否黑白
    font: ImageFont 对象
    scale: 缩放比例
    </span><span>"""</span><span>
    im </span>=<span> Image.open(file)
    path </span>=<span> os.getcwd()
    </span><span>if</span>(<span>not</span> os.path.exists(path+<span>"</span><span>/tmp</span><span>"</span><span>)):
        os.mkdir(path</span>+<span>"</span><span>/tmp</span><span>"</span><span>)
    os.chdir(path</span>+<span>"</span><span>/tmp</span><span>"</span><span>)
    </span><span>#</span><span> 清空 tmp 目录下内容</span>
    <span>for</span> f <span>in</span> os.listdir(path+<span>"</span><span>/tmp</span><span>"</span><span>):
        os.remove(f)
    </span><span>try</span><span>:
        </span><span>while</span> 1<span>:
            current </span>=<span> im.tell()
            name </span>= file.split(<span>"</span><span>.</span><span>"</span>)[0]+<span>"</span><span>_tmp_</span><span>"</span>+str(current)+<span>"</span><span>.png</span><span>"</span>
            <span>#</span><span> 保存每一帧图片</span>
<span>            im.save(name)
            </span><span>#</span><span> 将每一帧处理为字符画</span>
<span>            img2ascii(name, ascii_chars, isgray, font, scale)
            </span><span>#</span><span> 继续处理下一帧</span>
            im.seek(current+1<span>)
    </span><span>except</span><span>:
        os.chdir(path)

</span><span>#</span><span> 将不同的灰度值映射为 ASCII 字符</span>
<span>def</span><span> get_char(ascii_chars, r, g, b):
    length </span>=<span> len(ascii_chars)
    gray </span>= int(0.2126 * r + 0.7152 * g + 0.0722 *<span> b)
    </span><span>return</span> ascii_chars[int(gray/(256/<span>length))]


</span><span>#</span><span> 将图片处理成字符画</span>
<span>def</span><span> img2ascii(img, ascii_chars, isgray, font, scale):
    scale </span>=<span> scale
    </span><span>#</span><span> 将图片转换为 RGB 模式</span>
    im = Image.open(img).convert(<span>"</span><span>RGB</span><span>"</span><span>)
    </span><span>#</span><span> 设定处理后的字符画大小</span>
    raw_width = int(im.width *<span> scale)
    raw_height </span>= int(im.height *<span> scale)
    </span><span>#</span><span> 获取设定的字体的尺寸</span>
    font_x, font_y = font.getsize(<span>"</span> <span>"</span><span>)
    </span><span>#</span><span> 确定单元的大小</span>
    block_x = int(font_x *<span> scale)
    block_y </span>= int(font_y *<span> scale)
    </span><span>#</span><span> 确定长宽各有几个单元</span>
    w = int(raw_width/<span>block_x)
    h </span>= int(raw_height/<span>block_y)
    </span><span>#</span><span> 将每个单元缩小为一个像素</span>
    im =<span> im.resize((w, h), Image.NEAREST)
    </span><span>#</span><span> txts 和 colors 分别存储对应块的 ASCII 字符和 RGB 值</span>
    txts =<span> []
    colors </span>=<span> []
    </span><span>for</span> i <span>in</span><span> range(h):
        line </span>= <span>""</span><span>
        lineColor </span>=<span> []
        </span><span>for</span> j <span>in</span><span> range(w):
            pixel </span>=<span> im.getpixel((j, i))
            lineColor.append((pixel[0], pixel[</span>1], pixel[2<span>]))
            line </span>+= get_char(ascii_chars, pixel[0], pixel[1], pixel[2<span>])
        txts.append(line)
        colors.append(lineColor)
    </span><span>#</span><span> 创建新画布</span>
    img_txt = Image.new(<span>"</span><span>RGB</span><span>"</span>, (raw_width, raw_height), (255, 255, 255<span>))
    </span><span>#</span><span> 创建 ImageDraw 对象以写入 ASCII</span>
    draw =<span> ImageDraw.Draw(img_txt)
    </span><span>for</span> j <span>in</span><span> range(len(txts)):
        </span><span>for</span> i <span>in</span><span> range(len(txts[0])):
            </span><span>if</span><span> isgray:
                draw.text((i </span>* block_x, j * block_y), txts[j][i], (119,136,153<span>))
            </span><span>else</span><span>:
                draw.text((i </span>* block_x, j *<span> block_y), txts[j][i], colors[j][i])
    img_txt.save(img)

</span><span>#</span><span> 读取 tmp 目录下文件合成 gif</span>
<span>def</span><span> pic2gif(dir_name, out_name, duration):
    path </span>=<span> os.getcwd()
    os.chdir(dir_name)
    dirs </span>=<span> os.listdir()
    images </span>=<span> []
    num </span>=<span> 0
    </span><span>for</span> d <span>in</span><span> dirs:
        images.append(imageio.imread(d))
        num </span>+= 1<span>
    os.chdir(path)
    imageio.mimsave(out_name </span>+ <span>"</span><span>_ascii.gif</span><span>"</span>,images,duration = duration)

 

原图如下:

 

黑白效果图如下:

 

彩色效果图如下:

 

总结

本文我们利用Python演示文稿将静态图和GIF转为字符画的方法,大家如果有兴趣的话,可以将自己喜欢的图转一下,如果对转换效果不满意,还可以修改代码,改成自己满意的效果。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:教你用Python将自己喜欢的图片转成字符画,居然还有动态的

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址