質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

6282閲覧

[python 画像処理]opencvとPILで出てくるデータが違う

yamatail

総合スコア77

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/10/23 08:02

編集2018/10/29 01:57

pythonの画像処理libのopencvとPILを試しに使っています。

しかし、表示される画像は同じなのに、
2つのデータが違う値で出てくるのです。

データを見るにPILの方が正しい。
上がopencvを、下がPILを使ったコードになります。

お詳しい方いらっしゃいましたら、ご教授頂ければと思います。

Python3

1import cv2 2import numpy as np 3from matplotlib import pyplot as plt 4 5img = cv2.imread('data.tif',-1) 6 7plt.imshow(img) 8 9#######データを確認############## 10img[0][0] 11#9.25e-43

python3

1import matplotlib.pyplot as plt 2import numpy as np 3from PIL import Image 4%matplotlib inline 5 6im = Image.open('data.tif') 7#im.show() 8imarr = np.array(im) 9 10plt.imshow(imarr) 11 12#######データを確認############## 13imarr[0][0] 14#660

###追記(1),(2),(3),(3.1),(4)あります

###追記(1)
Yhaya様のアドバイスを受けてopencvで読み込んでRGBに変換した後、描写することを試みました。
調べて見ると
CV_img_RGB = CV_im[:, :, ::-1].copy()
を挿入し、RGBにするとのことでしたが、エラーが出てしましました。
どこかおかしなところがありますでしょうか。(追記(2)で一応対処済み)

python3

1%matplotlib inline 2import cv2 3from PIL import Image 4import numpy as np 5from matplotlib import pyplot as plt 6 7CV_im =cv2.imread('data.tiff',-1) 8 9#BGRからRGBへ変換 10CV_img_RGB = CV_im[:, :, ::-1].copy() 11 12#変換 13CV2PIL_normalize=Image.fromarray(CV_im_RGB) 14 15#描画 16plt.imshow(CV2PIL_normalize)

error

1IndexError Traceback (most recent call last) 2<ipython-input-108-5afa93a697bc> in <module>() 3 8 4 9 #BGRからRGBへ変換 5---> 10 CV_img_RGB = CV_im[:, :, ::-1].copy() 6 11 7 12 #変換 8 9IndexError: too many indices for array

###追記(2)2018/10/26

------追記(1)より

CV_img_RGB = CV_im[:, :, ::-1].copy()
を挿入し、RGBにするとのことでしたが、エラーが出てしましました。

これは
CV_img_RGB = CV_im[:, ::-1].copy()
に変えることで、正常に動くようになりました。
[:, :, ::-1]この中の次元をCV_imと合わせる必要があったようです。

これによって表示された画像は、変換前から変化がありました。
ただ、imarrの(PILで読み込んだ正しい)データと比べると
CV_img_RGBの(openCVで読み込んでRGB変換した)データは違う。
(しかも見当違いに違う、e-43も違うとは...)

Python3

1print(imarr[0][0]) 2#660 3 4print(CV_im_RGB[0][0]) 5#6.32e-43

###追記(3)2018/10/26
取り扱うtifデータは1ピクセルにカウント数の入ったデータなのでグレースケール相当のものです。カウント数の範囲は、-2から177880です。
ですので、opencvもPILも配列に変換した後は高さ×幅の2次元になります。

RGBのように3つあるわけではないので、opencvやPILを使うべきデータではないということなのでしょうか。そもそも一般的なtifファイルではない(グレースケールの場合0~255)ので取扱いも違うのでしょうか。

最終的に作りたいプログラムは、カウント数の範囲(-2から177880)のデータを画像として表示させる為に(グレースケールの場合)256に分割して表示したいということです。
その為、minmumとmaximumを調整するプログラムを作りたいと思いました。

minmumは最小値で固定して、maximumを200000にしたり100000にしたりと変更させ、それを256で区別して、表示させる。という感じです。

###追記(3.1)2018/10/26
上の追記(3)でも書いたように元データのtifが1色(カウント数)相当だったため、
質問当初に書いたように読み込みを行った場合を考えた。
・PILの場合
imarr[0][0] = 660 あってる

・opencvの場合
img[0][0] = 9.25e-43 良くわからない

そこでopencvのデータに(img[0][0]のデータが660になる)
660(imarr[0][0])/9.25e-43(img[0][0])
を全配列に掛けてみた。
img * 660/9.25e-43

すると、PILのと同じ値に変換できた。
どうやら定数が掛けているよう。

###追記(4)2018/10/19
そもそもtifファイルがtifに準拠したフォーマットになっているか確認する。
tifをバイナリエディタで開き中にあるタグの情報を確認する。
その後フリーのtif解析ソフトを使って確認してみる。(自信なかったので...)

以下、その結果を貼ります。
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tiitoi

2018/10/26 03:41

読み込みしようとしている画像を質問欄を編集して貼ることはできますか。
yamatail

2018/10/26 05:38

申し訳ございません。都合上、画像は載せることが出来ません。。。画像の情報をできるだけ追記(3)に記載させていただきます。
tiitoi

2018/10/26 06:05 編集

回答にも書きましたが、tiff という拡張子がついているだけでなく、そもそも画像が tiff フォーマットなのでしょうか?画像ビューアーとかで開けますか?
yamatail

2018/10/29 01:22

遅くなり申し訳ございません。一応開けます。真っ黒ですけど。
guest

回答2

0

ベストアンサー

取り扱うtifデータは1ピクセルにカウント数の入ったデータなのでグレースケール相当のものです。カウント数の範囲は、-2から177880です。

そもそも読み込もうとしているファイルが tiff フォーマットに準拠したデータなのでしょうか?フォーマットに準拠していないのであれば、読み込んだ結果がおかしくなるということも考えられるので、その点を確認する必要があります。
ヘッダーを調べて、ビット深度など画像の情報を調べてみてはどうでしょうか。

tiff フォーマット


ネット上にあった tiff 画像で試したところ、どちらで読み込んでも値が一致することが確認できました。
OpenCV では (H, W, C) の配列を返すのに対して、PIL では (H, W, C, A) のアルファチャンネル付きの配列を返しました。また OpenCV の場合はチャンネルの順序が BGR である違いはあります。ただ、それを考慮に入れると値自体は一致しました。

試したtiffファイル

import cv2 from PIL import Image img1 = cv2.imread('test.tiff', -1) img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB) print('img1.shape', img1.shape) # img1.shape (38, 174, 3) img2 = np.array(Image.open('test.tiff')) print('img2.shape', img2.shape) # img2.shape (38, 174, 4) print(np.allclose(img1, img2[:, :, :3])) # True

投稿2018/10/26 06:02

tiitoi

総合スコア21956

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yamatail

2018/10/26 06:15

tiff フォーマットに準拠したデータかどうかは調べる必要があるかもしれません。確認してみます。
yamatail

2018/10/29 01:52

tifファイルをバイナリエディタで開いていろいろ確認しました。 一応、「Tiff Analyzer」というフリーのソフトも通してみました。追記しておきます。おそらく問題ないのだと思うのですが。どうでしょうか
tiitoi

2018/10/29 03:12 編集

追加調査の結果を貼っていただきありがとうございます。読み込もうとしている画像は 32bit シングルチャンネルの画像ですか。OpenCV は 32bit 深度画像の扱いは問題が多く、実際にダミーの 32bit チャンネル画像を作り読み込んでみたところ、OpenCV では正しく読み込めていなかったので対応していないのではないでしょうか。
tiitoi

2018/10/29 03:25 編集

OpenCV は対応してないようなので、PIL で正しく読み込めているのであれば、それで良いと思いますが、そうでない場合は他のライブラリを探す必要がありそうです。 tifffile というモジュールも見つけましたが、どうでしょうか。 https://pypi.org/project/tifffile/ (pip install tifffile) img = tifffile.imread(filepath) で読み込めます。
yamatail

2018/10/29 04:14 編集

いろいろご教授頂きありがとうございました。tiffファイルとopenCVの互換性が良くないみたいですね。tifffileでも正しく読み込めました。 tifファイルから丁寧に教えて頂き、ただただ感謝です。では,データ読み込みは、PILかtifffileで行うことにしようかと思います。
guest

0

2つのライブラリの色情報の扱い方の差からきているのだと思います。PILでは普通にRGBで色を持ちますが、OpenCVではなぜかBGRで色を持ちます。その結果、2つのライブラリで値が対応しなくなり、有名なものだとPILからOpenCVへ変換すると画像が青くなるという現象が起きます。
https://qiita.com/yusukeasari/items/3eaddfbb3a25f37d8e08

[追記]
こちらでいろいろやってみた結果のリンクを張っておきます。
https://gist.github.com/Hayashi-Yudai/9bd527c69cd6e9265de45d4a637dc121

こちらにtiffファイルがなかったのでjpegでやったのですが、rbgの値はcv2とPILで若干違いますね。あとimg[0][0]はRGBそれぞれの値が格納されているはずなので長さ3のリストが返ってくると思うのですが、そちらの出力を見ると数字1つが返ってきているようです。これはどこかがおかしいと思うのですがどうでしょう?

投稿2018/10/23 08:17

編集2018/10/24 05:41
Yhaya

総合スコア439

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yamatail

2018/10/24 00:43

表示される画像の色も同じなのですが、 それでもデータだけ違うこともあり得るということなのでしょうか?
yamatail

2018/10/24 01:05

アドバイスありがとうございます。RGBに変換して描写するようにしましたが、別のところでつまづいております。経緯を本文に追記しております。貴重な情報ありがとうございました。
Yhaya

2018/10/24 05:22

表示される画像の色も同じということだと、色指定の問題ではないかもしれませんね。もう少し調べてみます。ちなみに、BGRからRGBへの変換はcv2を使うと簡単です。 CV_im_rgb = cv2.cvtColor(CV_im, cv2.COLOR_BGR2RGB)
yamatail

2018/10/26 00:19

お返事遅くなり申し訳ありません。 CV_im_rgb = cv2.cvtColor(CV_im, cv2.COLOR_BGR2RGB) でもエラーが出てダメでした・ error: OpenCV(3.4.1) C:\Miniconda3\conda-bld\opencv-suite_1533128839831\work\modules\imgproc\src\color.cpp:11115: error: (-215) scn == 3 || scn == 4 in function cv::cvtColor ただ、 CV_im_RGB = CV_im[:, ::-1].copy() とすると画像が表示されるようになりました。が、データはまだへんてこなままです。
yamatail

2018/10/26 02:02

重要な情報が一つわかりました。このtifファイルのデータは、グレースケールのデータです。(もともと、1ピクセルに入っている情報が、カウント数なので) なので変換とかそれ以前の問題だったかもしれません。 確認せず申し訳ありませんでした。
Yhaya

2018/10/26 11:21

そうなんですね、ピクセルに入っているデータがカウント数というのは珍しいですね(イメージングとかですか?)。このようなケースは遭遇したことないのでもう少し調べてみます。
yamatail

2018/10/29 00:55

あっそうですイメージングです.(察しがよろしいですね^^;)今は、imageJとか使っているのですが、データ扱うのには少々不憫なので、Pythonの方を勉強してます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問