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
numpy | 診療放射線技師がPythonをはじめました。 http://radiology-technologist.info 診療放射線技師のPython日記。解析等で使えるコードを作成、アップしていきたいと思っています。その他いろいろ Sat, 05 Sep 2020 07:56:19 +0000 ja hourly 1 https://wordpress.org/?v=6.7 https://i0.wp.com/radiology-technologist.info/wp-content/uploads/2018/09/cropped-logo5.png?fit=32%2C32 numpy | 診療放射線技師がPythonをはじめました。 http://radiology-technologist.info 32 32 164362728 画像間演算、サブトラクションをやってみる。 http://radiology-technologist.info/post-841 Wed, 02 Sep 2020 21:21:33 +0000 http://radiology-technologist.info/?p=841 はじめに 今回は、業務中によく使用する画像間演算で […]

The post 画像間演算、サブトラクションをやってみる。 first appeared on 診療放射線技師がPythonをはじめました。.]]>
はじめに

今回は、業務中によく使用する画像間演算であるサブトラクションをやってみたいと思います。


広告
デル株式会社

コードの流れ

サブトラクションをやるには最低2枚の画像が必要となりますので、画像の読み込み工程を2つ作成します。その際、どちらの画像からどちらの画像を引き算するのか決めなくてはなりませんが、今回はコードを簡単にするため初めに取り込んだ画像から、2枚目に取り込んだ画像をひき算することにします。


続いて、計算結果を格納する配列を作成します。この配列は、取り込んだ画像と同じサイズの配列を作成します。


画像間演算、引き算のコードを書いていきます。


最後に、画像表示のコードを書いて完成となります。


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

コードを書いていく

画像のピクセルデータを取り込む

まずは、画像を読み込む工程からやっていきます。込みこむ工程は、画像のパスを変数に取り込んでから、それをクラスに渡して画像のピクセルデータを配列に取り込み形になります。

それではコードを書いていきたいと思います。

DICOM画像を使いますので、pydicomのインポートをします。

画像の読み込みは、毎回使用しているfileselectのモジュールを使用します。まだ、ご覧になっていない方はこちら。fileselectのファイルは、今回書いているコードと同じフォルダの中に入れておいてくださいね。

今回もフォルダで一括選択する方法で画像を読み込みたいと思います。

# -- coding utf-8 --
import pydicom
import fileselect as fs

filenames = fs.folder_fileselect()


まずは、fileselectのモジュールを用いてフォルダ内の画像パスをfilenamesの変数に取り込みます。

そして、その変数をClassに渡し画像のピクセルデータを配列に取り込みます。

以前の記事から、Classの部分のコードをコピーします。画像読み込みをクラスを使ってやってみたの記事はこちらの記事を参照ください。

クラスがよくわからない方はこちらを参照ください。

このクラスではnumpyを用いていますのでnumpyのインポートを忘れないようにしましょう。

# -- coding utf-8 --
import pydicom
import fileselect as fs
import numpy as np

class Pixarr:
    def __init__(self,filenames):
        dcm = pydicom.dcmread(filenames[0])
 
        self.row = dcm[0x0028,0x0010].value
        self.column = dcm[0x0028,0x0011].value
        self.ww = dcm[0x0028,0x1050].value
        self.wl = dcm[0x0028,0x1050].value
 
        self.pix_arr = np.zeros((len(filenames),self.row,self.column),
            dtype ='int16')
 
        if len(filenames) == 1:
            self.pix_arr = dcm.pixel_array
        else:
            for i in range(len(filenames)):
                dcm = pydicom.dcmread(filenames[i])
                img_no = dcm[0x0020,0x0013].value    
                self.pix_arr[img_no-1] = dcm.pixel_array

filenames = fs.folder_fileselect()
f0 = Pixarr(filenames)

filenames = fs.folder_fileselect()
f1 = Pixarr(filenames)

読み込んだ画像パスをClassに渡すのですが、ひかれる画像をf0、ひく画像をf1と名前を付けてクラスに渡します。(上記コード28行目)

これで、ひかれる画像のピクセルデータを取り込むことができました。

同様に、引く画像をf1として取り込みます。f0の時と同様にコードを書きます。(上記コード30~31行目)

これで、画像の読み込みは完了です。


画像間演算したデータを格納する配列を作成する

画像間演算のコードを書く前に、計算結果を格納する配列を作成します。

引く画像、引かれる画像と同一サイズの配列を作成します。f0,f1どちらでも構わないのですが同じ大きさの配列f2を作成します。その際に、0で初期化しておきます。

同一サイズの配列を作成するコードは

f2 = numpy.full_like(f0.pix_arr,0)

で作成できます。numpyはインポートする際npの名称でインポートしていますので、実際のコードは下記コード33行目の様にnp.full_likeの形になります。

# -- coding utf-8 --
import pydicom
import fileselect as fs
import numpy as np

class Pixarr:
    def __init__(self,filenames):
        dcm = pydicom.dcmread(filenames[0])
 
        self.row = dcm[0x0028,0x0010].value
        self.column = dcm[0x0028,0x0011].value
        self.ww = dcm[0x0028,0x1050].value
        self.wl = dcm[0x0028,0x1050].value
 
        self.pix_arr = np.zeros((len(filenames),self.row,self.column),
            dtype ='int16')
 
        if len(filenames) == 1:
            self.pix_arr = dcm.pixel_array
        else:
            for i in range(len(filenames)):
                dcm = pydicom.dcmread(filenames[i])
                img_no = dcm[0x0020,0x0013].value    
                self.pix_arr[img_no-1] = dcm.pixel_array

filenames = fs.folder_fileselect()
f0 = Pixarr(filenames)

filenames = fs.folder_fileselect()
f1 = Pixarr(filenames)

f2 = np.full_like(f0.pix_arr,0)


画像間演算、サブトラクションのコード

サブトラクションはピクセル同士の引き算ですので本来であれば

f2[i] = f0.pix_arr[i] – f1.pix_arr[i]

のコードをfou文で繰り返すと考えるかもしれませんが、実はpythonでの配列計算はとても簡単で

f2 = f0.pix_arr – f1.pix_arr

の一文だけで済んでしまいます。もちろん、引き算だけでなく足し算でも使えますし、掛け算、割り算でも使用可能です。

for文でピクセルごとに計算しているよりも全然高速です。

ここまでのコードは以下となります。

# -- coding utf-8 --
import pydicom
import fileselect as fs
import numpy as np

class Pixarr:
    def __init__(self,filenames):
        dcm = pydicom.dcmread(filenames[0])
 
        self.row = dcm[0x0028,0x0010].value
        self.column = dcm[0x0028,0x0011].value
        self.ww = dcm[0x0028,0x1050].value
        self.wl = dcm[0x0028,0x1050].value
 
        self.pix_arr = np.zeros((len(filenames),self.row,self.column),
            dtype ='int16')
 
        if len(filenames) == 1:
            self.pix_arr = dcm.pixel_array
        else:
            for i in range(len(filenames)):
                dcm = pydicom.dcmread(filenames[i])
                img_no = dcm[0x0020,0x0013].value    
                self.pix_arr[img_no-1] = dcm.pixel_array

filenames = fs.folder_fileselect()
f0 = Pixarr(filenames)

filenames = fs.folder_fileselect()
f1 = Pixarr(filenames)

f2 = np.full_like(f0.pix_arr,0)

f2 = f0.pix_arr - f1.pix_arr


画像表示のコード

画像表示はmatplotlibを使用したいと思いますので、まずはmatplotlibをインポートします。

# -- coding utf-8 --
import pydicom
import fileselect as fs
import numpy as np
import matplotlib.pyplot as plt

class Pixarr:
    def __init__(self,filenames):
        dcm = pydicom.dcmread(filenames[0])
 
        self.row = dcm[0x0028,0x0010].value
        self.column = dcm[0x0028,0x0011].value
        self.ww = dcm[0x0028,0x1050].value
        self.wl = dcm[0x0028,0x1050].value
 
        self.pix_arr = np.zeros((len(filenames),self.row,self.column),
            dtype ='int16')
 
        if len(filenames) == 1:
            self.pix_arr = dcm.pixel_array
        else:
            for i in range(len(filenames)):
                dcm = pydicom.dcmread(filenames[i])
                img_no = dcm[0x0020,0x0013].value    
                self.pix_arr[img_no-1] = dcm.pixel_array

filenames = fs.folder_fileselect()
f0 = Pixarr(filenames)

filenames = fs.folder_fileselect()
f1 = Pixarr(filenames)

f2 = np.full_like(f0.pix_arr,0)

f2 = f0.pix_arr - f1.pix_arr

画像表示は引かれる画像、引く画像、計算後の画像の3画像表示したいと思います。

まずは、画像を表示設定からです。matplotlibで画像や、グラフ等を表示する際にまずはfigの設定をし、その後にaxの設定をします。ここが、よくわからないところかもしれませんが、考え方としては何もないところで絵を描こうとするときにまずは、画板や机を準備すると思います。それがfigにあたります。その後、その上に絵を描く紙を準備すると思います。それがaxにあたると考えやすいと思います。

figの設定は

fig = plt.figure()

チュートリアルはこちら

axの設定は

ax = fig.add_subplot()

で設定していきます。チュートリアルはこちら

figの大きさの設定をします。引数の中にfigsize =(横、縦)で設定をします。

fig = plt.figure(figsize=(15, 5))

どこに画像を表示するかはaxの括弧の中に引数として指定します。

ax0 = fig.add_subplot(1,3,1) #一番左に表示
ax1 = fig.add_subplot(1,3,2) #真ん中に表示
ax2 = fig.add_subplot(1,3,3) #一番右に表示

括弧内の初めの引数は縦方向の画像数を、2個目の引数は横方向の画像数、3個目の引数を何番目に画像を表示するかという設定になります。


続いて、axにどの画像を表示するかの設定に入ります。

引かれる画像をax0に、引く画像をax1に、演算後の画像をax2として設定していきます。

ax0.imshow(f0.pix_arr[sl],cmap= 'bone')
ax1.imshow(f1.pix_arr[sl],cmap= 'bone')
ax2.imshow(f2[sl],cmap= 'bone')

これで、画像表示の設定は完了です。

# -- coding utf-8 --
import fileselect as fs
import pydicom
import numpy as np
import matplotlib.pyplot as plt

class Pixarr:
    def __init__(self,filenames):
        dcm = pydicom.dcmread(filenames[0])

        self.row = dcm[0x0028,0x0010].value
        self.column = dcm[0x0028,0x0011].value
        self.ww = dcm[0x0028,0x1050].value
        self.wl = dcm[0x0028,0x1050].value

        self.pix_arr = np.zeros((len(filenames),self.row,self.column),
            dtype ='int16')

        if len(filenames) == 1:
            self.pix_arr = dcm.pixel_array
        else:
            for i in range(len(filenames)):
                dcm = pydicom.dcmread(filenames[i])
                img_no = dcm[0x0020,0x0013].value
                self.pix_arr[img_no-1] = dcm.pixel_array

filenames = fs.folder_fileselect()
f0 = Pixarr(filenames)

filenames = fs.folder_fileselect()
f1 = Pixarr(filenames)


f2 = np.full_like(f0.pix_arr,0)

f2 = f0.pix_arr - f1.pix_arr

fig = plt.figure(figsize=(15, 5))
plt.subplots_adjust(left=0, right=1, bottom=0, top=1, wspace=0.05, hspace=0.05)
ax0 = fig.add_subplot(1,3,1)
ax1 = fig.add_subplot(1,3,2)
ax2 = fig.add_subplot(1,3,3)

ax0.imshow(f0.pix_arr[sl],cmap= 'bone')
ax1.imshow(f1.pix_arr[sl],cmap= 'bone')
ax2.imshow(f2[sl],cmap= 'bone')


axに画像の設定をした際に [sl] とありますが、これは、何枚目の画像を表示するかの変数になります。マウスホイールを回すことで画像を切り替えるための変数です。(上記コードの38行目 sl = 0 とコードを追加してください。)

その機能を実装していきます。

これは、マウスイベントと言って右クリックや、左クリック、マウスホイールを回す、または押す等のイベントで何をするか決められます。

マウスホイールのイベントは

fig.canvas.mpl_connect('scroll_event', wheel_scroll)

動作設定はdefで関数を作成して決めます。今回はwheel_scrollという名前で設定しますが、次回matplotlibのマウスイベントで詳しく説明したいと思いますので今回はコードの提示だけとします。

# -- coding utf-8 --
import fileselect as fs
import pydicom
import numpy as np
import matplotlib.pyplot as plt

class Pixarr:
    def __init__(self,filenames):
        dcm = pydicom.dcmread(filenames[0])

        self.row = dcm[0x0028,0x0010].value
        self.column = dcm[0x0028,0x0011].value
        self.ww = dcm[0x0028,0x1050].value
        self.wl = dcm[0x0028,0x1050].value

        self.pix_arr = np.zeros((len(filenames),self.row,self.column),
            dtype ='int16')

        if len(filenames) == 1:
            self.pix_arr = dcm.pixel_array
        else:
            for i in range(len(filenames)):
                dcm = pydicom.dcmread(filenames[i])
                img_no = dcm[0x0020,0x0013].value
                self.pix_arr[img_no-1] = dcm.pixel_array

def wheel_scroll(event):
    global sl

    if event.button == 'down':
        sl += 1
        if sl > len(filenames)-1:
            sl =0

    if event.button == 'up':
        sl -= 1
        if sl < 0:
            sl = len(filenames)-1

    ax0.imshow(f0.pix_arr[sl], cmap='bone')
    ax1.imshow(f1.pix_arr[sl], cmap='bone')
    ax2.imshow(f2[sl], cmap='bone')

    fig.canvas.draw()

filenames = fs.folder_fileselect()
f0 = Pixarr(filenames)

filenames = fs.folder_fileselect()
f1 = Pixarr(filenames)

f2 = np.full_like(f0.pix_arr,0)

f2 = f0.pix_arr - f1.pix_arr

sl =0

fig = plt.figure(figsize=(15, 5))
plt.subplots_adjust(left=0, right=1, bottom=0, top=1, wspace=0.05, hspace=0.05)
ax0 = fig.add_subplot(1,3,1)
ax1 = fig.add_subplot(1,3,2)
ax2 = fig.add_subplot(1,3,3)

ax0.imshow(f0.pix_arr[sl],cmap= 'bone')
ax1.imshow(f1.pix_arr[sl],cmap= 'bone')
ax2.imshow(f2[sl],cmap= 'bone')

fig.canvas.mpl_connect('scroll_event', wheel_scroll)

plt.show()

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

最後に

いかがでしたか?お持ちのDICOM画像でサブトラクションできましたでしょうか?

上記コードで実行した結果です。マンモのMRI Dynamic画像、一番左が単純、真ん中が動脈相、一番左がサブトラクション画像となります。

正常乳腺は引き算され、腫瘍は濃染されているのが確認できると思います。

皆さんも試してみてください。

お疲れ様でした。

広告
上新電機 パソコン買取サービス
The post 画像間演算、サブトラクションをやってみる。 first appeared on 診療放射線技師がPythonをはじめました。.]]>
841
画像のヒストグラムを求めてみる。 http://radiology-technologist.info/post-797 Thu, 06 Aug 2020 21:01:16 +0000 http://radiology-technologist.info/?p=797 はじめに 今回は、画像のヒストグラムを求めてみたい […]

The post 画像のヒストグラムを求めてみる。 first appeared on 診療放射線技師がPythonをはじめました。.]]>
はじめに

今回は、画像のヒストグラムを求めてみたいと思います。

ヒストグラムを使用する場面としては、グラフで視覚的に信号値の分布を見たい時と、信号値の分布を数値として知りたい時があると思います。

そこで、今回はグラフとして求める方法と、数値として得る方法2つを紹介したいと思います。

求める手段としては以下の2つをやっていきます。

  • matplotlibでグラフ表示
  • numpyで求める

それでは、下の左側の画像を用いてそれぞれ紹介していきたいと思います。

ちなみに、右側は左側の画像のヒストグラムをimage-Jで表示したものです。


広告
デル株式会社

matplotlibでグラフ表示

まずはmatplotlibを用いて表示する方法を紹介します。

使用するライブラリーはmatplotlibのpyplotとなります。

それでは、コードを表示したいと思います。

# -- coding utf-8 --

import pydicom
import matplotlib.pyplot as plt
import numpy as np
import fileselect as fs

filename = fs.single_fileselect()
dcm = pydicom.dcmread(filename)

plt.hist(dcm.pixel_array)
plt.show()

ライブラリーのfileselectのコードはこちらを参照ください

上記コードで、ヒストグラムを求めるコードは12行目のplt.hist()となります。

カッコ内に第1引数としてピクセルデータの配列を指定します。

何か変だと思いませんか?ところどころ途切れているように見えます。階級であるbinの設定をしてみたいと思います。image-Jのヒストグラムと同一の設定にしてみましょう。image-Jではbinが256で設定されていますので上記コード12行目を以下に変更します。

# -- coding utf-8 --

import pydicom
import matplotlib.pyplot as plt
import numpy as np
import fileselect as fs

filename = fs.single_fileselect()
dcm = pydicom.dcmread(filename)

plt.hist(dcm.pixel_array,bins = 256)
plt.show()

いかがでしょうか?同様の結果となりましたね。

その他、グラフの色を変えたり、グラフのタイプを変えてみたりと様々な設定はカッコ内に記載していきます。詳しくは以下のチュートリアルを参照してください。

matplotlib ヒストグラムのチュートリアルはこちら

追伸

ヒストグラムを求める際、多次元配列の場合に行を1つのデータと認識してしまい思い通りのヒストグラムが得られない場合があります。その場合は、1次元配列に変換して求めると思い通りのヒストグラムを求めることができる場合があります。


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

numpyで求める

早速、コードから入ってみたいと思います。

# -- coding utf-8 --

import pydicom
import numpy as np
import fileselect as fs

filename = fs.single_fileselect()
dcm = pydicom.dcmread(filename)

hist_np = np.histogram(dcm.pixel_array.ravel())

print(hist_np)

上記コードでヒストグラムを求めるコードは11行目のmp.histogram()となります。matplotlibの時と同様にカッコ内に引数にピクセルデータの配列を指定します。

しかし、注意していただきたいところがあります。

numpyでヒストグラムを求める場合、配列は1次元配列でなければならないということです。なので、11行目で多次元配列を1次元配列にするravel()を用いてdcm.pixel_arrayを1次元配列に変更しています。

それでは、コードを実行してみましょう。結果は以下となりました。

結果は

[36106,22314,4192,1611,780,300,133,66,22,4]

[0,110.7,237.4,356.1,474.8,593.5,712.2,830.9,949.6,1060.3,1187]

という2つの配列が返ってくる結果となりました。1つ目の配列の要素数は10個、2つ目の配列の要素は11個となっています。

それぞれの配列は何を示しているのでしょうか?それは、1つ目は度数を示しており、2つ目の配列は階級の幅であるbinの幅を示しています。

なので、2つ目の配列は0~118.7、118.8~237.4と言うようにその範囲を示しています。よって10個の範囲があることが分かります。

これを、先ほどと同じように階級binの設定をして再度表示させてみましょう。

# -- coding utf-8 --

import pydicom
import numpy as np
import fileselect as fs

filename = fs.single_fileselect()
dcm = pydicom.dcmread(filename)

hist_np = np.histogram(dcm.pixel_array.ravel(),bins=256)

print(hist_np)

matoplotlibの時と同様にヒストグラムを求めるコード(11行目)の引数にbins=256と足してあげます。結果はどうだったでしょうか?

先ほどよりも、要素数が増えているのが分かります。はじめにimage-Jで求めたヒストグラムをリストとして出力したものが下の図のようになります。

いかがでしょうか?階級の幅、度数共に同様の結果となっています。

numpyにおいても様々な引数が用意されています。こちらのチュートリアルを参照してください。


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

最後に

いかがでしたか?今回はヒストグラムを求めるをやってみました。ヒストグラムは、画像にフィルタをかけたり、再構成をしたりした時に元画像との比較にする際に非常に役に立ちますね。是非ともマスターしておきたい技術ですね。

お疲れ様でした。


環境

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


広告
上新電機 パソコン買取サービス
The post 画像のヒストグラムを求めてみる。 first appeared on 診療放射線技師がPythonをはじめました。.]]>
797
MRI画像をスライダーを使ってウインドウ調整(OpenCV編)修正版(配列の型) http://radiology-technologist.info/post-491 http://radiology-technologist.info/post-491#respond Mon, 13 Apr 2020 21:28:03 +0000 http://radiology-technologist.info/?p=491 前回、前々回で「MRI画像をスライダーを使ってウイ […]

The post MRI画像をスライダーを使ってウインドウ調整(OpenCV編)修正版(配列の型) first appeared on 診療放射線技師がPythonをはじめました。.]]>
前回、前々回で「MRI画像をスライダーを使ってウインドウ調整」ということで記事を書かせていただきましたが、記載後いくつか修正したい部分が出てきましたのでそこを今回と次回で直していきたいと思います。今回は配列の型の指定を修正したいと思います。

前回のコード

import fileselect as fs   #ファイルパス取得のモジュールをインポート
import numpy np
import pydicom
import math
import copy

filenames = fs.multi_fileselect

dcm = pydicom.dcmread(filenames[0])
row,columns = dcm.pixel_array.shape[0],dcm.pixel_array.shape[1]
       #読み込んだ画像の横方向を変数row、縦方向を変数columnsとして取得します。

dcm_copy = np.zeros((len(filenames), row, columns),dtype = int)
       #dcm_copyという名前で0で初期化した配列を作成

for i in range(len(filenames)):
    dcm = pydicom.dcmread(filenames[i])
    dcm_arr = dcm.pixel_array
    dcm_copy[i] = dcm_arr.astype(np.int64) 
      #np.int64としてデータの型を指定しておきます。

dcm_main = copy.deepcopy(dcm_copy)
      #深いコピーで複製します。

cv2.namedWindow('dcm_image',cv2.WINDOW_NORMAL)
      #ウインドウ名を'dcm_image'とし、ウインドウサイズを変更できるように設定

maxvalue = dcm_copy.max().astype(np.int64)
lookup_tbl = np.zeros(maxvalue+1, dtype=np.int64)
      #作成要素数を最大値+1としておく。

cv2.createTrackbar("WL", "dcm_image", (maxvalue // 2), maxvalue, make_LUT)
cv2.createTrackbar("WW", "dcm_image", (maxvalue // 4), maxvalue, make_LUT)

while 1:
    wl = cv2.getTrackbarPos('WL', 'dcm_image')
    ww = cv2.getTrackbarPos('WW', 'dcm_image')

    ww_low = wl - ww // 2
    ww_high = wl + ww // 2
    lookup_tbl[0:ww_low] = 0
    lookup_tbl[ww_high:maxvalue] = 255
    for i in range(ww_low, ww_high, 1):
        lookup_tbl[i] = math.ceil((i - ww_low) * (256 / (ww_high - ww_low)))

    dcm_copy = lookup_tbl[dcm_main]

    dcm_copy =cv2.convertScaleAbs(dcm_copy, alpha=255/dcm_copy.max())
    cv2.imshow('dcm_image', dcm_copy[0])

    k = cv2.waitKey(1)
    if k == ord('q'):
        break

def make_LUT(val):
    pass #何もしない

修正点 配列の型の指定

CTや、MRI画像は16ビット階調だということです。その為、DICOMヘッダー[0028,0100]に登録されているBits Allocatedの画像階調度も16と登録(自施設の装置では16)されていますので、それに合わせていきたい友ます。

まずは上記コードの14行目

dcm_copy = np.zeros((len(filenames), row, columns),dtype = int)

の 「dtype = int」を 「dtype = ‘int16’」と変更し以下となります。

dcm_copy = np.zeros((len(filenames), row, columns),dtype = ‘int16’)

続いて20行目は14行目で指定しているので「.astype(np.int64)」を削除して

dcm_copy[i] = dcm_arr

とスッキリさせてしまいましょう。

29~30行目は

maxvalueはdcm_copyの最大値を入れる変数であるので、元の配列の型を指定する必要もないので「.astype(np.int64)」を削除。

30行目の

lookup_tbl = np.zeros(maxvalue+1, dtype=np.int64)

は、「dtype=np.int64」を「dtype=’int16’」とし

lookup_tbl = np.zeros(maxvalue+1, dtype=’int16′)

以上で型の修正は終わりです。

最後に・・・・

上記コードはopenCVのimportを忘れていました。以下のコードで追加しておきます。また、関数のmake_LUTを上に持ってきました。

修正後のコードは以下となります。

import fileselect as fs   #ファイルパス取得のモジュールをインポート
import numpy as np
import pydicom
import math
import copy
import cv2

def make_LUT(val):
    pass #何もしない

filenames = fs.multi_fileselect

dcm = pydicom.dcmread(filenames[0])
row,columns = dcm.pixel_array.shape[0],dcm.pixel_array.shape[1]

dcm_copy = np.zeros((len(filenames), row, columns),dtype = 'int16')

for i in range(len(filenames)):
    dcm = pydicom.dcmread(filenames[i])
    dcm_arr = dcm.pixel_array
    dcm_copy[i] = dcm_arr

dcm_main = copy.deepcopy(dcm_copy)

cv2.namedWindow('dcm_image',cv2.WINDOW_NORMAL)

maxvalue = dcm_copy.max()
lookup_tbl = np.zeros(maxvalue+1, dtype='int16')

cv2.createTrackbar("WL", "dcm_image", (maxvalue // 2), maxvalue, make_LUT)
cv2.createTrackbar("WW", "dcm_image", (maxvalue // 4), maxvalue, make_LUT)

while 1:
    wl = cv2.getTrackbarPos('WL', 'dcm_image')
    ww = cv2.getTrackbarPos('WW', 'dcm_image')

    ww_low = wl - ww // 2
    ww_high = wl + ww // 2
    lookup_tbl[0:ww_low] = 0
    lookup_tbl[ww_high:maxvalue] = 255
    for i in range(ww_low, ww_high, 1):
        lookup_tbl[i] = math.ceil((i - ww_low) * (256 / (ww_high - ww_low)))

    dcm_copy = lookup_tbl[dcm_main]

    dcm_copy =cv2.convertScaleAbs(dcm_copy, alpha=255/dcm_copy.max())
    cv2.imshow('dcm_image', dcm_copy[0])

    k = cv2.waitKey(1)
    if k == ord('q'):
        break


次回はマウスホイールの機能を入れていきたいと思います。


環境

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

広告
上新電機 パソコン買取サービス
The post MRI画像をスライダーを使ってウインドウ調整(OpenCV編)修正版(配列の型) first appeared on 診療放射線技師がPythonをはじめました。.]]>
http://radiology-technologist.info/post-491/feed 0 491