openpyxl编辑xlsx表格文件挺好用的,插入图片也方便。
但是,不知道是我学艺不精还是查资料手法不加,找到的方法默认只能把图片文件添加到表格sheet
如果是内存中的图片对象(比如cv2创建的图片,大图上的抠图 等等)不保存为文件想直接在这使用会导致保存表格文件时报错。错误原因如下
openpyxl载入图片有自己的方法库
from openpyxl.drawing.image import Image
给他一个图片文件路径就好了,返回对象就能添加到指定单元格了。
根据描述知道,这个类可以接收PIL.Image格式的图片对象
然后问题就来了,假如你把 PIL.Image.fromarray(img_cv2) 获得的对象传给他使用
结果会在你保存 Workbook为文件时报错。所以如果添加的图片是内存对象就需要做些修改
具体总结
from openpyxl import load_workbook, Workbook
from openpyxl.drawing.image import Image as wImage
from openpyxl.drawing.image import _import_image
from PIL import Image
import cv2
import io
# 如果要插入的图片是内存对象请使用这个重写的类
class rwImage(wImage):
# 能力有限只能做到样了,凑合能用吧
def _data(self):
"""
为了适用于内存中的图片对象
"""
img = _import_image(self.ref)
fp = io.BytesIO()
img.save(fp, format="png")
fp.seek(0)
return fp.read()
def test(excel_path, test_img_path):
# 尝试打开已有文件,失败则创建表格对象
try:
wb = load_workbook(excel_path)
except:
wb = Workbook()
sheet = wb.create_sheet("新sheet页")
line = 1
img = wImage(test_img_path) # 如果是文件,直接用原有类加载即可
sheet[f"A{line}"] = test_img_path
if 13.5 < img.height:
sheet.row_dimensions[line].height = img.height # 60
sheet.add_image(img, f"B{line}")
# 例举我遇到的需求
img_cv2 = cv2.imread(test_img_path) # opencv读取图片方便处理
H, W, _ = img_cv2.shape
ims = [None, None, None, None]
ims[0] = (img_cv2[:H // 2, :W // 2], "左上")
ims[1] = (img_cv2[:H // 2, W // 2:], "右上")
ims[2] = (img_cv2[H // 2:, :W // 2], "左下")
ims[3] = (img_cv2[H // 2:, W // 2:], "右下")
for im0,label in ims:
line += 1
pimg = Image.fromarray(cv2.cvtColor(im0, cv2.COLOR_BGR2RGB)) # 先转换PIL格式
xlsximg = rwImage(pimg) # !!!此时如果还用原有的类就会在save时报错!!!
sheet[f"A{line}"] = label
if 13.5 < xlsximg.height:
sheet.row_dimensions[line].height = xlsximg.height # 60
sheet.add_image(xlsximg, f"B{line}")
# 这时保存就不会报错
wb.save(excel_path)
if __name__ == '__main__':
excel_path = "testExcel.xlsx"
test_img_path = "testImg.jpg"
test(excel_path, test_img_path)
就当个笔记吧,省的下次使用又忘了
如果网友有更好的方法希望能告知与我,谢谢