今回は画像の差分を確認するアプリを Python の tkinter を用いて開発していきたいと思います。
といっても、Python での差分を確認するための画像の作り方は下記ページで解説していますので、このページでの解説は主にアプリへの仕立て方の解説になります。
Pythonでの差分画像の作り方【NumPy・PIL】Contents
画像の差分確認アプリ
まずは今回作成するアプリがどのようなものであるかを紹介していきます。
アプリの起動画面
今回作成する画像の差分確認アプリの起動画面は下の画像のようになります。
左側にキャンバスを3つ設けており、各キャンバスはそれぞれ下記を表示するためのものになります
- 左:画像の1つ目
- 中:画像の2つ目
- 右:画像の1つ目と画像の2つ目の差分画像
また右側にはボタンを設けており、このボタンでユーザーからの操作を受け付けられるようにしています。
具体的には下記の7つのボタンを用意しています。
- 画像1選択
- 画像2選択
- 単純差分をとる
- 差分を強調する
- 大きな差分のみ強調する
- 差分に色をつける
- 差分に色を混ぜる
上の2つは「差分をとる画像を選択するボタン」になります。
一方で、下の5つは「差分画像を作成するボタン」になります。
差分画像は差分をとる画像が選択されていないと作成することができませんので、上の2つのボタンで画像が選択されるまでは「無効」状態にしています。
スポンサーリンク
アプリの使い方
続いてアプリの使い方について解説します。
このアプリは画面右側の7つのボタンによって操作を行えるようにしています。
画像の選択
「画像1選択」ボタンと「画像2選択」ボタンを押せば、下の画像のようなファイル選択画面が表示されます。
差分を取りたい画像を選択して Open ボタンを押せば、その選択した画像がアプリの左側のキャンバスに表示されます。
差分画像の作成
画像を2つ選択するまでは、下側の5つのボタンは「無効」状態にしていますが、画像を2つ選択すれば、下側の5つのボタンが「通常」状態に変化し、ボタンクリックによって差分画像が作成できるようになります。
下側の5つのボタンは全て差分画像を作成するものですが、ボタンによって下記のように作成される差分画像が異なります。
- 「単純差分をとる」ボタン:単純な差分画像を作る
- 「差分を強調する」ボタン:差分のある輝度値を
255
にする - 「大きな差分のみ強調する」ボタン:差分の大きな輝度値を
255
にする - 「差分に色をつける」ボタン:元画像に対して差分のある画素に色をつける
- 「差分に色を混ぜる」ボタン:元画像に対して差分のある画素に色を混ぜる
具体的にどのような差分画像が作成されるかは下記ページで解説していますので、こちらを参考にしていただければと思います。
Pythonでの差分画像の作り方【NumPy・PIL】ボタンを押して作成された差分画像はキャンバスに表示されます(一番右側のキャンバス)。
差分画像はキャンバスに合わせて拡大縮小しますので、差分画像そのものではないことに注意してください。
画像の差分確認アプリの作り方
では Python での tkinter を用いた「画像の差分確認アプリの作り方」について解説していきます。
クラス設計
今回作成するアプリに用意するクラスは Diff
のみになります。
UI 部分と差分画像を作成する処理を行う部分などはクラスとして分けてもよかったかもしれないですが、今回はクラスとしては Diff
のみ用意し、このクラスに差分画像を確認するアプリの全ての処理を行わせるようにしています。
クラスには下記のような属性を用意し、それぞれの初期化をコンストラクタ __init__
で実行するようにしています。
- 読み込んだ or 作成した画像
im1
:読み込んだ画像の1つ目im2
:読み込んだ画像の2つ目diff
:作成した差分画像
- 描画中の画像
draw_im1
:左のキャンバスに描画中の画像draw_im2
:中のキャンバスに描画中の画像draw_diff
:右のキャンバスに描画中の画像
- 画像を描画するキャンバス
canvas_im1
:左のキャンバスcanvas_im2
:中のキャンバスcanvas_diff
:右のキャンバス
- キャンバスのサイズ
canvas_width
:キャンバスの幅(単位:px)canvas_height
:キャンバスの高さ(単位:px)
- 差分を作成するボタンのリスト
buttons
:差分を作成するボタンを要素とするリスト
スポンサーリンク
ウィジェットの作成
では、この Diff
クラスを作り込むことでアプリを開発していきます。
まずはアプリの画面を構成するウィジェットを作成していきます。
画面を構成するウィジェットは下の図のようになります。
左側のフレームにはキャンバス3つを grid
メソッドにより横に並べています。
右側のフレームにはボタン7つを pack
メソッドにより並べています。
まあ両方 grid
もしくは pack
で配置しても良いのですが…。
ウィジェットの配置については下記で詳しく解説していますので、配置について知りたい方は是非下記ページを読んでみてください。
Tkinterの使い方:ウィジェットの配置(pack・grid・place)また、これらのボタンに関してはクリック時にそれぞれに対するメソッドを実行するために、command
を設定しています(具体的に設定するメソッドについては後述する差分画像作成機能の実装で解説していきます)。
さらに、下側5つのボタンに関しては、差分画像が作れるようになるまではクリックできないように、state
を tkinter.DISABLED
として Button
クラスのインスタンスを生成するようにしています。
ボタンウィジェット・Button
クラスについてや、command
や state
については下記ページで解説していますので、詳しく知りたい方は是非こちらを読んでみてください。
これらのウィジェットの作成を行うスクリプトは、最後に紹介する画像の差分確認アプリのスクリプトの下記のメソッドで実装しています。
createWidgets
createCanvas
createSelectButton
createDiffButton
画像の読み込み機能の実装
次はボタンがクリックされた時に実行する機能を実装をしていきます。
まずは「画像1選択」ボタンと「画像2選択」ボタンがクリックされた時に実行する「画像の読み込みを行う機能」を実装していきます。
この「画像の読み込みを行う機能」では、より具体的には下記のことを行います。
- ファイル選択画面を表示する
- 選択された画像を読み込む
- 読み込んだ画像をリサイズする
- リサイズした画像を tkinter 画像に変換する
- tkinter 画像をキャンバスに描画する
- 差分画像作成ボタンの有効化・無効化を行う
1つ1つの処理について解説していきたいと思います。
ファイル選択画面を表示する
まずはユーザーが差分をとりたい画像を選択できるようにファイル選択画面を表示します。
ファイル選択画面とは下の画像のような画面です。OS によっては見た目は異なるは思いますが、PC 使っているとよく見るマウス操作でファイルを選択できる画面ですね。
ファイル選択画面の表示の仕方などは下記のページで詳しく説明していますので、興味のある方は是非読んでみてください。
Python でファイル選択画面を表示する要は、tkinter.filedialog
モジュールに用意された askopenfilename
を実行することでファイル選択画面を表示することができます。
さらに、askopenfilename
の戻り値として、ファイル選択画面でユーザーが選択したファイルへのパスを取得することができます。
file_path = tkinter.filedialog.askopenfilename()
この「ファイル選択画面を表示する」を行う処理は、最後に紹介する画像の差分確認アプリのスクリプトの下記のメソッドで実装しています。
selectIm1
(1つ目の画像選択用)selectIm2
(2つ目の画像選択用)
選択された画像を読み込む
で、ファイル選択画面でユーザーが選択するのはあくまでもファイルへのパスですので、そのパスの画像を読み込んでやる必要があります。
今回は、この画像の読み込みに PIL の Image
モジュールを利用します。Image
モジュールに用意された open
関数を実行することで、引数に指定したパスのファイルを画像オブジェクトとして読み込むことができます。
im = Image.open(file_path)
この「選択された画像を読み込む」を行う処理についても、最後に紹介する画像の差分確認アプリのスクリプトの下記のメソッドで実装しています。
selectIm1
(1つ目の画像選択用)selectIm2
(2つ目の画像選択用)
読み込んだ画像をリサイズする
続いて読み込んだ画像をキャンバスに描画するための準備をしていきます。
キャンバスと画像のサイズが異なる可能性がありますので、そのまま表示するとキャンバスから画像がはみ出たりする可能性があります。
なので、まずは画像をキャンバスに合わせてリサイズします。
リサイズ自体は PIL の Image
モジュールの resize
メソッドにより行うことができます。
この resize
メソッドでは、このメソッドを実行した画像を引数で指定したサイズにリサイズすることができます。
resized_image = image.resize(resize_size)
ただし、単純にこの引数にキャンバスのサイズを指定してしまうと、画像のサイズとキャンバスのサイズの関係によっては変に画像が縦方向もしくは横方向に伸ばされた形で表示されてしまいます。
要は縦方向と横方向とで異なる拡大縮小率でリサイズされてしまうのです…。
なので、縦横のサイズ関係(要はアスペクト比)を保ったまま画像のリサイズを行うため、下記のようにリサイズ後の画像サイズを設定します。
キャンバスの幅 / 画像の幅
を計算キャンバスの高さ / 画像の高さ
を計算- 1. と 2. との計算結果の小さい方を拡大縮小率に設定
- リサイズ後のサイズを 3. で設定した拡大縮小率を用いて下記により計算
リサイズ後の画像の幅 = 画像の幅 * 拡大縮小率
リサイズ後の画像の高さ = 画像の高さ * 拡大縮小率
3. で “小さい方” を選択して拡大縮小率に設定することで、キャンバスからはみ出ることなく、ちょうどキャンバスに収まるサイズでリサイズすることができます。
この「読み込んだ画像をリサイズする」を行う処理は、最後に紹介する画像の差分確認アプリのスクリプトの下記のメソッドで実装しています。
resize
リサイズした画像を tkinter 画像に変換する
続いてリサイズした画像を tkinter のキャンバスに描画可能な tkinter 画像に変換します。
この変換を行うのは、PIL で作成した画像はそのままではキャンバスには描画できないためです。
この変換方法は下記ページで詳しく解説します。
【Python】PIL ⇔ OpenCV2 ⇔ Tkinter 画像オブジェクトの相互変換要は PIL の ImageTk モジュールに用意された PhotoImage
関数を実行することで PIL 画像を tkinter 画像に変換することができます。
この「リサイズした画像を tkinter 画像に変換する」を行う処理は、最後に紹介する画像の差分確認アプリのスクリプトの下記のメソッドで実装しています。
drawImage
tkinter 画像をキャンバスに描画する
続いて tkinter 画像をキャンバスに描画します。
この tkinter 画像はリサイズも完了していますので、あとはキャンバスに描画すれば良いだけです。
このキャンバスへの図形や画像の描画については下記ページで解説しています。
Tkinterの使い方:Canvasクラスで図形を描画する要は Canvas
クラスの create_image
メソッドの実行によりキャンバスに画像を描画することができます。
ただし、今回は画像の中心がキャンバスの中心に来るようにキャンバスへの画像の描画を行うため、そのための引数指定を行う必要があります。
create_image
メソッドでは、これも下記ページで解説していますが、第1引数と第2引数及び anchor
引数により画像の描画位置を調整することができます。
具体的には、第1引数と第2引数では基準位置を表す座標を指定し、anchor
引数ではこの基準位置を画像のどの位置にするかを指定して描画位置を指定します。
つまり、第1引数と第2引数でキャンバスの中心座標を指定し、anchor
引数で画像を中心を意味する tkinter.CENTER
を指定すれば、キャンバスの中心に画像の中心が来るように画像を描画することができます。
この「tkinter 画像をキャンバスに描画する」を行う処理についても、最後に紹介する画像の差分確認アプリのスクリプトの下記のメソッドで実装しています。
drawImage
差分画像作成ボタンの有効化・無効化を行う
画像の描画はここまでで、最後に差分画像作成ボタンの有効化・無効化を行います。
前述でも触れましたが、差分画像が作成できるのは、差分をとる2つの画像が読み込まれてからです。
ですので、差分画像が作成できない時にはボタンが押すことができないように、差分画像作成ボタンを無効化するようにしています(ウィジェットの作成時にボタンの state
を tkinter.DISABLED
に設定しておく)。
そして、画像の読み込みの最後で、下記の条件を満たしているか確認し、満たしている時、つまり差分画像の作成の準備が整った時に差分画像作成ボタンを有効(通常状態)に設定するようにしています。
- 2つの画像が読み込まれている
- 2つの画像のサイズが同じ
より具体的には、上記の2条件を満たしている時にボタンの state
を tkinter.NORMAL
に設定します。
こんな感じでボタンの状態(無効状態や通常状態)を切り替えることで、準備が整っていない間にユーザーから処理が実行されたりすることを防ぐことができ、ユーザーにとっても操作しやすいアプリにすることができます。
この「差分画像作成ボタンの有効化・無効化を行う」を行う処理は、最後に紹介する画像の差分確認アプリのスクリプトの下記のメソッドで実装しています。
enableButton
差分画像作成機能の実装
続いて差分画像作成機能を実装していきます。
差分画像の作成
といっても、この機能のコアの処理やそのスクリプトは下記ページで紹介していますので、このページでは次に紹介する画像の差分確認アプリのスクリプトのメソッドとの関係だけを説明したいと思います。
Pythonでの差分画像の作り方【NumPy・PIL】上記ページで紹介している5つの方法による差分画像の作成を、次に紹介する画像の差分確認アプリのスクリプトの DIff
クラスのメソッドでそれぞれ作成するようにしています。
- 単純な差分画像を作る:
simpleDiff
- 差分のある輝度値を
255
にする:emphasizeDiff
- 差分の大きな輝度値を
255
にする:emphasizeLargeDiff
- 元画像に対して差分のある画素に色をつける:
colorDiff
- 元画像に対して差分のある画素に色を混ぜる:
blendDiff
画像の差分確認アプリで説明したように、アプリでは各ボタンがクリックされた際には下記の処理を行うようにしていますので、
- 「単純差分をとる」ボタン:単純な差分画像を作る
- 「差分を強調する」ボタン:差分のある輝度値を
255
にする - 「大きな差分のみ強調する」ボタン:差分の大きな輝度値を
255
にする - 「差分に色をつける」ボタン:元画像に対して差分のある画素に色をつける
- 「差分に色を混ぜる」ボタン:元画像に対して差分のある画素に色を混ぜる
各ボタンは command
引数に下記のメソッドを設定して作成する(Button
クラスのコンストラクタを実行する)ことになります。
- 「単純差分をとる」ボタン:
simpleDiff
- 「差分を強調する」ボタン:
emphasizeDiff
- 「大きな差分のみ強調する」ボタン:
emphasizeLargeDiff
- 「差分に色をつける」ボタン:
colorDiff
- 「差分に色を混ぜる」ボタン:
blendDiff
差分画像の描画
差分画像を作成した後は、その差分画像をキャンバスに描画してアプリに表示します。
これは画像のキャンバスへの描画に関しては画像の読み込み機能の実装で解説しており、ここで紹介した方法で、読み込んだ画像の代わりに作成した画像を描画してやれば良いです。
スポンサーリンク
画像の差分確認アプリのスクリプト
ここまで解説してきた内容を踏まえて作成した画像の差分確認アプリのスクリプトは下記のようになります。
import tkinter
import numpy as np
from PIL import Image, ImageTk
import tkinter.filedialog
class Diff():
def __init__(self, master):
# アプリのインスタンス
self.master = master
# 読み込んだor作成した画像(PIL画像)
self.im1 = None
self.im2 = None
self.diff = None
# 描画中の画像(tkinter画像)
self.draw_im1 = None
self.draw_im2 = None
self.draw_diff = None
# 画像を描画するキャンバス
self.canvas_im1 = None
self.canvas_im2 = None
self.canvas_diff = None
# キャンバスのサイズ
self.canvas_width = 300
self.canvas_height = 300
# 差分を作成するボタンのリスト
self.buttons = []
# ウィジェット作成
self.createWidgets()
def createWidgets(self):
'''
ウィジェットの作成と配置を行う
'''
# キャンバスを配置するフレーム作成
frame1 = tkinter.Frame(
self.master,
)
frame1.grid(column=0, row=0)
# ボタンを配置するフレーム作成
frame2 = tkinter.Frame(
self.master,
)
frame2.grid(column=1, row=0)
# キャンバスを作成
self.canvas_im1 = self.createCanvas(
master=frame1, column=0, row=0
)
self.canvas_im2 = self.createCanvas(
master=frame1, column=1, row=0
)
self.canvas_diff = self.createCanvas(
master=frame1, column=2, row=0
)
# 画像選択ボタンを作成
self.createSelectButton(
master=frame2,
text="画像1選択",
command=self.selectIm1
)
self.createSelectButton(
master=frame2,
text="画像2選択",
command=self.selectIm2
)
# 差分画像作成ボタンを作成(リストに追加)
self.buttons.append(
self.createDiffButton(
master=frame2,
text="単純差分をとる",
command=self.simpleDiff
)
)
self.buttons.append(
self.createDiffButton(
master=frame2,
text="差分を強調する",
command=self.emphasizeDiff
)
)
self.buttons.append(
self.createDiffButton(
master=frame2,
text="大きな差分のみ強調する",
command=self.emphasizeLargeDiff
)
)
self.buttons.append(
self.createDiffButton(
master=frame2,
text="差分に色を付ける",
command=self.colorDiff
)
)
self.buttons.append(
self.createDiffButton(
master=frame2,
text="差分に色を混ぜる",
command=self.blendDiff
)
)
def createCanvas(self, master, column, row):
'''
キャンバスを作成する
master:キャンバスの配置先のウィジェット
column:gridで貼り付ける位置(行)
row:gridで貼り付ける位置(列)
'''
# Canvasインスタンスを作成して配置
canvas = tkinter.Canvas(
master,
bg="white",
width=self.canvas_width,
height=self.canvas_height,
highlightthickness=0
)
canvas.grid(
column=column, row=row,
padx=10, pady=10
)
return canvas
def createSelectButton(self, master, text, command):
'''
画像選択ボタンを作成する
master:ボタンの配置先のウィジェット
text:ボタンに表示するテキスト
command:ボタンクリック時に実行する関数(メソッド)
'''
# Buttonインスタンスを作成して配置
button = tkinter.Button(
master,
text=text,
command=command
)
button.pack(
padx=10, pady=10
)
return button
def createDiffButton(self, master, text, command):
'''
差分画像作成ボタンを作成する
master:ボタンの配置先のウィジェット
text:ボタンに表示するテキスト
command:ボタンクリック時に実行する関数(メソッド)
'''
button = tkinter.Button(
master,
state=tkinter.DISABLED, # 画像選択するまで無効
text=text,
command=command
)
button.pack(
padx=10, pady=10
)
return button
def resize(self, img):
'''
画像をリサイズする
img:リサイズするPIL画像
'''
# 画像のサイズ取得
width, height = img.size
# キャンバスと画像のサイズから拡大縮小率計算
width_ratio = self.canvas_width / width
height_ratio = self.canvas_height / height
ratio = min((width_ratio, height_ratio))
# リサイズ後のサイズ計算
resize_width = int(ratio * width)
resize_height = int(ratio * height)
# リサイズ実行
resize_img = img.resize((resize_width, resize_height))
return resize_img
def drawImage(self, canvas, img):
'''
キャンバスに画像を描画する
canvas:描画先のキャンバス
img:描画する画像
'''
# キャンバスに合わせてリサイズ
resize_img = self.resize(img)
draw_img = ImageTk.PhotoImage(resize_img)
# キャンバス上のオブジェクトを全て削除
ids = canvas.find_all()
for id in ids:
canvas.delete(id)
# キャンバスに画像描画
canvas.create_image(
self.canvas_width // 2, self.canvas_height // 2,
image=draw_img,
anchor=tkinter.CENTER
)
return draw_img
def selectIm1(self):
'''
1つ目の画像を読み込みキャンバスに描画する
'''
# ファイル選択ダイアログの表示
file_path = tkinter.filedialog.askopenfilename()
if len(file_path) != 0:
# ファイルが選択された場合
# 画像としてファイルを開いてRGB変換
im = Image.open(file_path)
self.im1 = im.convert("RGB")
# 画像を描画後、描画している画像を受け取る
self.draw_im1 = self.drawImage(self.canvas_im1, self.im1)
# 差分画像作成ボタンの有効・無効化
self.enableButton()
def selectIm2(self):
'''
2つ目の画像を読み込みキャンバスに描画する
'''
# ファイル選択ダイアログの表示
file_path = tkinter.filedialog.askopenfilename()
if len(file_path) != 0:
# ファイルが選択された場合
# 画像としてファイルを開いてRGB変換
im = Image.open(file_path)
self.im2 = im.convert("RGB")
# 画像を描画後、描画している画像を受け取る
self.draw_im2 = self.drawImage(self.canvas_im2, self.im2)
# 差分画像作成ボタンの有効・無効化
self.enableButton()
def enableButton(self):
'''
差分画像作成ボタンの有効化/無効化を行う
'''
if not self.im1 or not self.im2:
# 画像がセット済でないならボタン無効
for button in self.buttons:
button.config(state=tkinter.DISABLED)
return
if self.im1.size != self.im2.size:
# 画像サイズが異なるならボタン無効
for button in self.buttons:
button.config(state=tkinter.DISABLED)
return
# 画像がセット済&サイズ一緒ならボタン有効
for button in self.buttons:
button.config(state=tkinter.NORMAL)
def simpleDiff(self):
'''
単純な差分画像を作成する
'''
# 差分配列作成
diff_i16 = self.createDiffArr()
# np.uint8型で扱える値に変換
diff_n_i16 = ((diff_i16 + 256) // 2)
# NumPy配列をnp.uint8型に変換
diff_u8 = diff_n_i16.astype(np.uint8)
# PIL画像に変換
self.diff = Image.fromarray(diff_u8)
# キャンバスに描画
self.draw_diff = self.drawImage(self.canvas_diff, self.diff)
def emphasizeDiff(self):
'''
差分のある輝度値を強調した画像を作成する
'''
# 差分配列作成
diff_i16 = self.createDiffArr()
# 差分の絶対値が0以外の輝度値を255に変換
diff_bool = diff_i16 != 0
diff_bin_u8 = diff_bool.astype(np.uint8)
diff_u8 = diff_bin_u8 * 255
# PIL画像に変換
self.diff = Image.fromarray(diff_u8)
# キャンバスに描画
self.draw_diff = self.drawImage(self.canvas_diff, self.diff)
def emphasizeLargeDiff(self):
'''
差分の大きな輝度値を強調した画像を作成する
'''
# 差分配列作成
diff_i16 = self.createDiffArr()
# 差分の絶対値が30を超える輝度値を255に変換
diff_bool = np.abs(diff_i16) > 30
diff_bin_u8 = diff_bool.astype(np.uint8)
diff_u8 = diff_bin_u8 * 255
# PIL画像に変換
self.diff = Image.fromarray(diff_u8)
# キャンバスに描画
self.draw_diff = self.drawImage(self.canvas_diff, self.diff)
def colorDiff(self):
'''
差分のある画素に色をつけた画像を作成する
'''
# 1つ目の画像を配列変換
im1_u8 = np.array(self.im1)
# 差分配列作成
diff_i16 = self.createDiffArr()
# 差分の絶対値が0以外の輝度値を255に変換
diff_bool = diff_i16 != 0
# 輝度値に差がある画素の輝度値を255とするグレースケール画像の配列作成
mask_bool = diff_bool[:,:,0] | diff_bool[:,:,1] | diff_bool[:,:,2]
mask_u8 = mask_bool.astype(np.uint8) * 255
# 全ての画素の色を(0,255,0)とした配列作成
green_u8 = np.zeros(im1_u8.shape, np.uint8)
green_u8[:,:,1] = 255
# PIL画像に変換
mask_img = Image.fromarray(mask_u8)
green_img = Image.fromarray(green_u8)
# 1つ目の画像に貼り付け
self.diff = self.im1.copy()
self.diff.paste(im=green_img, mask=mask_img)
# キャンバスに描画
self.draw_diff = self.drawImage(self.canvas_diff, self.diff)
def blendDiff(self):
'''
差分のある画素に色を混ぜた画像を作成する
'''
# 1つ目の画像を配列変換
im1_u8 = np.array(self.im1)
# 差分配列作成
diff_i16 = self.createDiffArr()
# 差分の絶対値が0以外の輝度値を255に変換
diff_bool = diff_i16 != 0
# 色ごとに分離した配列を参照
r_bool = diff_bool[:,:,0]
g_bool = diff_bool[:,:,1]
b_bool = diff_bool[:,:,2]
# 輝度値に差がある画素の輝度値を255とするグレースケール画像の配列作成
mask_bool = r_bool | g_bool | b_bool
mask_u8 = mask_bool.astype(np.uint8) * 255
mask_img = Image.fromarray(mask_u8)
# 全ての画素の色を(0,255,0)とした配列作成
green_u8 = np.zeros(im1_u8.shape, np.uint8)
green_u8[:,:,1] = 255
# 色を混ぜる
blend_u8 = im1_u8 * 0.75 + green_u8 * 0.25
blend_img = Image.fromarray(blend_u8.astype(np.uint8))
# 1つ目の画像に貼り付け
self.diff = self.im1.copy()
self.diff.paste(im=blend_img, mask=mask_img)
# キャンバスに描画
self.draw_diff = self.drawImage(self.canvas_diff, self.diff)
def createDiffArr(self):
'''
差分配列を作成する
'''
# NumPy配列へ変換
im1_u8 = np.array(self.im1)
im2_u8 = np.array(self.im2)
# 負の値も扱えるようにnp.int16に変換
im1_i16 = im1_u8.astype(np.int16)
im2_i16 = im2_u8.astype(np.int16)
# 差分配列作成
diff_i16 = im1_i16 - im2_i16
return diff_i16
# プログラムの開始
app = tkinter.Tk()
diff = Diff(app)
app.mainloop()
まとめ
このページでは画像の差分確認アプリの作り方について解説しました。
差分画像の作り方自体は下記ページで全て解説していますが、アプリに仕立てる上でいろいろ工夫が必要である点を感じ取っていただいたのではないかと思います。
Pythonでの差分画像の作り方【NumPy・PIL】このページのスクリプトでも使用している PIL や OpenCV を利用することで、高度な画像処理を行なう画像処理アプリなんかも作成することができます。
tkinter + PIL や tkinter + OpenCV 等の組み合わせによりさまざまなアプリが作成できますので、差分確認アプリ以外にもいろんなアプリを作ってみてください!