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

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

ただいまの
回答率

87.95%

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,649

score 46

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

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

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

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

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('data.tif',-1)

plt.imshow(img)

#######データを確認##############
img[0][0]
#9.25e-43
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
%matplotlib inline

im = Image.open('data.tif')
#im.show()
imarr = np.array(im)

plt.imshow(imarr)

#######データを確認##############
imarr[0][0]
#660

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

追記(1)

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

%matplotlib inline
import cv2
from PIL import Image
import numpy as np
from matplotlib import pyplot as plt

CV_im =cv2.imread('data.tiff',-1)

#BGRからRGBへ変換
CV_img_RGB = CV_im[:, :, ::-1].copy()

#変換
CV2PIL_normalize=Image.fromarray(CV_im_RGB)

#描画
plt.imshow(CV2PIL_normalize)
IndexError                                Traceback (most recent call last)
<ipython-input-108-5afa93a697bc> in <module>()
      8 
      9 #BGRからRGBへ変換
---> 10 CV_img_RGB = CV_im[:, :, ::-1].copy()
     11 
     12 #変換

IndexError: 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も違うとは...)

print(imarr[0][0])
#660

print(CV_im_RGB[0][0])
#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解析ソフトを使って確認してみる。(自信なかったので...)

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • tiitoi

    2018/10/26 12:41

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

    キャンセル

  • yamatail

    2018/10/26 14:38

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

    キャンセル

  • tiitoi

    2018/10/26 15:05 編集

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

    キャンセル

  • yamatail

    2018/10/29 10:22

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

    キャンセル

回答 2

checkベストアンサー

+1

取り扱う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/29 12:12 編集

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

    キャンセル

  • 2018/10/29 12:24 編集

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

    キャンセル

  • 2018/10/29 13:14 編集

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

    キャンセル

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/26 11:02

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

    キャンセル

  • 2018/10/26 20:21

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

    キャンセル

  • 2018/10/29 09:55

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

    キャンセル

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

  • ただいまの回答率 87.95%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る