Search code examples
pythonscikit-image

Why 'imshow' in skimage does not work properly with bit shift


I tried to display bit planes images with bit shift method. However I always get a whole black image for all subplots.

import skimage.io as io  
import skimage.util as util  
import numpy as np  
from matplotlib import pyplot as plt  
from skimage.color import rgb2gray  
import skimage.filters as fl  

path = 'D:/Users/user/PycharmProjects/Image_Processing/Data/16.png'
w = io.imread(path)  

# convert the colorful image to a grey scale image  
gray = rgb2gray(w)  
plt.imshow(gray, cmap=plt.get_cmap('gray'), vmin=0, vmax=1)  
plt.show()  

# bit shift for creating bit plane images  
bps = [(np.uint8(gray) >> i) % 2 for i in range(8)]  

# plot 8 subplots to show the result  
for i in range(8):  
    plt.subplot(3, 3, i+1)  
# add color map to assure the present color is in grey scale  
    io.imshow(bps[i], , cmap=plt.get_cmap('gray'))  
    plt.axis('off')  
    plt.show()  

Original grey scale picture

Result

Also there will be some warning with the execution result:

D:\Users\user\Anaconda3\python.exe D:/Users/user/PycharmProjects/Image_Processing/read_image.py D:\Users\user\Anaconda3\lib\site-packages\skimage\io_plugins\matplotlib_plugin.py:75: UserWarning: Low image data range; displaying image with stretched contrast. warn("Low image data range; displaying image with "

Process finished with exit code 0

By the way, if I used filter and threshold from otsu,yen,li. I will get the expected result.

thresh = fl.threshold_otsu(gray)
binary = gray >= thresh
io.imshow(binary)
plt.show()

Could you please tell me where I get wrong with the original method? In some other threads mentioned about the loss of converting pictures from one category to another. Moreover, I could also get successful result by using pure opencv method.

I have checked the following related threads, but I still have no idea how to fix this problem:

skimage issue

bit plane slicing

threshold method

Thank you for your help!


Solution

  • I found out that I misused the numpy unsigned integer transformation, since the original grey array contains unsigned float numbers between 0 and 1. First, I need to make grey's intensity into float numbers which are greater than 1.

    bps = [(np.uint8(gray*255) >> i) % 2 for i in range(8)] 
    

    Then, the problem is solved.