画像選択のプログラムを使いやすく!!

Python

DICOMタグを取得するのも、画像処理をするのもまずはファイル選択することから始まります。


一番簡単な方法は、プログラムの中でファイルを指定することなのですが、それでは他のファイルを処理したいときにいちいちコードのファイル名を書き換えなければならないし、保存しているフォルダが違うと余計に面倒ですよね。


それを解決するために以前の記事で「ファイルを一つ選択する方法」「ファイルを複数選択する方法」「フォルダ内のファイルを一括選択する方法」と3回にわたって記事にしてきました。


いずれも、一つのファイル内にコードを記述していたわけですが、コードが長くなってくると目的のコードを探すのが大変になってしまいます。

そこで、今回はファイル選択の部分だけを一つのプログラム(モジュール)として作成し、他のプログラムから呼び出す方法を記載していきたいと思います。



ファイル名を「fileselect.py」として作成します。

ひとまず前3回分のコードを一つにコピペしてみました。


#ファイルを一つ選択::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
import tkinter
from tkinter import filedialog as tkFileDialog

def fileselect():
    root = tkinter.Tk()
    root.withdraw()

    fTyp = [('', '*')]

    iDir = 'C:/Desktop'

    filename = tkFileDialog.askopenfilename(filetypes=fTyp, initialdir=iDir)
    return filename


#ファイルを複数選択:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

# -*- coding: utf-8 -*-

import tkinter  # tkinterをインポート
from tkinter import filedialog as tkFileDialog


def fileselect():
    root = tkinter.Tk()
    root.withdraw()

    fTyp = [('', '*')]
    iDir = 'C:/Desktop'

    filenames = tkFileDialog.askopenfilenames(filetypes=fTyp, initialdir=iDir)

    return filenames


#ファイルをフォルダで一括選択:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
# -*- coding: utf-8 -*-

import tkinter  
from tkinter import filedialog as tkFileDialog
import glob

def fileselect():
    root = tkinter.Tk()  
    root.withdraw()  

    iDir = 'C:/Desktop'  

    dirname = tkFileDialog.askdirectory(initialdir=iDir)

    filenames = glob.glob(dirname +"/*")
    return filenames

ここで目に着くところが、import~というところが複数出てきていますのでこれを一番先頭に持ってきて、重複している部分を削除してしまいましょう。


そうすると、以下のようになります。


# -*- coding: utf-8 -*-

import tkinter  
from tkinter import filedialog as tkFileDialog
import glob

#ファイルを一つ選択::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def fileselect():
    root = tkinter.Tk()
    root.withdraw()

    fTyp = [('', '*')]

    iDir = 'C:/Desktop'

    filename = tkFileDialog.askopenfilename(filetypes=fTyp, initialdir=iDir)
    return filename

#ファイルを複数選択:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def fileselect():
    root = tkinter.Tk()
    root.withdraw()

    fTyp = [('', '*')]
    iDir = 'C:/Desktop'

    filenames = tkFileDialog.askopenfilenames(filetypes=fTyp, initialdir=iDir)

    return filenames

#ファイルをフォルダで一括選択:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def fileselect():
    root = tkinter.Tk()  
    root.withdraw()  

    iDir = 'C:/Desktop'  

    dirname = tkFileDialog.askdirectory(initialdir=iDir)

    filenames = glob.glob(dirname +"/*")
    return filenames

だいぶスッキリとしました。しかし、

def 〇 〇 〇 〇 ():

で始まる関数名がすべて同じになってしまっていますので、これを変更しましょう。

ファイルを一つ選択する場合は、single_fileselect、複数選択するときはmulti_fileselect、フォルダで選択する場合はfolder_fileselectと変更しましょう。



# -*- coding: utf-8 -*-

import tkinter  
from tkinter import filedialog as tkFileDialog
import glob

#ファイルを一つ選択::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def single_fileselect():
    root = tkinter.Tk()
    root.withdraw()

    fTyp = [('', '*')]

    iDir = 'C:/Desktop'

    filename = tkFileDialog.askopenfilename(filetypes=fTyp, initialdir=iDir)
    return filename

#ファイルを複数選択:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def multi_fileselect():
    root = tkinter.Tk()
    root.withdraw()

    fTyp = [('', '*')]
    iDir = 'C:/Desktop'

    filenames = tkFileDialog.askopenfilenames(filetypes=fTyp, initialdir=iDir)

    return filenames

#ファイルをフォルダで一括選択:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def folder_fileselect():
    root = tkinter.Tk()  
    root.withdraw()  

    iDir = 'C:/Desktop'  

    dirname = tkFileDialog.askdirectory(initialdir=iDir)

    filenames = glob.glob(dirname +"/*")
    return filenames

これで完成です。

それでは、実際に使用してみたいと思います。

前回の「マウスを使って画像を切り替える」のコードを使って説明します。

前回のコードは以下になります。

# coding: UTF-8
import cv2
import tkinter
from tkinter import filedialog as tkFileDialog
 
def onMouse(event, x, y, flag, params):
    i, filenames= params
 
    if event == cv2.EVENT_MOUSEWHEEL:  # ホイールを回したときの動作
 
        if flag > 0:       #もしflagが正の数だったら画像番号iを1引く
            i -= 1         # -= とはiの数から1を引いた数をiに代入すること
        elif flag < 0:     #もしflagが負の数だったら画像番号iを1足す
            i += 1         # += とはiの数から1を引いた数をiに代入すること
 
        if i <= 0:         #もし、iが0より小さかったら
            i = 0         #iは0
        elif i >= len(filenames)-1:  #もし、iが要素数以上だったら
            i = len(filenames)-1    #要素数より1少ない数に
 
        imageshow(filenames, i)
 
def fileselect():
    root = tkinter.Tk()
    root.withdraw()
    fTyp = [('', '*')]
    iDir = 'C:/Desktop'
    filenames = tkFileDialog.askopenfilenames(filetypes=fTyp, initialdir=iDir)
    return filenames  # 選択ファイルの絶対パスを返します。
 
def imageshow(filenames,i):
    img = cv2.imread(filenames[i])
    wname = "img"
 
    cv2.imshow(wname, img)
    print(str(i) + "   image  " + filenames[i])
 
    cv2.setMouseCallback(wname, onMouse, [i, filenames])
    cv2.waitKey()
    cv2.destroyAllWindows()
 
filenames = fileselect()
i=0
imageshow(filenames,i)

まず、23行目から、29行目のコードは新しく作成したfileselect.pyに記載してありますので削除します。

あと、3行目と4行目のimport文はファイルを選択するダイアログを開く際に必要なライブラリでした。このライブラリはfileselect.pyの中で呼び出しをしますので必要なくなりましたので削除します。

その代わり、fileselect.pyを使用しますので

import fileselect

の一文を追加します。これで、 fileselect.py を使用することができます。

最後に、42行目

filenames = fileselect()

の文をfileselect.pyの中の使用したい関数名を指定すればいいので例えば一つのファイルを選択したいのであれば

filenames = fileselect.single_fileselect()

複数のファイルであれば

filenames = fileselect.multi_fileselect()

フォルダごと選択であれば

filenames = fileselect.folder_fileselect()

とすることで使用することができます。

例えば、複数ファイルでやってみるとコードは以下となります。


# coding: UTF-8
import cv2
import fileselect

def onMouse(event, x, y, flag, params):
    i, filenames = params

    if event == cv2.EVENT_MOUSEWHEEL:  # ホイールを回したときの動作

        if flag > 0:  # もしflagが正の数だったら画像番号iを1引く
            i -= 1  # -= とはiの数から1を引いた数をiに代入すること
        elif flag < 0:  # もしflagが負の数だったら画像番号iを1足す
            i += 1  # += とはiの数から1を引いた数をiに代入すること

        if i <= 0:  # もし、iが0より小さかったら
            i = 0  # iは0
        elif i >= len(filenames) - 1:  # もし、iが要素数以上だったら
            i = len(filenames) - 1  # 要素数より1少ない数に

        imageshow(filenames, i)

def imageshow(filenames, i):
    img = cv2.imread(filenames[i])
    wname = "img"

    cv2.imshow(wname, img)
    print(str(i) + "   image  " + filenames[i])

    cv2.setMouseCallback(wname, onMouse, [i, filenames])
    cv2.waitKey()
    cv2.destroyAllWindows()

filenames = fileselect.multi_fileselect()
i = 0
imageshow(filenames, i)

少し、コードがすっきりとしましたね。

マウスイベントも同様に別ファイルとして作ってしまえば、かなりすっきりとしますので試してみてください。

それでは。お疲れ様でした。


環境

  • windows10
  • python3.6.1
  • Anaconda custom(64-bit)
  • PyCharm2020.2(Communication Edition)

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