下記のコードでtiff形式からnifti形式に変換し、napariでnifti画像を表示させると、90度回転した画像が表示されます。
コードを追っても、そんな命令をしていないのですが。。。
見落としてますか?
90度回転はなしの状態にしたいです。
変換前のtiff画像は何枚も画像を重ねています。(gif画像のようなもの)
python
1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3""" 4tif_to_nii 5command line executable to convert a directory of tif images 6(from one image) to a nifti image stacked along a user-specified axis 7call as: python tif_to_nii.py /path/to/tif/ /path/to/nifti 8(append optional arguments to the call as desired) 9Author: Jacob Reinhold (jacob.reinhold@jhu.edu) 10""" 11 12import argparse 13from glob import glob 14import os 15from pathlib import Path 16import sys 17 18from PIL import Image 19import nibabel as nib 20import numpy as np 21 22 23def arg_parser(): 24 parser = argparse.ArgumentParser(description='merge 2d tif images into a 3d image') 25 parser.add_argument('img_dir', type=str, 26 help='path to tiff image directory') 27 parser.add_argument('out_dir', type=str, 28 help='path to output the corresponding tif image slices') 29 parser.add_argument('-a', '--axis', type=int, default=2, 30 help='axis on which to stack the 2d images') 31 return parser 32 33 34def split_filename(filepath): 35 path = os.path.dirname(filepath) 36 filename = os.path.basename(filepath) 37 base, ext = os.path.splitext(filename) 38 if ext == '.gz': 39 base, ext2 = os.path.splitext(base) 40 ext = ext2 + ext 41 return path, base, ext 42 43 44def main(): 45 try: 46 args = arg_parser().parse_args() 47 img_dir = Path(args.img_dir) 48 fns = sorted([str(fn) for fn in img_dir.glob('*.tif*')]) 49 if not fns: 50 raise ValueError(f'img_dir ({args.img_dir}) does not contain any .tif or .tiff images.') 51 imgs = [] 52 for fn in fns: 53 _, base, ext = split_filename(fn) 54 img = np.asarray(Image.open(fn)).astype(np.float32).squeeze() 55 ''' 56 if img.ndim != 2: 57 raise Exception(f'Only 2D data supported. File {base}{ext} has dimension {img.ndim}.') 58 ''' 59 imgs.append(img) 60 img = np.stack(imgs, axis=args.axis) 61 nib.Nifti1Image(img,None).to_filename(os.path.join(args.out_dir, f'{base}.nii.gz')) 62 return 0 63 except Exception as e: 64 print(e) 65 return 1 66 67 68if __name__ == "__main__": 69 sys.exit(main()) 70
変換前のtiffファイルが回転していて、それを無視してデータのみ読み込んで変換してファイル保存してるため、変換時に回転してしまったように見える、ということはありませんでしょうか?
tiffファイルはOrientationタグの設定で、ファイル中のデータの本当の並び順とビューアで見たときの見た目の向きを変えることができるため、tiffファイルの中の本当のデータの並び順はビューアで見たときの方向の通りとは限りません
参考
http://hackmylife.net/archives/7400448.html
https://gigazine.net/news/20191208-python-exif-orientation/
どうすれば、tiffファイルを回転させないで保存できますか?
> どうすれば、tiffファイルを回転させないで保存
そのtiffファイルのOrientationタグがどうなってるのか(tiffファイルが回転してるのか)を、確認したのでしょうか?
まだでしたら、下記を行なって、確認してみてください
https://dabiyone.com/misc/mia023.html
の「PilExifTag00.py」で、
rawdic = pilimage._getexif()
↓ 修正
rawdic = pilimage.getexif()
だけ変えて(もちろん画像ファイル名は実際に合わせて)実行したら、tiffファイルのタグの一覧が表示されます
その中に「Orientation」があるか探して、あれば値を確認します
上記を確認した結果が、もしOrientationタグがあって、値が「1」以外ならですが、
https://teratail.com/questions/366680
を見たら、そのtiffファイルはjpgファイルやpngファイルから変換したもののようなので、変換前のjpgファイルやpngファイルも同様にしてOrientationタグがあるか探して、あれば値を確認してみてください
実行すると、
<class 'PIL.TiffImagePlugin.TiffImageFile'>
<class 'PIL.Image.Exif'>
と出てきて、orientaionタグは見当たりません。
それだけですか?
当方で適当なtiffファイルで実行したら、その下にかなりの行数が表示されるのですけど
最初の3行だけ載せます
(こんな感じのが30行くらい表示されます)
256 : ImageWidth : 7087 : <class 'int'>
257 : ImageLength : 9449 : <class 'int'>
258 : BitsPerSample : (8, 8, 8, 8) : <class 'tuple'>
もしOrientationタグがあれば、下記のように「274」から始まる行です
274 : Orientation : 1 : <class 'int'>
全然でないです。。。
最後の部分をこのように書き換えたのですが、これが間違いですかね?
file1 = "train_tiff/Input/1~5.tiff"
file2 = "train_tiff/Input/1~5.tiff"
edic = get_exif_dic(file2)
「train_tiff/Input」に「1~5.tiff」という名前のファイルがあるのですか?
変換前のjpgファイルかpngファイルでも、同様に確認してみてください
そうです。
確認してみます。
jpgでも同じ結果しか出力されません。
https://github.com/ianare/exif-samples/blob/master/jpg/Canon_40D.jpg
https://github.com/ianare/exif-samples/blob/master/tiff/Arbitro.tiff
をダウンロードして、同様に試してみてください
当方ではOrientationタグが表示されることを確認済みです
ダウンロードした画像ではたくさんの行が出力されました。
何が違うのでしょう?
質問者さんが扱ってる画像ファイルには、Exifデータが付いてないのでしょう
その場合は、Orientationタグが付いていたから回転して見えていた、という説は無くなりますね
そうなると、怪しいのはtiffからniftiに変換してるところかな??
下記を見ると、「affine」次第で向きが変えられるみたいなので
http://meg.aalip.jp/python/BrainVISA_nibabel.html
https://nshalnote.com/?p=352
当方で変換し確認したら、変換後に普通の画像として見たら方向は合ってましたが、
http://meg.aalip.jp/python/BrainVISA_nibabel.html
https://nshalnote.com/?p=352
に記載の表示例のように左下を座標原点にして表示したら、上下が逆になりました
どちらの場合でも、90°回転ではありませんでした
以下、確認した手順を書きます
nifti画像は扱ったこと無いので、手順が間違ってるかも
http://icb-lab.naist.jp/members/yoshi/ouec_lecture/image_recognition/image_files/len_std.jpg
をダウンロードし、Exifデータが付いて無いことを確認
Pythonで下記を実行して、jpgをグレースケールのtiffに変換
from PIL import Image
img = Image.open("len_std.jpg").convert("L")
img.save("len_std.tiff")
「tin」というディレクトリを作り、そこにtiffファイルを置き、tiffファイルを複数にコピー
「nout」というディレクトリを作る (中は空)
質問に掲載のコードを実行して、tiffからniftiに変換
python tif_to_nii.py tin nout
Pythonで下記を実行して、niftiを表示
import matplotlib.pyplot as plt
import nibabel as nib
import napari
imgn = nib.load("./nout/len_std.nii.gz")
imgn0 = imgn.get_fdata()[:, :, 0]
# 普通の画像として表示:元画像と同じ向き
plt.imshow(imgn0, cmap='gray')
plt.show()
# 左下を座標原点にして表示:元画像と上下が逆
plt.imshow(imgn0, cmap='gray', origin='lower')
plt.show()
# napariで表示:元画像と同じ向き
viewer = napari.view_image(imgn0)
当方でnapariで表示させたら、元画像と同じ向きでした
上記の手順に、その手順も追記しました
> napariでnifti画像を表示させると、90度回転した画像が表示
とならないのは、当方の確認手順が間違ってるのでしょうか?
ありがとうございます。
試してみます。
試してみたら、同じ向きで表示されました。
機械学習でこの画像を読み込みたいんですが、表示させるときだけ同じ向きになっている感じですかね?
普通にnapariで表示させると、90度回転した画像が表示されるので。
> 試してみたら、同じ向きで表示されました。
は、私の「2021/11/02 16:25」のコメントの手順で実行したら、tiffとniftiの向きは(napariで表示させても)一致していた、という意味ですか?
もしそうなら、それと、
> napariで表示させると、90度回転した画像が表示される
は、何がどのように違うのでしょうか?
私がコメントで提示したのと同じ手順で変換したら、napariで表示させても向きは変わらないと思うのですが、当方の確認の手順と、質問者さんがやってる手順は、どこかに違いがあるのでしょうか?
> 普通にnapariで表示させると
みたいなふわっとした表現だと、現象の再現ができません
当方でも現象が再現できるように、手順を具体的に提示してください
どのようにしたら、画像が90°回転するのでしょうか?
jbpb0さんのコードを実行したら、正しく表示されました。(回転なし)viewer=napari.view_image(imgn0)までの手順で。
今、悩んでいるのは、
$python tif_to_nii.py tin nout
で変換したあとの画像を
$napari image.nii
で表示させると、90度回転していました。
つまり、このコードを使わないで表示
import matplotlib.pyplot as plt
import nibabel as nib
import napari
imgn = nib.load("./nout/len_std.nii.gz")
imgn0 = imgn.get_fdata()[:, :, 0]
# 普通の画像として表示:元画像と同じ向き
plt.imshow(imgn0, cmap='gray')
plt.show()
# 左下を座標原点にして表示:元画像と上下が逆
plt.imshow(imgn0, cmap='gray', origin='lower')
plt.show()
# napariで表示:元画像と同じ向き
viewer = napari.view_image(imgn0
> $napari image.nii
で表示させると、90度回転
その状態で表示されてるのと、元画像を良く見比べてみてください
単純に90°回転してるだけですか?
元画像の左右を逆にした上で、90°左(時計回りの逆)に回転してませんか?
当方で確認したら、そうなってました
質問者さんが90°回転してると思ってる状態で、napariのメニューの「View」→「Axes」→「Visible」をON(チェック有り)にしてみてください
画像の左上に二つの矢印が現れて、「矢印1」が下向きで、「矢印2」が右向きになってると思います
ここからは推測ですが、「矢印1」が普通の画像の横方向の向き、「矢印2」が縦方向の向きに相当するもののような気がします
もしそうなら、下記の対応関係になります
・普通の画像の横方向の画素の並びは左→右:napariのこの状態では「矢印1」の上→下
・普通の画像の縦方向の画素の並びは上→下:napariのこの状態では「矢印2」の左→右
つまり、画素の並びの縦横が、普通の画像とは逆に解釈されて表示されているのではないか、ということです
(あくまでも現象からの推測で、もし当たっているとしても、そうなる理由は分かりませんが)
回答1件
あなたの回答
tips
プレビュー