why is every pixel of an image are equal to 255? - python

I am experimenting with PIL and trying to analyze the image I attached.
Since my goal is to eventually be able to recognize it via neural networks,
I expect all pixels to have different intensities and therefore different values
ranging from 0 to 255. I am not sure why, every single pixel of this image is equal to
255. How so? What exactly am I doing wrong?
import numpy as np
import pandas as pd
import PIL
from PIL import Image
img = Image.open(r'key_1.jpg')
print(img.format)
print(img.size)
print(img.mode)
img # displays the image
img_sequence = img.getdata()
img_array = np.array(img_sequence)
print((img_array)) # all pixels = 255

Actually, they are not. You can see the top and the last few rows only where it shows 255 because the pixels there are white. If you try reading the same array using PIL/OpenCV, the result will show properly.
However, you can see all the results of the NumPy array using this method-
img_sequence = img.getdata()
img_array = np.array(img_sequence)
np.set_printoptions(threshold=np.inf)
print(img_array)
Sample screenshot of a random part of the output I got for the same image -

Related

How to change specific pixel value in grayscale image?

I want to change the pixel value of a grayscale image using OpenCV.
Assume that I have a grayscale image and I want to convert all its pixel to 0 value one at a time. So that the resultant image is completely black. I tried this but there is no change in the image:
image = cv2.imread('test_image.png',0)
for i in range(image.shape[0]):
for j in range(image.shape[1]):
image[i, j] = 0
Result:
display the updated image
In most cases, you want to avoid using double for loops to modify pixel values since it is very slow. A better approach is to use Numpy for pixel modification since OpenCV uses Numpy arrays to display images. To achieve your desired result, you can use np.zeros to create a completely black image with the same shape as the original image.
import cv2
import numpy as np
image = cv2.imread("test_image.png", 0)
black = np.zeros(image.shape, np.uint8)
cv2.imshow('image', image)
cv2.imshow('black', black)
cv2.waitKey(0)
For example with a test image. Original (left), result (right)
I would suggest you to always try manipulating the copy of an image so that the image doesn't get affected in the wrong way. Coming to your question, you can do the following:
import cv2
image = cv2.imread('test_image.png',0)
#Creating a copy of the image to confirm right operation is performed on the image.
image_copy = image.copy()
image_copy[:,:] = [0] #Setting all values to 0.

Skimage - Weird results of resize function

I am trying to resize a .jpg image with skimage.transform.resize function. Function returns me weird result (see image below). I am not sure if it is a bug or just wrong use of the function.
import numpy as np
from skimage import io, color
from skimage.transform import resize
rgb = io.imread("../../small_dataset/" + file)
# show original image
img = Image.fromarray(rgb, 'RGB')
img.show()
rgb = resize(rgb, (256, 256))
# show resized image
img = Image.fromarray(rgb, 'RGB')
img.show()
Original image:
Resized image:
I allready checked skimage resize giving weird output, but I think that my bug has different propeties.
Update: Also rgb2lab function has similar bug.
The problem is that skimage is converting the pixel data type of your array after resizing the image. The original image has a 8 bits per pixel, of type numpy.uint8, and the resized pixels are numpy.float64 variables.
The resize operation is correct, but the result is not being correctly displayed. For solving this issue, I propose 2 different approaches:
To change the data structure of the resulting image. Prior to changing to uint8 values, the pixels have to be converted to a 0-255 scale, as they are on a 0-1 normalized scale:
# ...
# Do the OP operations ...
resized_image = resize(rgb, (256, 256))
# Convert the image to a 0-255 scale.
rescaled_image = 255 * resized_image
# Convert to integer data type pixels.
final_image = rescaled_image.astype(np.uint8)
# show resized image
img = Image.fromarray(final_image, 'RGB')
img.show()
Update: This method is deprecated, as per scipy.misc.imshow
To use another library for displaying the image. Taking a look at the Image library documentation, there isn't any mode supporting 3xfloat64 pixel images. However, the scipy.misc library has the appropriate tools for converting the array format in order to display it correctly:
from scipy import misc
# ...
# Do OP operations
misc.imshow(resized_image)

I am trying to convert a numpy array to PIL.Image. But it is giving black images. The numpy array is returned by pyramid_gaussian method from skimage

Here is my code
import numpy as np
from PIL import Image
from skimage.transform import pyramid_gaussian
image = Image.open('/home/sumith/Downloads/AFW/testimages/3854178896.jpg')
rows, cols, dim = np.asarray(image).shape
pyramid = tuple(pyramid_gaussian(image, downscale=2,))
count = 0
for pyr in pyramid[0:8]:
row, col, dim = (np.asarray(pyr).shape)
count += 1
#io.imsave('/home/sumith/imagepyramids/'+count.__str__()+".jpg", pyr)
print(type(pyr))
image = Image.fromarray(pyr.astype('uint8'), 'RGB')
image.save('/home/sumith/imagepyramids/'+count.__str__()+".jpg")
when I print the type(pyr) it is showing as but when I try to convert and save it from PIL image all the images in the pyramid will be black. but if i save it using io.imsave it is working fine .I need the image pyramid's image to be fed into a neural network so if i can feed it as PIL.Image then it will be very helpful.
Thanks in advance!! The black image looks like this black-image
Check the values in pyr. Maybe they are values between 0 and `, while your RGB image is expected to be with values between 0 and 255.

Blank image appearing

I am using simpleITK to process MRI images in .mha format. I subsequently convert it into a numpy array. I am able to visualize the images using matplotlib.However, if I perform any prerprocessing or I multiply the image by its binary mask, all I get is a blank image. Is there something I am missing. My simplified code is shown below.
import SimpleITK as sitk
import numpy as np
from matplotlib import pyplot as plt
input_image = sitk.ReadImage('MRI.mha')
input_array = sitk.GetArrayFromImage(input_image)
plt.imshow(input_array[0,:,:],cmap = 'gray') # I get an image for this. No preprocessing has been performed.
plt.show()
# However, if I replace input_array after preprocessing, I get a black square.
I think this has something to do with the range of the data, but I am not able to pinpoint where. The image visualized before preprocessing has a maximum value of 744. After preprocessing, this drops down to 4, and that is when problems crop up. Any pointers to where I might be going wrong?
You should check your image pixel type before any processing. The MRI image volume which you are testing on has a sitkInt32 (Signed 32 bit integer) pixel type. So there is a high chance that your processing (e.g. your division operations) would make your pixel values zeros and you get black images.
You can either cast your image to float using SimpleITK:
input_image = sitk.ReadImage('MRI.mha')
print(input_image.GetPixelIDTypeAsString())
input_image = sitk.Cast(input_image,sitk.sitkFloat32)
input_array = sitk.GetArrayFromImage(input_image)
or change your numpy array data type before processing:
input_image = sitk.ReadImage('MRI.mha')
input_array = sitk.GetArrayFromImage(input_image)
input_array = input_array.astype(np.float32)
Read more about pixel types at SimpleITK Image Basics notebook.

PIL/Pillow convert Image to list and back again

I'm trying to open an RGB picture, convert it to grayscale, then represent it as a list of floats scaled from 0 to 1. At last, I want to convert it back again to an Image. However, in the code below, something in my conversion procedure fails, as img.show() (the original image) displays correctly while img2.show() display an all black picture. What am I missing?
import numpy as np
from PIL import Image
ocr_img_path = "./ocr-test.jpg"
# Open image, convert to grayscale
img = Image.open(ocr_img_path).convert("L")
# Convert to list
img_data = img.getdata()
img_as_list = np.asarray(img_data, dtype=float) / 255
img_as_list = img_as_list.reshape(img.size)
# Convert back to image
img_mul = img_as_list * 255
img_ints = np.rint(img_mul)
img2 = Image.new("L", img_as_list.shape)
img2.putdata(img_ints.astype(int))
img.show()
img2.show()
The image used
The solution is to flatten the array before putting it into the image. I think PIL interprets multidimensional arrays as different color bands.
img2.putdata(img_ints.astype(int).flatten())
For a more efficient way of loading images, check out
https://blog.eduardovalle.com/2015/08/25/input-images-theano/
but use image.tobytes() (Pillow) instead of image.tostring() (PIL).
.

Categories