自定义图像旋转方法异常:逆时针旋转仅首次生效求助
问题描述
我正在开发一个图像旋转程序,通过将图像转为二维numpy数组实现给定路径下图像的顺时针/逆时针旋转。目前顺时针旋转(rotate_Clockwise())可重复正常工作,但逆时针旋转(rotate_Counter())仅首次调用有效,后续调用会让图像顺时针旋转或恢复原状。
基础配置说明:
- 从PIL导入Image,导入numpy并命名为np
- 图像保存至原路径(导入和保存用同一路径)
已尝试的排查步骤
- 修改两种旋转方法中的变量名(将
new_image改为image2和image3),排查内存问题 - 多次重置
widthiterator变量,排查迭代器错误 - 测试同一运行实例中两次调用方法、每次仅调用一次旋转后重启程序/IDE,排除迭代起始点未重置的可能性
- 怀疑路径缓存问题,但实际第二次运行保存的图像和第一次不同,排除该猜想
代码实现
import time from PIL import Image import numpy as np path = "Insert_Path_Here" image = Image.open(path) class Image_Processer: def __init__(self, image, path): self.image = image self.data = np.asarray(image) self.data_type = type(self.data) self.data_shape = self.data.shape self.path = path # 顺时针旋转图像 def rotate_Clockwise(self): print("Rotating Clockwise") size = [len(self.data[0]), len(self.data)] # 宽度, 高度 image2 = [] # 创建新图像列表 for i in range(0,size[0]): # 根据原图像高度创建新图像的行 image2.append([]) heightiterator = size[1]-1 # 从最后一行开始 widthiterator = size[0]-1 # 从每行最后一个元素开始 while heightiterator >= 0: # 遍历原图像每一行 widthiterator = size[0]-1 # 重置到每行最后一个元素 while widthiterator >= 0: # 遍历当前行的元素 image2[widthiterator].append(self.data[heightiterator][widthiterator]) # 将列元素转为行元素 widthiterator -= 1 # 向前移动一个元素 heightiterator -= 1 # 向上移动一行 return np.asarray(image2) # 返回新图像的numpy数组 # 逆时针旋转图像 def rotate_Counter(self): print("Rotating Counter-Clockwise") size = [len(self.data[0]), len(self.data)] # 宽度, 高度 image3 = [] # 创建新图像列表 for i in range(0,size[0]): # 根据原图像高度创建新图像的行 image3.append([]) heightiterator = 0 # 从第一行开始 widthiterator = 0 # 从每行第一个元素开始 while heightiterator < size[1]: # 遍历原图像每一行 widthiterator = 0 # 重置到每行第一个元素 while widthiterator < size[0]: # 遍历当前行的元素 image3[widthiterator].append(self.data[heightiterator][widthiterator]) # 将列元素转为行元素 widthiterator += 1 # 向后移动一个元素 heightiterator += 1 # 向下移动一行 return np.asarray(image3) # 返回新图像的numpy数组 # 将新图像覆盖保存到原路径 def save_image(self, new_image): self.image = Image.fromarray(new_image) self.image.save(path) time.sleep(1) # 等待1秒 image1 = Image_Processer(image, path) #image1.save_image(image1.rotate_Clockwise()) image1.save_image(image1.rotate_Counter())
问题分析与解决建议
核心问题:逆时针旋转的数组构造逻辑错误
你的rotate_Counter()方法中,元素填充逻辑完全不符合逆时针旋转的数学规则,导致第一次旋转结果看似正确(可能是巧合),后续因为图像尺寸变化(旋转后宽高互换),错误被放大,出现反向旋转或恢复原状的现象。
错误点拆解:
- 元素映射逻辑错误:逆时针旋转90度,应该取原图像的每一列,从最后一行到第一行依次取出,作为新图像的一行。而你的代码是将原图像第height行第width列的元素,直接放到新图像第width行的末尾,完全不符合旋转逻辑。
- 类状态未同步:保存新图像后,类的
self.data没有更新为新图像的数组,后续调用旋转方法时,依然基于原始图像的数组计算,而非刚保存的图像。
修正后的代码
- 修复
rotate_Counter()方法:
def rotate_Counter(self): print("Rotating Counter-Clockwise") # 获取原图像的高度和宽度 orig_height, orig_width = self.data.shape[:2] # 逆时针旋转后,新图像的高度=原宽度,宽度=原高度 new_height, new_width = orig_width, orig_height image3 = [] # 创建新图像的空行 for _ in range(new_height): image3.append([]) # 逆时针旋转核心逻辑:遍历原图像的每一列,从下到上取元素,作为新图像的一行 for col in range(orig_width): for row in reversed(range(orig_height)): image3[col].append(self.data[row][col]) return np.asarray(image3)
- 修复
save_image()方法,同步类内部状态:
def save_image(self, new_image): self.image = Image.fromarray(new_image) self.image.save(self.path) # 使用实例的self.path而非全局变量,避免作用域问题 self.data = new_image # 更新实例的data属性,确保后续旋转基于最新图像 time.sleep(1)
额外建议
- 避免使用全局变量
path,类初始化时已接收path参数,直接用self.path更安全 - 可以用numpy内置的
np.rot90函数验证结果:np.rot90(self.data, k=1)对应逆时针旋转90度,np.rot90(self.data, k=-1)对应顺时针旋转90度,对比你的实现结果是否一致
内容的提问来源于stack exchange,提问作者HiThere
相关产品推荐
相关产品推荐

