web-dev-qa-db-ja.com

タイプfloat64のnp.arrayをタイプuint8スケーリング値に変換します

特定のグレースケール画像を表す特定のnp.array dataがあります。残念ながら8ビット画像しか受け入れないSimpleBlobDetector()を使用する必要があるため、この画像を変換する必要があります。明らかに品質が低下しています。

私はすでに試しました:

import numpy as np
import cv2
[...]
data = data / data.max() #normalizes data in range 0 - 255
data = 255 * data
img = data.astype(np.uint8)
cv2.imshow("Window", img)

しかし、cv2.imshowは期待どおりの画像を提供しませんが、奇妙な歪みを伴います...

最後に、np.float64をnp.uint8に変換するだけで、すべての値をスケーリングし、残りを切り捨てます。 65535は255になり、65534は254になります。

ありがとう。

16
decadenza

画像を正規化するより良い方法は、各値を取得し、データ型が経験した最大値で除算することです。これにより、画像のダイナミックレンジが小さい画像が小さくなり、不注意に正規化されてグレーにならないようにします。たとえば、画像のダイナミックレンジが[0-2]であった場合、コードは現在、[0, 128, 255]の強度を持つようにスケーリングします。 np.uint8に変換した後、これらを小さくしたい。

したがって、すべての値を、実際の画像自体ではなく、画像typeで可能な最大値で除算します。次に、これを255でスケーリングして、正規化された結果を生成します。 numpy.iinfo を使用して、イメージのタイプ(dtype)を指定すると、そのタイプの情報の構造が取得されます。次に、この構造体からmaxフィールドにアクセスして、最大値を決定します。

したがって、上記を使用して、コードに次の変更を加えます。

import numpy as np
import cv2
[...]
info = np.iinfo(data.dtype) # Get the information of the incoming image type
data = data.astype(np.float64) / info.max # normalize the data to 0 - 1
data = 255 * data # Now scale by 255
img = data.astype(np.uint8)
cv2.imshow("Window", img)

入力データ型がそうでない場合に備えて、除算を行うときに浮動小数点の精度を維持するために、イメージをnp.float64にさらに変換したことに注意してください。

24
rayryeng

skimage.img_as_ubyte(yourdata)を使用できます。0〜255の範囲の配列を指定できます

from skimage import img_as_ubyte

img = img_as_ubyte(data)
cv2.imshow("Window", img)
1
Ali Farouk