基于Python的图片转为字符画的系统

目录

1. 简介

 2. 技术介绍

(1) Pillow

(2) PySide2

3. 系统实现

(1) 图片转字符图实现

(2) GUI界面实现

4. 运行效果


1. 简介

        这是一个基于Python的图片转为ASCII字符的系统,话不多说,先看效果:

 2. 技术介绍

(1) Pillow

        Pillow 是 Python 图像处理库,是由 PIL(Python Imaging Library)库开发者创建的一个友好的 PIL 分支库,它提供了许多以 PIL 为基础的接口和许多新的功能。Pillow 库可以帮助您处理各种图像操作,如图像缩放、裁剪、旋转、转换格式等等。

        Pillow 支持的图像文件格式非常多,包括 BMP、GIF、JPEG、PNG、TIFF、WebP 等,同时还支持处理 GIF 动图,以及图像信息的获取等功能。此外,Pillow 提供了一些图像增强的方法,比如颜色调整、对比度调整、滤波器等。

(2) PySide2

        PySide2 是 Qt5 的 Python 绑定库,可以让开发者使用 Python 语言轻松地构建跨平台(包括 Windows、macOS、Linux、Android 和 iOS)的图形界面应用程序。PySide2 采用了 BSD 许可证,因此可以免费使用和分发。

        PySide2 可以调用 Qt5 中的各种功能,包括界面控件、布局管理器、事件处理、绘图等等。除此之外,它还提供了很多 Qt5 无法提供的高效便捷的 Pythonic API,如信号槽机制的 pyqtSignal 和 pyqtSlot、虚函数覆盖的 Python 装饰器、命令行参数解析等等。

3. 系统实现

        由于系统代码行数较多,这里只粘贴了部分关键代码:

(1) 图片转字符图实现

        try:
            #  将图片转换为ASCII字符
            with Image.open(self.image_path) as im:
                # 获取原图的高度与宽度
                width, height = im.size
                # 原图的高宽之比
                t = width/height
                # 设置转换出的字符图的高度,设置的值越小,转换出的字符图就越小,细节程度也低,该值不建议太大也不建议太小,介于50-200之间的整数即可
                # 这里我根据图片的高度来确定字符图的高度
                char_height = int(height/2)
                char_width = int(char_height*t*2)  # 通过图片高宽比例计算字符图的宽度,乘2是因为转换后宽度被压缩为原来的1/2
                # 将图片转换为单通道灰度图并调整为字符图的大小
                im = im.convert('L').resize((char_width, char_height))
                # 将像素映射为ASCII字符
                char_lst = ['@', '#', '8', 'M', '&', 'N', '9', 'H', 'Q', '4', 's', 'r',
                            '1', 'i', '*', ';', '~', ':', ',', '.', ' ']
                result = ''
                for j in range(im.size[1]):
                    for i in range(im.size[0]):
                        gray = im.getpixel((i, j))
                        idx = int(gray / (256 / len(char_lst)))
                        result += char_lst[idx]
                    result += '\n'

            if result:
                # 根据图片名称将字符保存到文件
                file_path, ext = os.path.splitext(self.image_path)
                filename = os.path.basename(file_path) + '.txt'
                file_path = os.path.join('./data', filename)
                with open(file_path, 'w') as f:
                    f.write(result)

                self.update_progress.emit(100)  # 发送完成进度信号
            else:
                self.update_progress.emit(0)  # 发送失败进度信号
        except:
            self.update_progress.emit(0)  # 发送失败进度信号

(2) GUI界面实现

    def __init__(self):
        super().__init__()

        # 设置窗口标题和图标
        self.setWindowTitle('图片转字符')
        self.setWindowIcon(QIcon('./icon/icon.ico'))

        # 设置图片显示标签
        self.image_label = QLabel()  # 创建图片显示标签
        self.image_label.setAlignment(Qt.AlignCenter)  # 居中对齐
        self.image_label.setFixedSize(400, 400)  # 设置固定大小
        self.image_label.setStyleSheet('border: 1px solid black;')  # 添加边框样式

        # 设置上传图片按钮
        self.upload_button = QPushButton('上传图片')  # 创建上传图片按钮
        self.upload_button.clicked.connect(self.upload_image)  # 绑定点击事件

        # 设置开始转换按钮
        self.convert_button = QPushButton('开始转换')  # 创建开始转换按钮
        self.convert_button.setDisabled(True)  # 初始状态禁用
        self.convert_button.clicked.connect(self.start_conversion)  # 绑定点击事件

        # 设置查看结果按钮
        self.result_button = QPushButton('查看结果')  # 创建查看结果按钮
        self.result_button.setDisabled(True)  # 初始状态禁用
        self.result_button.clicked.connect(self.show_result)  # 绑定点击事件

        # 设置进度标签
        self.progress_label = QLabel('')  # 创建进度标签
        self.progress_label.setAlignment(Qt.AlignCenter)  # 居中对齐

        # 设置标题
        title_layout = QHBoxLayout()  # 创建水平布局
        title_layout.addWidget(self.image_label)  # 将图片标签添加到布局中

        # 设置按钮
        button_layout = QHBoxLayout()  # 创建水平布局
        button_layout.addWidget(self.upload_button)  # 添加上传图片按钮
        button_layout.addWidget(self.convert_button)  # 添加开始转换按钮
        button_layout.addWidget(self.result_button)  # 添加查看结果按钮

        # 设置主布局
        main_layout = QVBoxLayout()  # 创建垂直布局
        main_layout.addLayout(title_layout)  # 添加标题布局
        main_layout.addLayout(button_layout)  # 添加按钮布局
        main_layout.addWidget(self.progress_label)  # 添加进度标签

        # 设置窗口布局
        self.setLayout(main_layout)  # 设置主布局
        self.setFixedSize(450, 520)  # 设置固定大小,增加高度避免遮挡进度标签

    def upload_image(self):
        # 选择并显示图片
        image_path, _ = QFileDialog.getOpenFileName(self, '上传图片', '/', 'Images (*.jpg *.jpeg *.png *.bmp)')
        if image_path:
            self.image_label.setPixmap(QPixmap(image_path).scaled(400, 400, Qt.KeepAspectRatio))
            self.convert_button.setEnabled(True)
            self.upload_button.setText('重新上传')
            self.image_path = image_path

    def start_conversion(self):
        # 转换图片为字符并保存到文件
        self.convert_button.setDisabled(True)
        self.result_button.setDisabled(True)
        self.convert_button.setText('转换中...')
        self.image2ascii = Image2ASCII(self.image_path)
        self.image2ascii.update_progress.connect(self.update_progress)
        self.image2ascii.start()

    def update_progress(self, progress):
        # 更新进度标签
        if progress == 100:
            self.progress_label.setText('转换完成')
            self.result_button.setEnabled(True)
            self.convert_button.setText('开始转换')
        else:
            self.progress_label.setText(f'转换进度:{progress}%')
            self.convert_button.setEnabled(False)

    def show_result(self):
        file_name, _ = QFileDialog.getOpenFileName(self, '查看结果', './data/', 'Text Files (*.txt)')
        if file_name:
            with open(file_name, 'r') as f:
                result = f.read()

                # 使用 os.startfile 打开文件
                os.startfile(file_name)

4. 运行效果

        运行效果如下图所示:

猜你喜欢

转载自blog.csdn.net/spx_0108/article/details/130794706