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
jpeg | 診療放射線技師がPythonをはじめました。 http://radiology-technologist.info 診療放射線技師のPython日記。解析等で使えるコードを作成、アップしていきたいと思っています。その他いろいろ Wed, 22 Apr 2020 02:57:30 +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 jpeg | 診療放射線技師がPythonをはじめました。 http://radiology-technologist.info 32 32 164362728 DICOM画像からjpg、png等の汎用画像に変更 http://radiology-technologist.info/post-413 Wed, 22 Apr 2020 02:57:22 +0000 http://radiology-technologist.info/?p=413 前回、OpenCVを用いてマウスホイールを使って画 […]

The post DICOM画像からjpg、png等の汎用画像に変更 first appeared on 診療放射線技師がPythonをはじめました。.]]>
前回、OpenCVを用いてマウスホイールを使って画像を切り替えるといった記事を書きました。しかし、そのままではつまらないので、DICOM画像をjpeg,pngといった汎用画像として保存する方法を記載したいと思います。


手順

手順としては、

  1. DICOM画像を読み込み
  2. ピクセルデータを配列として読み込み
  3. ww、wlで最適な条件に合わせる
  4. その配列をww、wlの範囲に落とし込む
  5. 汎用画像として保存

の手順となります。

ただ、前回までの記事で1~4までの作業は完了しいるので残り5番の作業となります。(前回のコードは下のリンクから)

http://radiology-technologist.info/2020/04/17/post-501/

それでは、5番の作業をさらに細かく分けていきましょう。

  1. 何をきっかけに画像保存をするか?
  2. 保存先の指定は?
  3. ファイル名は?
  4. 画像形式は何にするか?
  5. コードを作成

それでは、それぞれ決めていきましょう。


何をきっかけに画像保存をする?

まずは、何をきっかけに画像保存をするか?

せっかく前回マウスイベントで作業をしたので今回もマウスイベントで画像保存する方法をやっていきましょう。

右クリックを押した時に、画像保存ができるようにします。(過去のマウスイベントの記事はこちら

http://radiology-technologist.info/2019/11/18/post-306/

右クリックを押した時の指定は

if event == cv2.EVENT_RBUTTONDOWN:

でできます。

前回のマウスホイールを回した時の関数の後に記載します。

インデントの位置は

if event == cv2.EVENT_MOUSEWHEEL:

と同じ位置にします。


保存先の指定は?

新しく作成する画像の保存先の指定はどのようにするか?

それはユーザーが指定できるように組みたいと思います。

右クリックを押した時に、ファイルダイアログが開いて画像の保存フォルダを指定できるようにします。

これも以前、記事で書いたフォルダ選択でやってみたいと思います。

http://radiology-technologist.info/2019/12/21/post-371/

以前の記事では、フォルダ内のファイル全部を選択する形となっていたので少しそこを修正、追加して使いたいと思います。前回のコードは以下となります。

# -*- 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

フォルダだけ選択できればいいので

#ファイルをフォルダで一括選択の下から2段目

filenames = glob.glob(dirname +”/*”)

を削除すればフォルダのパスのみ取得できますので

関数名 folder として作成してしまいましょう

# -*- 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

#フォルダを選択:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
def folder():
    root = tkinter.Tk()  
    root.withdraw()  

    iDir = 'C:/Desktop'  

    dirname = tkFileDialog.askdirectory(initialdir=iDir)

    return filenames

この関数を呼び出すことでフォルダの指定ができます。

フォルダパスはfolという変数名で受け取るようにします。

if event == cv2.EVENT_RBUTTONDOWN:

の後に

fol = fs.folder()

とすることでfolの変数内に指定したフォルダパスを入れることができます。


ファイル名は?

ファイル名ですが、DICOM画像と同じ名前で保存する方法としましょう。

ファイル選択したパスからファイル名だけを抽出する方法は以下の記事に記載してあります。

http://radiology-technologist.info/2020/01/28/post-417/

.rfind(“/”)

で最後から数えて “/” が何文字目にあるかを調べます。

そしてそのファイルパスから、その文字分だけ切り抜いてあげ、先ほど選択したフォルダの後ろにつけてあげればいいわけです。

変数couとして画像ファイル名の前にある”/”までの文字数を入れます。

cou = filenames[i].rfind(“/”)

(なお、[i]は後でfor文の中でこのコードを使うので入れています。)

その数字文ファイルパスから抜き出せばいいので

filenames[i][cou:]

これで、ファイル名の抜き出しが完了です。


画像形式は何にするか?

画像形式は、jpg,png,bmp,tiffどの形式にするか決まったら、保存する時、パスの最後に付けてあげればいいだけです。

なので

“.jpg” “.png” “.bmp” “.tiff”

これだけで、画像形式の指定が終わりです。


画像保存

次は、画像を保存していく工程になります。

cv2.imwrite(ファイルパス,データ)

のコードで行います。

まずは保存先のファイルパスを作成します。

ファイルパスは、画像保存のフォルダにファイル名、拡張子を付けて作成します。

保存フォルダはfolの変数名で取得しましたね。

次にファイル名は

cou = filenames[i].rfind(“/”)

filenames[i][cou:]

の2文で抜き出しができました。

画像形式はjpegとしますと”.jpg”となりますので

ファイルパスfnameは

fname = fol + filenames[i][cou:] + “.jpg”

となります。

画像データはdcm_copyとなります。

後はfor文の中に上のコードを入れてあげればいいので、マウスイベントの文も合わせると

if event == cv2.EVENT_RBUTTONDOWN:
	fol = fs.folder()

	for i in range(len(dcm_copy)):

		cou = filenames[i].rfind("/")
		fname = fol + filenames[i][cou:] + ".jpg"

		cv2.imwrite(fname,dcm_copy[i])

これでコードは完成しました。


ただ、ここで問題があります。

今作成しているコードはマウスイベントの関数内でありますので、関数外で宣言しているfilenamesおよび、画像表示に作成した配列dcm_copyは使用できません。なのでこれを使うにはglobalで宣言しておかなければなりません。なので、マウスイベントの関数を宣言した直下に宣言を追加します。前回のコードでgという変数を宣言したと思いますが、その後に追加します。

def onMouse(event, x, y, flag, params):
global g,dcm_copy,filenames

これで、関数外で宣言していたfilenamesおよび、dcm_copyが使えるようになりました。


広告
デル株式会社

完成したコード

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

def onMouse(event, x, y, flag, params):
    global g,dcm_copy,filenames
    g = params

    if event == cv2.EVENT_MOUSEWHEEL:
        if flag > 0:
            g -= 1
        elif flag < 0:
            g += 1

        if g <= 0:
            g = 0
        elif g >= len(filenames)-1:
            g = len(filenames)-1

    if event == cv2.EVENT_RBUTTONDOWN:
        fol = fs.folder()

        for i in range(len(dcm_copy)):

            cou = filenames[i].rfind("/")
            fname = fol + filenames[i][cou:] + ".jpg"

            cv2.imwrite(fname,dcm_copy[i])

def make_LUT(val):
    global lookup_tbl, dcm_copy
    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())

filenames = fs.multi_files()

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)

make_LUT(0)
g = 0

while 1:
    params = g
    cv2.setMouseCallback('dcm_image', onMouse, params)
    cv2.imshow('dcm_image', dcm_copy[g])

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

となります。いかがでしたか?

お疲れ様でした。


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

環境

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

広告
上新電機 パソコン買取サービス
The post DICOM画像からjpg、png等の汎用画像に変更 first appeared on 診療放射線技師がPythonをはじめました。.]]>
413