Pillow(PIL)tkinter

【Python】画像ビューア(ズーム(拡大/縮小)、移動表示)

Canvasに画像を表示する のページではtkinterでGUIを作り画像ビューアを作りましたが、これに アフィン変換 を追加し、画像の拡大/縮小、移動の出来る画像ビューアを作成しました。

Python 画像ビューア ズーム 拡大/縮小 平行移動

機能は、Fileメニューから画像ファイルを開き、マウスホイールの上下で画像の拡大/縮小を行い、マウスの左ボタンのドラッグで画像を移動します。
左ボタンのダブルクリックで画像全体を表示します。
また、ウィンドウ下にはCanvas上のマウスポインタの座標と、マウスポインタ位置の画像の座標および、その輝度値を表示します。
ウィンドウの右下には画像ファイルの種類、画像サイズ、画像の種類を表示します。

Python 画像ビューア ズーム 拡大/縮小 平行移動

全ソースコード

参考

【Python/tkinter】Canvasに画像を表示する
まず、Canvasを作成し、画像ファイルを開き、Canvasに画像を表示するサンプルは以下のようになります。 import tkinter as tk from PIL import ImageTk class Application(tk...
アフィン変換(平行移動、拡大縮小、回転、スキュー行列)
画像の拡大縮小、回転、平行移動などを行列を使って座標を変換する事をアフィン変換と呼びます。 X,Y座標の二次元データをアフィン変換するには、変換前の座標を(x, y)、変換後の座標を(x',y')とすると回転や拡大縮小用の2行2列の行列と、...
【Python/NumPy】行列の演算(積、逆行列、転置行列、擬似逆行列など)
個人的には、行列は最小二乗法で近似式を求めるときや、アフィン変換を用いて画像の表示やリサイズを行う際に用いるのですが、この行列の演算は、PythonではNumPyを用いて行います。 NumPyのインポート import numpy as n...

コメント

  1. shoheikuni より:

    勝手ながら改変して利用させていただきました。
    なにか問題ございましたらご連絡お願いいたします。
    https://github.com/shoheikuni/Image-Registration-Tool/blob/main/annotate.py

    • Akira より:

      連絡頂き、ありがとうございます。
      自由に使って頂いて問題ありません。

  2. kubo より:

    python初心者ながらコメントさせていただきます。
    この記事を参考にさせていただきながらtkinterを勉強しているのですが、この機能にプラスして右クリックで3点の座標をとりその間の角度を算出する機能を追加していただけないでしょうか?
    忙しいと思いますので、できればで結構でございます。
    もし厳しいようでしたら、今後もこの記事を参考に勉強していきたいと思いますので、自分で頑張ります!

    • Akira より:

      コメントありがとうございます。

      ここで公開している内容は、できるだけ多くの人にプログラムのベースとして使ってもらいたく、シンプルにしておきたいのもあって、特定の機能の追加は、あまりやりたくないと考えています。
      そのため、機能の追加は、ご自身でやって頂けると幸いです。
      その際に、不明点などありましたら、また、コメントを頂ければと思います。

  3. けい より:

    丁寧な返信ありがとうございます.クラスの違いが原因であることが理解できました.クラスを確認する手段は初耳でしたので参考になります
    menu_open_clickedメソッドの下,本記事で言う32行目から新たに保存用のメソッドを追加してそのメソッド内にself.dst.save(filename)を実装しようとしました.
    ↓という感じです.

    def menu_save_clicked(self):
    #ファイルを保存する
    filename = tk.filedialog.asksaveasfilename(defaultextension = “.jpg”, filetypes=[(“JPEG file”, “.jpg”)], initialdir = os.getcwd())
    if filename != “”:
    self.dst.save(filename)

    ですが,
    AttributeError: ‘Application’ object has no attribute ‘dst’
    というエラーが出てしまい,画像が保存できませんでした,,,
    VSCodeを使用しているのですが,dst.saveの色が変わっていないのでうまく認識できていないのかな?とも思ったのですが,どうすればmenu_save_clickedメソッド内で保存が可能になるでしょうか,,?

    重ねての質問申し訳ありません.アドバイスいただけると嬉しいです!

    • Akira より:

      おそらく、dstからself.deftへの置換のし忘れがあるか、画像を表示する前に保存しようとしていないでしょうか?

    • けい より:

      コンストラクタでself.filenameを宣言するとうまくいきました,,
      アドバイスありがとうございます

  4. けい より:

    突然の質問すいません.

    記事を読みコードを使わせていただきました.大変参考になりました.ありがとうございます.
    一つ質問があるのですが,このプログラムで拡大(縮小)した画像を保存するにはどのようにすればよろしいでしょうか?

    個人的に調べて
    filename = tk.filedialog.asksaveasfilename(defaultextension = “.jpg”, filetypes=[(“JPEG file”, “.jpg”)], initialdir = os.getcwd())
    self.image.save(filename)
    という処理が入ったメソッドを追加したのですが
    AttributeError: ‘PhotoImage’ object has no attribute ‘save’
    というエラーがでてしまいうまくいきません.(pil_imageではこの処理はうまくいくのですが,,,)

    拙い文章で申し訳ありません.お忙しいところ恐縮なのですが,ご教授いただけると幸いです.

    • Akira より:

      けいさん、コメントありがとうございます。

      保存しようとしているself.imageはPhotoImageクラスのオブジェクトなので、saveのような保存するメソッドはありません。
      (参考)
      https://pillow.readthedocs.io/en/stable/reference/ImageTk.html?highlight=PhotoImage#PIL.ImageTk.PhotoImage

      画像の拡大、縮小そのものは
      dst = pil_image.transform(・・・・・
      の部分でやっています。
      つまり、pil_imageの画像を拡大/縮小した画像が dst になります。

      そのため
      dst.save(filename)
      のようにすると、拡大/縮小された画像が保存されます。

      もし、保存をdraw_imageのメソッド以外の場所でやりたい場合は、dst を self.dst に置き換えて、
      self.dst.save(filename)
      のようにしてください。

      また、pil_image や self.image、 dst などの型(クラス)が分からない場合は、下記のようなコードを追加して、確認してみてください。
      print(type(self.image))
      ※私は普段、Visual Studioを使っているので、ウォッチで見てますが。。

タイトルとURLをコピーしました