如何用Pillow实现卫星图像循环平移以完成道路识别数据集增强?
解决Pillow实现卫星图像循环左右平移的问题
嘿,我明白你想要实现的是循环式左右平移(也就是无缝滚动的效果,超出边界的部分从对面补回来),你的当前代码用了PIL.Image.AFFINE变换,但问题在于默认的变换逻辑会把超出边界的区域填充为黑色,而不是循环复用图像内容。咱们来一步步解决这个问题:
为什么你的代码没达到预期?
你写的变换矩阵(1, 0, 0, 0, 1, 0)其实是无平移的恒等变换,哪怕你修改了平移参数(比如把第三个值改成平移量),默认的transform方法也不会自动处理循环边界,只会用黑色填充空白区域——这就是你看到左侧黑边的原因。
两种可行的解决方案
方法1:用Image.WRAP模式实现循环仿射变换
Pillow的transform方法支持method=Image.WRAP参数,这个模式会让超出图像边界的部分从对面的边界循环过来,正好匹配你的需求:
from PIL import Image def cyclic_translate_x(img, shift): """ 实现图像的循环左右平移 :param img: 输入的PIL图像对象 :param shift: 平移像素数,正数=图像向左移(右侧内容补到左侧),负数=图像向右移(左侧内容补到右侧) :return: 平移后的图像 """ width, height = img.size # 构造仿射变换矩阵:(1, 0, shift, 0, 1, 0) 表示仅x方向平移shift像素 return img.transform( img.size, Image.AFFINE, (1, 0, shift, 0, 1, 0), resample=Image.BILINEAR, # 根据需要选择采样方式,比如NEAREST/BILINEAR method=Image.WRAP # 关键:启用循环边界模式 )
方法2:手动分割拼接图像(更直观)
如果你想更清楚地控制整个过程,可以手动把图像切成两部分,再交换位置拼接,完全实现循环效果:
from PIL import Image def cyclic_translate_x_manual(img, shift): """ 手动实现循环左右平移 :param img: 输入的PIL图像对象 :param shift: 平移像素数,正数=右侧内容移到左侧,负数=左侧内容移到右侧 :return: 平移后的图像 """ width, height = img.size # 处理shift的取值,确保在0到width之间(避免重复平移) shift = shift % width if shift == 0: return img.copy() # 分割图像:取右侧shift宽度的部分,和左侧剩余部分 right_segment = img.crop((width - shift, 0, width, height)) left_segment = img.crop((0, 0, width - shift, height)) # 创建新图像,把右侧部分拼到左边,左侧部分拼到右边 new_img = Image.new(img.mode, img.size) new_img.paste(right_segment, (0, 0)) new_img.paste(left_segment, (shift, 0)) return new_img
测试示例
你可以用下面的代码测试两种方法:
if __name__ == "__main__": # 加载你的卫星图像 original_img = Image.open("your_satellite_image.jpg") # 向右平移150像素(即图像左移150,右侧150像素补到左侧) transformed_img1 = cyclic_translate_x(original_img, 150) transformed_img1.save("cyclic_translate_affine_result.jpg") # 手动拼接的方式实现同样效果 transformed_img2 = cyclic_translate_x_manual(original_img, 150) transformed_img2.save("cyclic_translate_manual_result.jpg")
两种方法都能实现你想要的“吃豆人”式循环平移,不会丢失任何图像信息。如果你的数据集需要批量处理,只需要把这些函数集成到你的数据增强流程里就好啦。
内容的提问来源于stack exchange,提问作者Camil Hamdane
相关产品推荐
相关产品推荐

