8비트 그레이스케일 이미지로 다운 스케일링 및 이미지 대비

전제



여기서 말하는 다운 스케일링은 이미지의 표본화에서 말하는 다운 스케일을 의미합니다.

이미지 다운 스케일링



여기에서는 그레이 스케일 이미지를 대상으로 이야기합니다.
일반적으로 그레이 스케일 이미지는 8비트, 16비트, 32비트 등 '1채널'의 픽셀 모음으로 구성되어 있습니다.
(RGB등의 컬러 화상은, R, G, B 각각의 채널이 있어, 이것들을 통합해 화상으로 하고 있습니다.이 점은 중요합니다. 바꾸어 말하면, RGB 화상은, 8-bit grayscale 화상이 3장 분 있다고 말할 수 있습니다.엄격하게는 α성분(투명도를 지정하는 성분)이 있는 경우도 있습니다만, α성분도 8-bit grayscale 화상이 1장분 증가한 것 같습니다.)

자주 의료 영상으로 사용되는 것이 16-bit 이미지입니다.
16비트 이미지는 0-65535 사이의 숫자를 픽셀 값으로 유지할 수 있습니다.
반면 8비트 이미지는 0-255까지의 숫자만 유지할 수 있습니다.
(부호 첨부, 부호 없음에 대해서는 여기에서는 감히 만지지 않습니다.)

화상 처리나 기계 학습 등에서는, 계산을 간편하게 하기 위해서, 또는 처리를 고속으로 하기 위해서, 높은 비트의 화상을 8-bit 화상에 다운 스케일 해 변환하는 처리를 실시합니다.
이 다운 스케일 때 작법을 잘못하면 이미지가 이상하게되기 때문에주의가 필요합니다.

샘플 이미지



JIRA의 흉부 X 선을 빌려드립니다.
LEE와 붙어 있는 것은 비압축 이미지라는 의미입니다. 이것을 사용합니다.
샘플 이미지

다운 스케일 예 (16-bit ~ 8-bit)



먼저 이미지를로드하고 numpy의 ndarray로 처리하기 위해 pydicom을 사용합니다.
!pip install pydicom

데이터를 로드합니다.
import pydicom
import numpy as np
ds = pydicom.dcmread('CR_LEE_IR87a.dcm')#パスを指定する

#ピクセルを取り出す(ndarrayとして扱っています)
pixels = ds.pixel_array

# 左右反転しているので戻す
pixels = np.fliplr(pixels)

#画像として表示
import matplotlib.pyplot as plt
plt.imshow(pixels,cmap="gray")#2つとも必要
plt.show() 



이를 위해 이 이미지가 8비트가 아닌지 확인합니다.
DICOM 태그에서도 알 수 있지만 직접 픽셀을 보아도 알 수 있습니다.
# この画像の画素を見てみる
print (pixels[512,512]) # 3186

픽셀(x, y)(512,512)의 픽셀 값은 3186임을 확인할 수 있습니다.
즉, 0-255 사이에 없고, 실수가 아니기 때문에 16-bit인 것을 알 수 있습니다.

이제 준비가 되었습니다.

numpy



단순히 8bit로 변환해 보겠습니다.
# numpyで8 bit変換してみる
np_img = pixels.astype('uint8')
plt.imshow(np_img,cmap="gray")
plt.show() 



다르다.

Pillow


# pillowを使う
from PIL import Image, ImageOps
pil_img = Image.fromarray(pixels)
pil_img = pil_img.convert('L')#L:grayscale
plt.imshow(pil_img,cmap="gray")#2つとも必要
plt.show() 
print(np.asarray(pil_img)[512,512]) #255, 完全にアウトオブレンジな感じです。



이것도 다르구나.

OpenCV


# opencvを使う
# 変換可能
# pixels は16 bit配列の変数とする。
import cv2
cv_img8 = np.zeros(pixels.shape)  # dummy変数
cv_img8 = cv2.convertScaleAbs(pixels-np.min(pixels), cv_img8, 255/(np.max(pixels)-np.min(pixels)), beta=0) #  2021/6/22修正
cv_img8 = cv_img8.astype(np.uint8)
plt.imshow(cv_img8, cmap="gray")
plt.show() 
print(cv_img8[512,512])

Scikit-image


# skimageを使う
import skimage
sk_img = skimage.img_as_ubyte(pixels)
plt.imshow(sk_img,cmap="gray")#2つとも必要
plt.show() 

오! 라고 생각하지만, 이것은 눈부시고, 잘 보면 화소가 붕괴되고 있다.



ImageJ 알고리즘을 이용한 다운 스케일



ImageJ의 다운 스케일을 구현해 보았습니다.
최대값, 최소값 및 스케일링 팩터로 정규화합니다.
# ImageJから拝借したノーマリゼーション
amin=np.amin(pixels)
amax=np.amax(pixels)
scale = 255.0/(amax-amin) # 256.0/(amax-amin+1)
pixelsByte = np.copy(pixels)
# pixelsByte = pixelsByte - amin # 最小値は差分 20210622修正
pixelsByte = pixelsByte*scale # 0-255の範囲にリスケール
# np.clip(pixelsByte,0,255) # 冗長でした
pixelsByte = np.uint8(pixelsByte) # 符号なしバイトに変換

print(np.asarray(pixelsByte)[512,512])
plt.imshow(pixelsByte,cmap="gray")
plt.show() 



이것 이것. 원하는 이미지입니다.

Visionary Imaging Services, Inc.

좋은 웹페이지 즐겨찾기