Python——实现图片转字符画的exe(附原代码)

本文介绍了作者之前开发的一个练手项目,通过Python的Tkinter和PIL库,实现了一个将上传的图片自动转换为字符画的功能,提供了一些优化建议,如图片选择、字符类型调整等。
摘要由CSDN通过智能技术生成

    一段时间以前用于练手的一个小项目。实现的主要功能是做一个exe(简陋的 XD),上传一张图片,并自动将其转化成字符画。效果如下:

1. 一些Tips:

(1)适合图片主体为大面积、不同色图像;

(2)可以调整字符数、字符类型,用以改进效果;

(3)设置用于画图的字符时,尽量用形状更小的字符代表更浅的颜色;也可以根据生成的字符画,选择合适的字符类型(如上图中的眼泪用 ‘l’ 就比较合适);

(4)远看效果会好一些;

2. 以下是其实现代码:

# Encoding=UTF-8
"""
CreateTime: ***
说明:点击上传图片,并将之转化为字符图
"""

from tkinter import *
from tkinter import simpledialog, filedialog
from tkinter import messagebox
from PIL import Image,ImageTk
import os

# 创建窗口:实例化一个窗口对象
window = Tk()
# 设置窗口大小:注意该乘号为 小写字母x
window_width = 1000
window_height = 600
window.geometry('1000x600')
# 设置窗口位置:window.geometry('800x400+位置横坐标+位置纵坐标')
# 设置窗口名称:
window.title('trans')

# 图片大小转化。先以高度为准。
def scale_resize(img):
    w_old, h_old = img.size[0], img.size[1]
    h_new = int(window_height*0.8)  # 高度为窗口高度的0.8
    scale = h_new/h_old
    w_new = int(w_old*scale)   # 按原比例转换
    if w_new > 0.4*window_width:  # 如果按原比例转换后宽度超过窗口宽度的0.4倍
        w_new = int(0.4*window_width)   # 则按宽度转换
        scale = w_new / w_old
        h_new = int(h_old*scale)
    img_new = img.resize((w_new,h_new))
    return img_new

# 获取用于替换的字符
def get_char(r, g, b, alpha=256):
    # 判断 alpha 值
    if alpha == 0:
        return ' '
    # 用于画图的字符
    # ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ")
    # 选取适合图片的字符集
    ascii_char = list("$@#%*bil,'. ")
    # 获取字符集的长度,这里为 70
    length = len(ascii_char)
    # 将 RGB 值转为灰度值 gray,灰度值范围为 0-255
    # Gray = R*0.299 + G*0.587 + B*0.114
    gray = int(0.299 * r + 0.587 * g + 0.114 * b)
    # 灰度值范围为 0-255,而字符集只有 70,需要将灰度值映射到指定的字符上
    unit = (256.0 + 1) / length
    # 返回灰度值对应的字符
    return ascii_char[int(gray / unit)]

# 图片转换为字符画任务脚本
def task1(img):
    width, height = int(0.1*img.size[0]), int(0.1*img.size[1])
    img = img.resize((width, height))
    # 初始化输出的字符串
    txt = ""
    for i in range(height):
        # 遍历该行中的每一列
        for j in range(width):
            # 将 (j,i) 坐标的 RGB 像素转为字符后添加到 txt 字符串
            txt += get_char(*img.getpixel((j, i)))  # getpixel是获取图像中某一点像素的RGB颜色值
            txt += get_char(*img.getpixel((j, i)))  # 鉴于一个字符长度比宽度大,故为了显示好看,每行输出两次。未必通用
        # 遍历完一行后需要增加换行符
        txt += '\n'
    # 输出到屏幕
    return txt

# 选择图片文件并显示图片
def choose_pic():
    file = filedialog.askopenfilename(initialdir=os.path.dirname(__file__)) #打开文件
    img_open = Image.open(file)
    global img_resize
    img_resize = scale_resize(img_open)  # 图片大小转换
    img = ImageTk.PhotoImage(img_resize)
    label_pic.config(image=img)
    label_pic.image = img

# 转换图片函数
def trans_pic():
    # 得到转换后字符图的txt
    txt = task1(img_resize)
    #print(txt)
    text_pic.delete("1.0", 'end')  # 清理文本框中原有内容
    text_pic.insert("1.0", txt)  # 将生成的字符图文本输入到文本框

# 上传按钮
button = Button(window,text="上传图片",font=("宋体",10),fg="blue",command=choose_pic)
button.grid(row=1,column=1)

label_pic = Label(window)
label_pic.grid(row=2,column=1)

# 图片转换按钮
button = Button(window,text="图片转换",font=("宋体",10),fg="blue",command=trans_pic)
button.grid(row=1,column=2)

# 设置转换后字符画展示窗口
text_pic = Text(window, font=('Courier New',8),width=80,height=40)
text_pic.grid(row=2,column=2)

# 展示窗口
window.mainloop()

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是 Python 实现 A* 算法的代码: ```python from queue import PriorityQueue class State: def __init__(self, value, parent, start=0, goal=0): self.children = [] self.parent = parent self.value = value self.distance = 0 if parent: self.start = parent.start self.goal = parent.goal self.path = parent.path[:] self.path.append(value) else: self.start = start self.goal = goal self.path = [value] def get_distance(self): pass def create_children(self): pass class State_String(State): def __init__(self, value, parent, start=0, goal=0): super().__init__(value, parent, start, goal) self.distance = self.get_distance() def get_distance(self): if self.value == self.goal: return 0 distance = 0 for i in range(len(self.goal)): letter = self.goal[i] distance += abs(i - self.value.index(letter)) return distance def create_children(self): if not self.children: for i in range(len(self.goal) - 1): val = self.value val = val[:i] + val[i+1] + val[i] + val[i+2:] child = State_String(val, self) self.children.append(child) class AStar_Solver: def __init__(self, start, goal): self.path = [] self.visited_queue = [] self.priority_queue = PriorityQueue() self.start = start self.goal = goal def solve(self): start_state = State_String(self.start, None, self.start, self.goal) count = 0 self.priority_queue.put((0, count, start_state)) while not self.path and self.priority_queue.qsize(): closest_child = self.priority_queue.get()[2] closest_child.create_children() self.visited_queue.append(closest_child.value) for child in closest_child.children: if child.value not in self.visited_queue: count += 1 if not child.distance: self.path = child.path break self.priority_queue.put((child.distance, count, child)) if not self.path: print("Goal of " + self.goal + " is not possible!") return self.path start = "dabcfehg" goal = "abcdefgh" a = AStar_Solver(start, goal) a.solve() print(a.path) ``` 在上述代码中,`State` 类表示状态,包含当前状态值、父状态、起始状态、目标状态、路径和距离等属性。`State_String` 类是 `State` 类的子类,用于处理字符串类型的状态。`get_distance` 函数用于计算当前状态与目标状态之间的距离,`create_children` 函数用于创建当前状态的子状态。 `AStar_Solver` 类是 A* 算法的主要实现部分。在 `__init__` 函数中,我们初始化路径和队列等属性。在 `solve` 函数中,我们首先将起始状态加入优先队列,并不断从队列中取出距离最短的状态,生成其子状态,并将未访问过的子状态加入优先队列中。在每次加入子状态到队列中时,我们使用 `count` 属性来确保优先队列中的元素是按照加入顺序排序的。当找到目标状态时,我们提取路径并返回。 最后,我们通过调用 `AStar_Solver` 类来解决字符串类型的问题。在此例中,我们使用字符串 "dabcfehg" 作为起始状态,使用字符串 "abcdefgh" 作为目标状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值