使用Pandas UDF进行Spark图像处理时无法访问元素的问题
问题解决:Spark图像处理UDF中访问struct属性报错
错误原因
你遇到的AttributeError: 'str' object has no attribute 'width',核心原因是Spark将struct类型传入Pandas UDF时,会自动把struct序列化为JSON字符串,而非保留可直接访问属性的对象。所以你试图访问input_dim.width时,实际是在操作一个JSON字符串,自然触发属性不存在的错误。
解决方案
不要用struct封装width和height,直接将这两个字段作为独立列传入UDF,同时修正代码中的其他遗漏问题:
修正后的完整代码
from PIL import Image import resizeimage import numpy as np import pandas as pd from pyspark.sql.functions import pandas_udf, col # 加载数据集,修正原代码变量名不一致问题 roses = spark.read.format("image").load("/databricks-datasets/flower_photos/roses") # 直接选择独立的origin、data、width、height列,无需封装struct modified_dataset = roses.select("image.origin", "image.data", "image.width", "image.height") def resize_image(data, input_width, input_height): # 缩放尺寸转为整数,图像尺寸不支持浮点数 output_width = int(input_width * 0.5) output_height = int(input_height * 0.5) # 从二进制数据加载RGB图像 img = Image.frombytes("RGB", (input_width, input_height), bytes(data)) # 按指定尺寸缩放图像 img = resizeimage.resize_cover(img, (output_width, output_height)) # 将图像转回二进制格式 img_array = np.asarray(img) return bytearray(img_array) @pandas_udf("binary") def resize_image_udf(img_data, input_widths, input_heights): # 批量处理每一行的图像数据、宽度和高度 return pd.Series([ resize_image(data, width, height) for data, width, height in zip(img_data, input_widths, input_heights) ]) # 传入独立的width和height列生成缩略图 modified_dataset = modified_dataset.withColumn( "thumbnail", resize_image_udf(col("data"), col("width"), col("height")) ) # 查看结果 modified_dataset.select("origin", "thumbnail").show(5)
关键修改点
- 移除struct封装:直接使用独立的width和height列,避免Spark将struct序列化为JSON字符串。
- 修正变量名错误:原代码中加载数据集到
dataset但后续使用roses,导致未定义错误,已统一变量名。 - 补充缺失导入:添加了
resizeimage和numpy的导入,这两个库是代码运行必需的。 - 尺寸转为整数:图像缩放后的尺寸必须是整数,原代码中的浮点数会触发PIL的参数错误,已转为
int类型。
内容的提问来源于stack exchange,提问作者Yan Chong Tan
相关产品推荐
相关产品推荐

