以下是我的代码:
workbook = load_workbook(path)
sheet = workbook.active
image_loader = SheetImageLoader(sheet)
def get_cell_image(image_loader, cell_name):
image = image_loader.get(cell_name)
image = np.array(image)
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
return image
get_cell_image(image_loader, 'A2')
get_cell_image(image_loader, 'A2')
我第二次尝试运行同一行代码时,我得到了
ValueError:对已关闭文件进行 I/O 操作。
我正在尝试做两个for循环。通过内循环读取 Excel 文件中的所有图像。当循环第二次运行时,我遇到了同样的错误。我试图通过在同一个单元上运行相同的图像加载器两次来简化我的问题。这导致了同样的错误。
Openpyxl 代码在加载时打开图像文件,但当它读取文件以获取字节数据时,它会关闭该文件。因此,尝试第二次读取同一图像的数据会失败,因为该图像文件现已关闭。
img._data()
函数执行此操作,因此一旦在图像上运行一次,您就无法在同一图像上再次运行它。要执行您需要的操作,您可以在第一次读取时保存该图像字节数据,在本例中保存到针对单元格坐标的字典中。
因此,在第一次请求单元格“A2”中的图像时,会根据全局字典“image_bytes_dict”检查单元格,如果不存在则添加其数据。然后,在第二个请求时,由于该单元格确实存在于字典中,因此将从那里获取数据。
此代码示例不使用 SheetImageLoader,它运行相同的函数来获取数据。
import numpy as np
from openpyxl import load_workbook
import cv2
import io
from PIL import Image
import string
image_bytes_dict = {} # Dictionary to hold image bytes data with cell co-ord as key
def get_cell_image(ws, cell_name):
for img in ws._images:
row = img.anchor._from.row + 1
col = string.ascii_uppercase[img.anchor._from.col]
if f'{col}{row}' == cell_name:
if cell_name not in image_bytes_dict:
image_bytes_dict[cell_name] = img._data()
### bytes data is always loaded from the dictionary
image = Image.open(io.BytesIO(image_bytes_dict[cell_name]))
image = np.array(image)
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
return image
workbook = load_workbook(path)
sheet = workbook.active
get_cell_image(sheet, 'A2')
get_cell_image(sheet, 'A2')