I am having a problem converting an image I;16 to JPEG with PIL.
My original image can be found here (as pickle).
The original image comes from a DICOM file.
Here is the code to try:
import pickle
import matplotlib.pyplot as plt
from PIL import Image
ims = pickle.load(open("pixel_array.pickle", "rb"))
img = Image.fromarray(ims)
print(img.mode)
rgb_im = img.convert("RGB")
print(rgb_im.mode)
fig, ax = plt.subplots(figsize=(20, 10))
ax.imshow(rgb_im, cmap=plt.cm.bone)
fig.show()
Unfortunately the image is completely white, while it should be a chest x-ray scan image.
I followed this other stackoverflow question, and with the following
ims = pickle.load(open("pixel_array.pickle", "rb"))
img = Image.fromarray(ims)
print(img.mode)
img.mode = 'I'
rgb_im = img.point(lambda i:i*(1./256)).convert('L')
rgb_im.save('my.jpeg')
fig, ax = plt.subplots(figsize=(20, 10))
ax.imshow(rgb_im, cmap=plt.cm.bone)
fig.show()
I am able to visualise the image, but unfortunately my.jpeg is a black image. Please help!
Your values are 16-bit and need to be reduced to 8-bit for display. You can scale them from their current range of 2,712 (i.e. ims.min()) to 4,328 (i.e. ims.max()) with the following:
from PIL import Image
import numpy as np
import pickle
# Load image
ims = pickle.load(open("pixel_array.pickle", "rb"))
# Normalise to range 0..255
norm = (ims.astype(np.float)-ims.min())*255.0 / (ims.max()-ims.min())
# Save as 8-bit PNG
Image.fromarray(norm.astype(np.uint8)).save('result.png')
Related
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
from PIL import Image
iFile = "Temp.txt" # Binary image
shape = (320,240) # length and width of the image
dtype = np.dtype('<u2') # unsigned 16 bit little-endian.
oFile = "Temp_Main.png"
#Open binary image to convert as an image
fid = open(iFile, 'rb')
data = np.fromfile(fid, dtype)
image = data.reshape(shape)
imgplot = plt.imshow(image)
imgplot = plt.axis("off")
plt.savefig(oFile)
im = Image.open('C:/Users/sesa627732/Documents/_Cases/Temp_Main.png')
#show 90 degree flipped image
im = im.transpose(Image.ROTATE_270)
#Show vertically flipped image
im = im.transpose(Image.FLIP_TOP_BOTTOM)
im.save("Temp_Main.png")
im.show()
I'm scanning a book and now I'm on the final step. I need to crop all squared images with content in the center by white background without saving ratio. Some libs do not support TIFF format.
How can I do that ?
I combined some examples from How do I crop an image on a white background with python?, How do I crop an image on a white background with python? and other questions. It works
from PIL import Image
from skimage import io, img_as_float
import sys
import numpy as np
import glob
import matplotlib.pyplot as plt
filePaths = glob.glob("*.tif")
for filePath in filePaths:
image = img_as_float(io.imread(filePath))
white = np.array([1, 1, 1, 1])
mask = np.abs(image - white).sum(axis=2) < 0.05
coords = np.array(np.nonzero(~mask))
top_left = np.min(coords, axis=1)
bottom_right = np.max(coords, axis=1)
out = image[top_left[0]:bottom_right[0],
top_left[1]:bottom_right[1]]
plt.imshow(out)
# plt.show()
fig = plt.gcf()
for ax in fig.axes:
ax.axis('off')
ax.margins(0,0)
ax.xaxis.set_major_locator(plt.NullLocator())
ax.yaxis.set_major_locator(plt.NullLocator())
fig.savefig(filePath + ".png", dpi=1200, bbox_inches="tight", pad_inches=0)
I came over the following issue: the resize functions of these two libraries behave differently. Here is a small test:
import numpy as np
import PIL
import cv2
from matplotlib import pyplot as plt
img = np.random.randn(10, 10, 3)
SIZE = (5, 5)
img -= img.min()
img /= img.max()
img = (img*255).astype(np.uint8)
# Display the initial image
plt.figure(figsize=(16,9))
plt.imshow(img)
plt.show()
plt.close()
# resize the image in two different ways
img_cv2 = cv2.resize(img, dsize=SIZE, interpolation=cv2.INTER_LINEAR)
img_pil = PIL.Image.fromarray(img).resize(SIZE, resample=PIL.Image.BILINEAR)
# get the difference image and normalize it
diff = np.abs(img_cv2.astype(np.float32) - img_pil)
diff /= diff.max() or 1
# display results
fig, axs = plt.subplots(1, 3, figsize=(16, 9))
axs[0].imshow(img_cv2)
axs[1].imshow(img_pil)
axs[2].imshow(diff)
plt.show()
plt.close()
My question is now: why is this happening? Is the difference in the implementation (I didn't check the code in PIL or OpenCV yet) or am I using the functions in the wrong way?
Here are some example outputs: Input image and Resized images.
I tried to convert RGB image into gray image and plot them. But I can't plot the gray image after PIL convert('L'). the following error was reported in the Spyder console (Python3.6). However, the original image can be plotted if i don't use the convert('L').
File "d:\ProgramData\Anaconda3\lib\site-packages\matplotlib\image.py", line 430, in _make_image
if A.mask.shape == A.shape:
AttributeError: 'numpy.ndarray' object has no attribute 'mask'
see my python code in below:
from PIL import Image, ImageFilter
import tensorflow as tf
import matplotlib.pyplot as plt
file_name='images\\2.4.1.png'
im0 = Image.open(file_name)
plt.imshow(im0)
plt.show()
im = im0.convert('L')
plt.imshow(im, cmap='gray')
plt.show() # Not working here
Trying using LA instead of just L as follows:
from PIL import Image, ImageFilter
import matplotlib.pyplot as plt
file_name = r'images\2.4.1.png'
im0 = Image.open(file_name).convert('LA')
plt.imshow(im0, cmap='gray')
plt.show()
The parameter specifies the conversion mode, in your case the PNG file probably has an alpha channel, so the A is needed.
See also: Pillow modes
I need to add noise to multiple of coloured images (file format is ppm; source: http://benchmark.ini.rub.de/Dataset/GTSRB_Final_Training_Images.zip) in python. The noised output images should be still in colour.
I tryed the following:
from scipy import misc
import numpy as np
import cv2
import imageio
# Read image ('00000_00030.ppm') from file system
image = misc.imread('./00000/00000_00030.ppm', mode="RGB")
# Add noise to the input image
noised_image = image + 3 * image.std() * np.random.random(image.shape)
# Plot original and noisy images
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
f, axarr = plt.subplots(2, 2)
axarr[0, 0].imshow(image)
axarr[0, 0].set_title('Original image')
axarr[0, 1].imshow(noised_image)
axarr[0, 1].set_title('Noised image')
plt.show()
# Save noised image to file system
saved_image = cv2.imwrite("./noised.ppm", noised_image)
But first of all the problem is that the noised image won't be plotted correctly in jupyter notebook (see figure 1):
figure 1
The second problem is that the RG-channels (Red and Green) were be lost (in saved file):
figure 2
So how can I preserve all RGB colors in noised image?
After searching for a long time I have the solution now - the saved file preserves now all RGB-colours (See Line 8 in following code; see figure 3):
from scipy import misc
import numpy as np
import cv2
import imageio
# Read image ('00000_00030.ppm') from file system
# image = misc.imread('./00000/00000_00030.ppm', mode="RGB")
image = cv2.imread('./00000/00000_00030.ppm',1)
# Add noise to the input image
noised_image = image + 3 * image.std() * np.random.random(image.shape)
# Plot original and noisy images
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
f, axarr = plt.subplots(2, 2)
axarr[0, 0].imshow(image)
axarr[0, 0].set_title('Original image')
axarr[0, 1].imshow(noised_image)
axarr[0, 1].set_title('Noised image')
plt.show()
# Save noised image to file system
saved_image = cv2.imwrite("./noised1.ppm", noised_image)
Figure 3
But the plotted figures are still wrong:
Figure 4
Here is the final Code to add noise to RGB images in python, and plot them correctly:
from scipy import misc
import numpy as np
import cv2
import imageio
# Read image ('00000_00030.ppm') from file system
# image = misc.imread('./00000/00000_00030.ppm', mode="RGB")
image = cv2.imread('./00000/00000_00030.ppm',1)
# Add noise to the input image
noised_image = image + 3 * image.std() * np.random.random(image.shape)
RGB_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Plot original and noisy images
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
f, axarr = plt.subplots(2, 2)
axarr[0, 0].imshow(RGB_image)
axarr[0, 0].set_title('Original image')
axarr[0, 1].imshow(noised_image)
axarr[0, 1].set_title('Noised image')
plt.show()
# Save noised image to file system
saved_image = cv2.imwrite("./noised1.ppm", noised_image)
This will take the pixel values of the given image and start encoding the noise that you give as input to the least significant bits in the pixel. The image output would vary slightly.
def asciiToBin(ascii):
return ''.join(str(bin(ord(byte)))[2:].zfill(8) for byte in ascii)
def hide(img, data, outName):
dataBin = asciiToBin(data)
pixels, mode = list(img.getdata()), img.mode
newPixels = []
for i in range(len(dataBin)):
newPixel = list(pixels[i])
newPixel[i%len(mode)] = setLSB(newPixel[i%len(mode)], dataBin[i])
newPixels.append(tuple(newPixel))
newData = newPixels + pixels[len(newPixels):]
img.putdata(newData)
img.save(outName, "PNG")
def setLSB(target, value):
binary = str(bin(target))[2:]
if binary[-1] != value:
binary = binary[:-1] + value
return int(binary, 2)