找回密码
 立即注册
首页 业界区 业界 我把Excel变成了像素画板!用Python实现图片到单元格的 ...

我把Excel变成了像素画板!用Python实现图片到单元格的映射

蛟当罟 6 小时前

 视频演示

 
我把Excel变成了像素画板!用Python实现图片到单元格的映射

 
大家好,这里是Coding茶水间!
最近做了一个有趣的小工具:用 Python 把任意图片“复刻”成 Excel 表格艺术。
通过解析图片像素值,然后在 Excel 单元格中填充对应颜色,就能生成一张由无数小方格组成的“像素画”。
这个工具不复杂,适合对图像处理和自动化感兴趣的小伙伴研究。
在这篇图文教程中,我会一步步带你了解工具的原理、代码实现和使用方法。
代码基于 PyQt5(GUI 界面)、OpenCV(图像处理)和 openpyxl(Excel 操作),简单易上手。感兴趣的同学可以直接 fork 代码试试!
工具效果预览

先来看看成品效果吧!左边是原图,右边是生成的 Excel 艺术(每个单元格就是一个像素)。
1.png

 
另一个例子,我换了张猫咪图片,生成后效果如下:
2.png

(截图说明:工具自动缩放图片到 320 宽,生成低分辨率 Excel 以节省资源,但细节依然清晰)
手工操作这种效果?想想看,一张 320x240 的图片就需要 76,800 个单元格手动填色……太恐怖了!用程序,几秒钟搞定。
实现原理

核心思路很简单:

  • 读取图片:用 OpenCV 加载图像,获取每个像素的 RGB 值。
  • 缩放处理:为了避免高分辨率图片占用过多资源,默认将宽度固定为 320,高度按比例缩放。
  • 生成 Excel:用 openpyxl 创建工作表,每个像素对应一个单元格,填充对应颜色的 PatternFill。
  • GUI 界面:PyQt5 提供简单界面,选择图片和保存路径,一键绘制,还带进度条显示。
环境准备


  • Python 3.8+
  • 依赖库:pip install PyQt5 opencv-python openpyxl numpy
  • UI 文件:用 Qt Designer 设计 excel_ui.py(我用的是一个简单的窗口,包含图片预览、路径输入和按钮)。
如果懒得配置环境,我还打包了 EXE 可执行文件(脱离 Python 环境)
完整代码

下面是核心代码,分为主窗口类和入口。代码不长,注释详尽。
  1. import sys
  2. from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox, QProgressDialog
  3. from PyQt5.QtGui import QImage, QPixmap
  4. from excel_ui import Ui_MainWindow  # Qt Designer 生成的 UI 文件
  5. from PyQt5.QtCore import Qt, QTimer
  6. import cv2
  7. import numpy as np
  8. import openpyxl
  9. from openpyxl.styles import PatternFill
  10. from openpyxl.utils import get_column_letter
  11. class MainWindow(QMainWindow, Ui_MainWindow):
  12.     def __init__(self, parent=None):
  13.         super().__init__(parent)
  14.         self.setupUi(self)
  15.         self.img_ori = None  # 存储原始图像
  16.     def select_pic(self):
  17.         """选择图片并预览"""
  18.         file_path, _ = QFileDialog.getOpenFileName(self, "选择图片", "", "Image Files(*.png *.jpg *.jpeg *.bmp)")
  19.         if file_path:
  20.             self.img_ori = cv2.imread(file_path)
  21.             img = cv2.cvtColor(self.img_ori, cv2.COLOR_BGR2RGB)
  22.             h, w, ch = img.shape
  23.             bytes_per_line = ch * w
  24.             q_image = QImage(img.data, w, h, bytes_per_line, QImage.Format.Format_RGB888)
  25.             q_pixmap = QPixmap.fromImage(q_image)
  26.             self.imageLabel.setPixmap(q_pixmap.scaled(
  27.                 self.imageLabel.width(), self.imageLabel.height(),
  28.                 Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation
  29.             ))
  30.     def select_excel(self):
  31.         """选择 Excel 保存路径"""
  32.         file_path, _ = QFileDialog.getSaveFileName(
  33.             self,
  34.             "设置 Excel 路径",
  35.             "",
  36.             "Excel Files (*.xlsx *.xls)"
  37.         )
  38.         if file_path:
  39.             self.excelPathLineEdit.setText(file_path)
  40.             return file_path
  41.         else:
  42.             return None
  43.     def huizhi(self):
  44.         """绘制图片到 Excel"""
  45.         if not hasattr(self, 'img_ori') or self.img_ori is None:
  46.             QMessageBox.warning(self, "警告", "请先选择图片!")
  47.             return
  48.         excel_path = self.excelPathLineEdit.text()
  49.         if not excel_path:
  50.             QMessageBox.warning(self, "警告", "请先选择 Excel 文件保存路径!")
  51.             return
  52.         try:
  53.             # 强制缩放宽度为 320,高度按比例计算
  54.             min_width = 320
  55.             image = self.img_ori
  56.             height, width = image.shape[:2]
  57.             scale_factor = min_width / width
  58.             new_width = min_width
  59.             new_height = int(height * scale_factor)
  60.             image = cv2.resize(image, (new_width, new_height))
  61.             # 创建 Excel 工作簿
  62.             workbook = openpyxl.Workbook()
  63.             sheet = workbook.active
  64.             # 设置单元格为正方形(宽度 3,高度 17)
  65.             for col in range(1, new_width + 1):
  66.                 sheet.column_dimensions[get_column_letter(col)].width = 3
  67.             for row in range(1, new_height + 1):
  68.                 sheet.row_dimensions[row].height = 17
  69.             # 创建进度条
  70.             progress = QProgressDialog("正在绘制图片到 Excel...", "取消", 0, new_height, self)
  71.             progress.setWindowTitle("进度")
  72.             progress.setWindowModality(Qt.WindowModal)
  73.             progress.setValue(0)
  74.             # 遍历图片像素并填充 Excel 单元格
  75.             for y in range(new_height):
  76.                 if progress.wasCanceled():
  77.                     break
  78.                 for x in range(new_width):
  79.                     b, g, r = image[y, x]  # OpenCV 默认 BGR 格式
  80.                     color = "{:02x}{:02x}{:02x}".format(r, g, b)  # 转换为 RGB 格式的十六进制
  81.                     if color == "000000":
  82.                         color = "010101"  # 纯黑色替换为深灰色
  83.                     fill = PatternFill(start_color=color, end_color=color, fill_type="solid")
  84.                     sheet.cell(row=y + 1, column=x + 1).fill = fill
  85.                 progress.setValue(y + 1)
  86.                 QApplication.processEvents()  # 确保 UI 更新
  87.             # 保存 Excel 文件
  88.             if not progress.wasCanceled():
  89.                 workbook.save(excel_path)
  90.                 QMessageBox.information(self, "成功", "图片已成功绘制到 Excel 文件!")
  91.             progress.close()
  92.         except Exception as e:
  93.             QMessageBox.critical(self, "错误", f"绘制失败: {str(e)}")
  94. if __name__ == '__main__':
  95.     app = QApplication(sys.argv)
  96.     window = MainWindow()
  97.     window.show()
  98.     sys.exit(app.exec())
复制代码
3.gif
代码亮点解析


  • 图像预览:select_pic() 用 QImage 实时显示选中的图片,保持宽高比。
  • 缩放优化:cv2.resize() 固定宽度 320,避免高分辨率卡顿。实际 Excel 文件大小控制在合理范围内。
  • 像素填充:双层循环遍历 (y, x),转 RGB 十六进制,应用 PatternFill。进度条用 QProgressDialog 实时反馈。
  • 异常处理:捕获保存错误,友好提示。
4.png

使用步骤


  • 运行程序(python main.py 或双击 EXE)。
  • 点击“选择图片”,挑选一张 PNG/JPG 等格式的图像,界面会预览。
  • 点击“选择 Excel 路径”,设置保存文件名(.xlsx)。
  • 点击“开始绘制”,等待进度条完成。
  • 打开生成的 Excel,Ctrl + 滚轮缩放查看效果!(建议全屏查看)
5.png

结语

这个小工具就是下午“无聊”时写的,编程的乐趣就在于把不可能变可能。
如果你有图像处理项目灵感,评论区聊聊~别忘了三连(点赞、收藏、关注)支持下,更多干货见!
如果代码有 bug 或优化建议,随时 issue 我。玩得开心!


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册