• 娱乐时间 —— 用python将图片转为excel十字绘


           最近看蛮多朋友在玩,要么只能画比较简单的,要么非常花时间。想了下本质上就是把excel对应的单元格涂色,如果能知道哪些格子要上什么颜色,用编程来实现图片转为excel十字绘应该是很方便的。
           图片的每一个像素点都可以数值化,那么将构成图片的每一个像素点填充到excel的单元格中去,然后合理调整单元格长宽比便可以拼成一副画。反过来想,用一张单元格足够小的excel表格将图片蒙上一层,犹如用 一张网去切割这张图片,图片被切割成一小块一小块 ,如果网格足够细,每一小块里面的颜色几乎只有一种,这样就可以用一个三元组(RGB)来刻画 ,这样一张图片就可以由一个很大的矩阵来刻画 ,矩阵中的每一个元素都是一个 RGB三元组。不管从图片到excel还是从excel到图片,我们都可以构建一个一一映射关系,我们便可以依循这个理论在excel作画。
           网上搜索了下用python就可以实现,主要是以下两个模块:
    • Pillow(PIL,Python Imaging Library):强大的图形处理库
    • openpyxl:用于操作excel的模板,之前也用到过

    代码主要来自:程序员如何 10 分钟用 Python 画出蒙娜丽莎? - 知乎

    直接运行会有报错,需要稍微修改:

    • 获取列信息:新版本修改了属性名,用原文的会报错
    1. # 修正前
    2. column = col[0].column
    3. # 修正後
    4. column = col[0].column_letter
    • 调整列宽部分:原文的1会让图片变得奇扁无比,测试设为8大小会比较合适
     worksheet.column_dimensions[_w].width = 8
    • 调整单元格大小:相对来说400更清晰
    1. MAX_WIDTH = 400
    2. MAX_HEIGHT = 400

    修改后代码如下:

    1. #!/usr/bin/env python
    2. # -*- coding:utf-8 -*-
    3. #@Time : 2023/09/10
    4. #@Author: Hehuyi_In
    5. #@File : picture_to_excel.py
    6. from PIL import Image
    7. import openpyxl
    8. from openpyxl.styles import fills
    9. import os
    10. MAX_WIDTH = 400
    11. MAX_HEIGHT = 400
    12. # excel的单元格默认是长方形,修改为正方形才不会使图片变形
    13. # 调整excel每个单元格大小,避免图片过大,excel无法打开
    14. # 过小电子画会过于模糊,太大excel可能无法打开
    15. def resize(img):
    16. w, h = img.size
    17. if w > MAX_WIDTH:
    18. h = MAX_WIDTH / w * h
    19. w = MAX_WIDTH
    20. if h > MAX_HEIGHT:
    21. w = MAX_HEIGHT / h * w
    22. h = MAX_HEIGHT
    23. return img.resize((int(w), int(h)), Image.ANTIALIAS)
    24. # 整型转16进制
    25. # getpixel()获取的颜色值是rgb十进制的,但fills.PatternFill 里的fgColor`参数接收到的颜色值是十六进制的值,因此需要转换
    26. def int_to_16(num):
    27. num1 = hex(num).replace('0x', '')
    28. # 位数只有一位时在前面补零
    29. num2 = num1 if len(num1) > 1 else '0' + num1
    30. return num2
    31. # 绘图函数
    32. def draw_jpg(img_path):
    33. # 打开图片
    34. img_pic = resize(Image.open(img_path))
    35. img_name = os.path.basename(img_path)
    36. # 输出的excel名,若已存在则删除
    37. out_file = img_name.split('.')[0] + '.xlsx'
    38. if os.path.exists(out_file):
    39. os.remove(out_file)
    40. # 新建一个excel文件
    41. workbook = openpyxl.Workbook()
    42. # 激活一个工作表(sheet)
    43. worksheet = workbook.active
    44. width, height = img_pic.size
    45. # 循环处理图片中的每个像素
    46. for w in range(1, width + 1):
    47. for h in range(1, height + 1):
    48. # getpixel函数用于获取像素色彩值,入参为像素坐标
    49. if img_pic.mode == 'RGB':
    50. r, g, b = img_pic.getpixel((w - 1, h - 1))
    51. elif img_pic.mode == 'RGBA':
    52. r, g, b, a = img_pic.getpixel((w - 1, h - 1))
    53. # 将rgb值转换为16进制
    54. hex_rgb = int_to_16(r) + int_to_16(g) + int_to_16(b)
    55. # 定位每个单元格
    56. cell = worksheet.cell(column=w, row=h)
    57. # 第一行
    58. if h == 1:
    59. _w = cell.column_letter
    60. _h = cell.col_idx
    61. # 调整列宽
    62. worksheet.column_dimensions[_w].width = 8
    63. # 调整行高
    64. worksheet.row_dimensions[h].height = 45
    65. # 填充颜色,fill_type是填充类型,fgColor是填充的颜色
    66. cell.fill = fills.PatternFill(fill_type="solid", fgColor=hex_rgb)
    67. print('saving...')
    68. workbook.save(out_file)
    69. print('success!')
    70. if __name__ == '__main__':
    71. draw_jpg('lyx.jpg')

    效果图,以我这个头像为例(excel画出来的图太大了,这里截了一部分)

    这要是手工画一张不得画几个月...但通过程序可以直接秒出,牛哇~

    参考
    https://zhuanlan.zhihu.com/p/95720761
    https://blog.51cto.com/u_15255081/6164226
    https://blog.csdn.net/weixin_43790276/article/details/108478270
    https://qiita.com/gorimacho/items/63707223e692f7401988

  • 相关阅读:
    聊聊GLM-4-9B开源模型的微调loss计算
    uniapp小程序更新逻辑,按实际开发为主
    数据库到底是什么?举例MySQL给你讲明白
    Python:实现fermat little theorem费马小定理算法(附完整源码)
    Web前端:Web 项目的前14个React图表库
    leetcode20. 有效的括号 [简单题]
    Java HTTP连接客户端,选 HttpClient 还是 OkHttp ?
    python+playwright 学习-81 page.expect_request()捕获网络请求
    原画设计咨询回复话术
    visual studio 2022 opencv 4.6.0 创建测试工程
  • 原文地址:https://blog.csdn.net/Hehuyi_In/article/details/52210231