はじめに
undo・・・直前の操作を取り消すこと (パワポのctr+Z)
redo・・・undoで一旦取り消した操作をやり直すこと(パワポのctr+Shift+Z)
画像処理とする際undoとredoがあると便利だなと思い、
自分なりにpythonで実装してみました。
undo redo 実装の説明
undo, redo用のデータを保存するリストをundo_list, redo_listとします。
画像処理をする際に、処理前のデータを都度undo_listに追加することで,後から復元できるようにしていきます。
undo操作の際は、以下の操作を行います
・現在の画像をredo_listに追加する。
・undo_listの末尾のデータを現在の画像と置き換える。
redo操作の際はundo操作の逆を行います。
・現在の画像をundo_listに追加する。
・redo_listの画像を、現在の画像と置き換える。
実際の実装
以上のことを踏まえて、以下のように実装してみました。
class Image(object):
def __init__(self,data):
self.data=data
self.shape=data.shape
self.undos=[] #undo_list
self.redos=[] #redo_list
def __set_undo(self):
self.undos.append(self.data.copy()) #undo_listの末尾に今のデータを追加
if len(self.undos)>5:
self.undos.pop(0) #undo listの先頭の値を削除する。
#undo_listにデータが蓄積されることを防ぐために、
#5つ以上の数のデータが追加された場合は、リストの先頭のデータを削除。
def __set_redo(self):
self.redos.append(self.data.copy()) #redo_listの末尾に今のデータを追加
if len(self.undos)>5:
self.redos.pop(0) #redo listの先頭の値を削除する。
def undo(self):
if not self.undos: #undo listが空の場合
print('ERROR: No undo data')
sys.exit()
self.__set_redo()
self.data=self.undos.pop(-1) #undo listから一番最後の値を取得し、削除する。
def redo(self):
if not self.redos: #redo listが空の場合
print('ERROR: No redo data')
sys.exit()
self.__set_undo()
self.data=self.redos.pop(-1) #redo listから一番最後の値を取得し、削除する。
#適当な処理
def add_noise(self,var=30):
self.__set_undo()
noise=np.random.normal(scale=var, size=self.shape)
self.data+=noise
def rot(self, k):
self.__set_undo()
self.data=np.rot90(self.data, k=k)
def plot(self):
plt.figure()
plt.imshow(self.data, cmap='gray')
if __name__=='__main__':
data=misc.ascent().astype(np.float32) # 階段の画像の取得
img=Image(data)
適当な処理として、ガウシアンノイズを加える操作と、回転操作の関数を加えました。
各処理の前にself.__set_undo()を行うことで、処理前の画像をundo_listに加えています。
画像処理をしていきます。
img.plot() #最初の画像の表示
img.add_noise()
img.plot()
img.rot(k=1)
img.plot()
ここからundoしていきます。
img.undo()
img.plot()
img.undo()
img.plot()
ここでもう一回img.undo()
をするとundo listが空のためエラーが返されます。
ERROR: No undo data
An exception has occurred, use %tb to see the full traceback.
SystemExit
今度はredoしていきます
img.redo()
img.plot()
img.redo()
img.plot()
まとめ
自分の勉強がてら、undo機能を作ってみました。
なにかありましたらコメントいただけると幸いです。