Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the all-in-one-seo-pack domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/functions.php on line 6114

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the easy-fancybox domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/functions.php on line 6114

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the urvanov-syntax-highlighter domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/functions.php on line 6114

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the breadcrumb-navxt domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/functions.php on line 6114

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the advanced-ads domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/functions.php on line 6114

Notice: 関数 _load_textdomain_just_in_time が誤って呼び出されました。lancr ドメインの翻訳の読み込みが早すぎました。これは通常、プラグインまたはテーマの一部のコードが早すぎるタイミングで実行されていることを示しています。翻訳は init アクション以降で読み込む必要があります。 詳しくは WordPress のデバッグをご覧ください。 (このメッセージはバージョン 6.7.0 で追加されました) in /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/functions.php on line 6114

Warning: Cannot modify header information - headers already sent by (output started at /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/functions.php:6114) in /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-content/plugins/all-in-one-seo-pack/app/Common/Meta/Robots.php on line 87

Warning: Cannot modify header information - headers already sent by (output started at /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/functions.php:6114) in /virtual/mcu03iphuk/public_html/radiology-technologist.info/wp-includes/feed-rss2.php on line 8
画像切り替え | 診療放射線技師がPythonをはじめました。 http://radiology-technologist.info 診療放射線技師のPython日記。解析等で使えるコードを作成、アップしていきたいと思っています。その他いろいろ Fri, 21 May 2021 06:26:33 +0000 ja hourly 1 https://wordpress.org/?v=6.7.1 https://i0.wp.com/radiology-technologist.info/wp-content/uploads/2018/09/cropped-logo5.png?fit=32%2C32 画像切り替え | 診療放射線技師がPythonをはじめました。 http://radiology-technologist.info 32 32 164362728 マウスを使って画像を切り替える http://radiology-technologist.info/post-306 Mon, 18 Nov 2019 11:45:38 +0000 http://mcu03iphuk.m5.valueserver.jp/wordpress/?p=306 今回は、複数選択した画像をマウスを使って切り替えて […]

The post マウスを使って画像を切り替える first appeared on 診療放射線技師がPythonをはじめました。.]]>
今回は、複数選択した画像をマウスを使って切り替えていく方法をやってみたいと思います。

ただ、今回切り替えていく画像はDICOM画像ではなくてピング形式や、ビットマップ等の一般的な画像ファイルとします。


マウスイベントとは

右クリック(左クリック)した時の動作や、マウス中央のマウスホイールをクルクルっとした時の動作をマウスイベントと言います。

今回は、そのマウスイベントを使って画像を切り替えていくことをやろうと思っているのですが、Image-Jなどの画像ビューアではマウスホイールで画像切り替えを行っていると思いますので、それを真似してコードを作成していきたいと思います。


広告
デル株式会社

手順

まずは、ざっくりと手順を。

  1. マウスイベントの関数を作る。
  2. 画像表示の関数を作る
  3. コードを繋げる
  4. マウスイベント呼び出しのコードを入れる

といった流れでやっていきます。


マウスイベントの関数とは?

マウスイベントは、関数を作って指定していきますので、まずは関数のおさらいです。関数は

def ○○(引数1 ,引数2):

で指定していきます。なお、関数内のコードは字を下げて記載していきます。(Tabキーで文字を下げていきますが、プログラム作成用のソフトを使う場合、大抵初めの一行目を下げれば、それ以降も自動で字下げをやってもらえます。)


それでは、本題のマウスイベントに入ります。関数名はどんな名前でも構わないのですが、マウス動作なのでonMouseとしてみましょう。

def onMouse(event,x,y,flag,param):


引数

def onMouse(event,x,y,flag,param):

マウスイベントには指定しなければならない引数がいくつかあります。ここで引数の説明をします。


def onMouse(event,x,y,flag,param):  eventとは

引数のeventとは、マウスの操作を指します。

クリックを押した時なのか、クリックを押しながら動かした時なのか、クリックを上げた時なのか、マウスホイールを動かした時なのか等さまざまな指定ができます。

  • cv2.EVENT_MOUSEMOVE    マウスの移動
  • cv2.EVENT_LBUTTONDOWN  左クリック
  • cv2.EVENT_RBUTTONDOWN   右クリック
  • cv2.EVENT_LBUTTONUP    左クリックを離した時
  • cv2.EVENT_RBUTTONUP    右クリックを離した時
  • cv2.EVENT_MOUSEWHEEL   マウスホイールを回した時

等、いろんなイベントがありますが今回は、マウスホイールの動作なので

cv2.EVENT_MOUSEWHEEL:を使います。

(なお、マウスイベントはOpenCVの動作になりますので、OpenCVをインポートするのを忘れないでくださいね。)

なので、プログラム的に

「もし、マウスホイールを回したら」という構文を作ります。なので

# coding: UTF-8

def onMouse(event, x, y, flag, params):
    if event == cv2.EVENT_MOUSEWHEEL:


def onMouse(event,x,y,flag,param):  x,yとは

イベントが起こった画像上の座標を指します。

今回は意味はありません。


def onMouse(event,x,y,flag,param):  flagとは

flagとは、イベントと同時に起こした動作です。

例えば、shiftキーを押しながらとか、ctrlキーを押しながらとか言ったことです。

今回のマウスホイールの場合は、数値が入ってきます。

マウスホイールを回した場合手前に回すか、奥に回すかによって正の数、もしくは負の数が返されます。値も、使っているマウスによってさまざまです。

ちなみに、今回はflagで受けた数値は0以上か、0以下で画像を送るか、戻すかの判断します。


def onMouse(event,x,y,flag,param):  paramとは

paramとは、event,x,y,flag以外で処理に使いたい値をひっくるめて指定できます。

今回は、画像表示した際のウインドウ名や、ファイルを格納した変数を渡すのに使います。使い方として関数の次の行に以下のように指定します。

i,filenames = params

といった感じです。 (i,filenames は以後のコードの中で使う変数なので今は気にしないでください。)

i,filenamesという変数はparamsの中に入っていますよという意味です。


マウスホイールの関数を作成

そいれでは、関数を書いていきたいと思います。

前回の記事で書きましたが、複数の画像をダイアログを使って選択した際、変数にその画像のパスが保存されます。そのパスを一個一個取り出して画像表示をしていかなくてはいけません。

1個目のパスを取り出して 画像を表示した次は、2個目のパスを取り出して表示、次は3個目のパスを取り出して表示と順番にやっていく。

i番目の画像パスを取り出したいときは

filenames[i]といった書き方になると記載しました。(filenamesはファイルパスを入れた変数名です。)

なので、マウスホイールを動かした時にiが変わる処理を書きます。

マウスホイールが動いた時には引数のflagの引数に正、もしくは負の数が入ってきますので

もし、正の数であったら画像を送る(画像番号がiだったらi+1の画像表示)負の数であったら画像を戻す( 画像番号がiだったらi-1の画像表示)

# coding: UTF-8

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に代入すること
                           # -=が気に入らなかったらi = i-1でもOK
        elif flag < 0:     #もしflagが負の数だったら画像番号iを1足す
            i += 1         # += とはiの数から1を引いた数をiに代入すること
                           # +=が気に入らなかったらi = i+1でもOK

13行目

if i < 0: #もし、iが0より小さかったら

となっていたら文字化けしていますので ”<” 部分を ”<” と直してください。


これで、画像番号を示す変数iを変える処理は完成です。簡単でしょ?

しかし、このままではiが負になったり、iが変数の要素(選択したファイル数)以上の数になった際には画像表示できませんとエラーになってしまいます。

今度は、その処理を書いていきます。

内容は、

もしiがマイナスになるようだったらiは0のまま。

もしiが要素数以上になるようだったらiはそのまま

といった処理を付け加えておきます。

# coding: UTF-8

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

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

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

        if i &lt; 0:         #もし、iが0より小さかったら
            i = 0         #iは0

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

ここでlen(filenames)が出てきましたが、lenとは要素の数を返す関数となるのでファイル選択した数となります。

len(filenames)-1 となっているのはプログラム上、数は0からカウントするからです。(人間は1から数えるので-1しないとずれてしまいます。)


画像表示の関数を作成

次に、今回は画像表示を何度も繰り返す動作になるので画像表示のコード自体を関数と作成してしまいましょう。

今回はDICOM画像ではなく、一般的な画像形式(png,bitmap,jpg)の画像を表示していきます。(DICOM画像だと、WW,WLの設定もコードに入れなければならない為、簡素化のために一般的画像形式としました。)

使うモジュールはマウスイベントでOpenCVを使っているので、同じOpenCVで開こうと思います。

画像を開く際はまず、画像を変数内に読み込みます。

img = cv2.imread(filenames[i])

そして、画像表示のウインドウ名を決めなければなりません。

今回は、window名なので変数名wnameとしてそこにimgと名付けます。

wname = “img”

最後に、画像表示のコードを付けます。コードは以下となり、引数は

cv2.imshow(ウインドウ名,画像のパス)

となるので

cv2.imshow(wname, img)

となります。

これで画像表示ができるかといえばできません。よく忘れてしまうのですが画像表示後をいつまで続けるのか?といった指定をしなければいけません。忘れてしまうと画像が一瞬開いてすぐに閉じてしまいます。見た目には画像が表示されたことに気が付かず、おかしいな?と思ってしまいます。私はこれに気が付かず苦労しました。

cv2.waitKey()

上記処理は、何かキーが押されるまで待ちます。

cv2.destroyAllWindows()

何か押されたらすべてのウインドウを閉じる処理となります。

def imageshow(filenames,i):
    img = cv2.imread(filenames&#91;i])
    wname = "img"

    cv2.imshow(wname, img)
    print(str(i) + "   image  " + filenames&#91;i])  #確認用。コンソールに変数の番号とイメージパスを表示

    cv2.setMouseCallback(wname, onMouse, &#91;i, filenames])
    cv2.waitKey()
    cv2.destroyAllWindows()


コードを繋げていきます。

マウスイベントと、画像表示、ダイアログを使ってファイルを選択の関数を一つのファイルに入れ、それらを繋げていきましょう。

順番はどうでもいいですが、まずマウスイベントのファイルを入れ、ファイルセレクト、その後に、画像表示の関数を入れていきましょう。

その際、OpenCV、tkinterのimportを忘れないでくださいね。

# 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 &lt; 0:     #もしflagが負の数だったら画像番号iを1足す
            i += 1         # += とはiの数から1を引いた数をiに代入すること

        if i &lt;= 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 = &#91;('', '*')]
    iDir = 'C:/Desktop'
    filenames = tkFileDialog.askopenfilenames(filetypes=fTyp, initialdir=iDir)
    return filenames  # 選択ファイルの絶対パスを返します。

def imageshow(filenames,i):
    img = cv2.imread(filenames&#91;i])
    wname = "img"

    cv2.imshow(wname, img)
    print(str(i) + "   image  " + filenames&#91;i])


    cv2.waitKey()
    cv2.destroyAllWindows()

上記の様になります。ただ、これだけではプログラムは動かないのでそれらを関連付けてあげましょう。

プログラムの流れは、

  1. 起動したらダイアログを使ってファイルを選択
  2. 画像表示
  3. マウスホイールを回したら画像が切り替わる

となります。

filenamesという変数に選択した画像ファイルのパスを入れたいので

初めは

filenames = fileselect()

とし、ダイアログを使ってファイルを選択する関数(fileselect)を呼び出し、returnで返されたリストをfilenamesの変数にいれます。

今度は、そのリストを画像表示(imageshow)の関数で画像表示しましょう。

imageshowの関数にリスト(filenames)を渡してそのリストの中から画像表示をさせます。その際、はじめに表示する画像はリストに入っている初めの画像にしたいので変数iを0に設定します。

i=0

imageshow(filenames,i)

これで、画像表示がでます。


「 マウスホイールを回した時の処理 」を呼び出す。

はじめに、マウスホイールの関数を書きましたがそれだけでは、マウスイベントは動きません。

動かすにはマウスイベントを呼び出すコードが必要となります。

cv2.setMouseCallback(window, onMouse, 引数)

マウスイベントを呼び出すにはcv2.setMouseCallbackという関数を使います。

引数

cv2.setMouseCallback(window, onMouse, 引数)   windowとは
windowとはどのウインドウでのマウスイベントなのかを指定します。

wnameです。

cv2.setMouseCallback(window, onMouse, 引数)   onMouseとは

onMouseはどの関数名を呼び出すかという事です。

cv2.setMouseCallback(window, onMouse, 引数)   引数とは

onMouse関数のparamsの渡す引数を指定します。複数ある場合は[]で指定します。

今回はiとfilenamesを渡しますので[i,filenames]となります。

マウスイベント呼び出しコードの挿入

マウスイベントは、画像が表示されてから閉じられるまでの間になるので上記コードの39行目になります。

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

のコードを挿入して終了となります。

広告
HP Directplus -HP公式オンラインストア-

完成コード

# 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 &lt; 0:     #もしflagが負の数だったら画像番号iを1足す
            i += 1         # += とはiの数から1を引いた数をiに代入すること

        if i &lt;= 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 = &#91;('', '*')]
    iDir = 'C:/Desktop'
    filenames = tkFileDialog.askopenfilenames(filetypes=fTyp, initialdir=iDir)
    return filenames  # 選択ファイルの絶対パスを返します。

def imageshow(filenames,i):
    img = cv2.imread(filenames&#91;i])
    wname = "img"

    cv2.imshow(wname, img)
    print(str(i) + "   image  " + filenames&#91;i])

    cv2.setMouseCallback(wname, onMouse, &#91;i, filenames])
    cv2.waitKey()
    cv2.destroyAllWindows()

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

いかがでしょうか?

きちんと動きましたか?


広告
BTOパソコン・パソコン関連商品がお買い得!パソコン工房のセール

環境

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


広告
上新電機 パソコン買取サービス
The post マウスを使って画像を切り替える first appeared on 診療放射線技師がPythonをはじめました。.]]>
306