[PYTHON] 8-bit grayscale Downscaling to images and image contrast

Premise

Downscaling here means downscaling in terms of image sampling.

Image downscaling

Here, we will talk about grayscale images. Generally, a grayscale image is composed of a collection of "1 channel" pixels such as 8-bit, 16-bit, 32-bit, etc. (Color images such as RGB have R, G, and B channels, and these are integrated into an image. This is important. In other words, RGB images have three 8-bit grayscale images. Strictly speaking, there may be an α component (a component that specifies transparency), but the α component is also like an 8-bit grayscale image increased by one.)

16-bit images are often used in medical images. 16-bit images can hold numbers between 0-65535 as pixel values. On the other hand, 8-bit images can only hold numbers from 0 to 255. (Signed and unsigned are not mentioned here.)

In image processing and machine learning, high-bit images are downscaled and converted to 8-bit images in order to simplify calculations or speed up processing. Please note that if you make a mistake during this downscale, the image will be strange.

sample image

I will borrow a chest X-ray from JIRA. The one with LEE means uncompressed image. Use this. Sample image

Downscale example (16-bit to 8-bit)

First, use pydicom to load the image and treat it as a numpy ndarray.

!pip install pydicom

Load the data.

import pydicom
import numpy as np
ds = pydicom.dcmread('CR_LEE_IR87a.dcm')#Specify the path

#Extract pixels (treated as ndarray)
pixels = ds.pixel_array

#Since it is flipped left and right, return it
pixels = np.fliplr(pixels)

#Display as an image
import matplotlib.pyplot as plt
plt.imshow(pixels,cmap="gray")#Both are required
plt.show() 

ダウンロード (2).png

To be on the safe side, make sure this image is not 8-bit. You can see it from the DICOM tag, but you can also see it by looking directly at the pixels.

#Take a look at the pixels in this image
print (pixels[512,512]) # 3186

You can see that the pixel value at pixel (x, y) (512,512) is 3186. In other words, it is 16-bit because it is not between 0 and 255 and it is not a real number.

Now you are ready.

numpy

I will simply convert it to 8bit.

#Try 8 bit conversion with numpy
np_img = pixels.astype('uint8')
plt.imshow(np_img,cmap="gray")
plt.show() 

ダウンロード (3).png

It's different.

Pillow

#Use 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")#Both are required
plt.show() 
print(np.asarray(pil_img)[512,512]) #255,It feels completely out of range.

ダウンロード (4).png

This is also different.

OpenCV

#use opencv
#Since it cannot be converted by the following method, astype from numpy in step 1()You may only be able to use the same method as the conversion method with.
#Perhaps my usage is wrong. .. Refer to it as a failure example.
import cv2
cv_img16 = cv2.cvtColor(pixels, cv2.COLOR_BAYER_GR2GRAY)
cv_img8 = cv2.cvtColor(pixels, cv2.COLOR_BAYER_GR2GRAY) #For copying and conversion.
cv2.convertScaleAbs(cv_img16, cv_img8, 1/255,)#Not converted
plt.imshow(cv_img8,cmap="gray")
plt.show() 
print(cv_img8[512,512])#Confirm that it is not converted.

Scikit-image

#Use skimage
import skimage
sk_img = skimage.img_as_ubyte(pixels)
plt.imshow(sk_img,cmap="gray")#Both are required
plt.show() 

Oh! I think this is a deception, and if you look closely, the pixels are crushed.

ダウンロード (5).png

Downscaling using ImageJ algorithm

I implemented ImageJ downscale. Normalize with maximum, minimum and scaling factors.

#Normalization borrowed from 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 #It feels like the minimum value does not have to be different.
pixelsByte = pixelsByte*scale # 0-Rescale to the range of 255
# np.clip(pixelsByte,0,255) #It was redundant
pixelsByte = np.uint8(pixelsByte) #Convert to unsigned bytes

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

ダウンロード (6).png

This is this. This is the image I was looking for.

Visionary Imaging Services, Inc.

Recommended Posts

8-bit grayscale Downscaling to images and image contrast
Grayscale image and save as csv
How to adjust image contrast in Python
Resize the image to the specified size and blacken the margins