Display Dicom image using PIL(PILLOW) Python Library - python

I am trying to read and display DICOM(.dcm) images using below code:-
import pydicom as dicom
import numpy as np
from PIL import Image, ImageEnhance, ImageOps
from PIL.ImageQt import ImageQt
def display_dicom_images(self, folder_Path):
try:
# Image parameters
image_width = 382
image_height = 382
image_depth = 3
self.total_images_in_folder = len(glob.glob1(folder_Path,"*"))
# Select the center image for display
self.current_image_number = round(self.total_images_in_folder / 2)
self.display_number = self.current_image_number
image_dtype = np.uint8
pixel_array = np.ndarray([self.total_images_in_folder, image_height, image_width, image_depth]).astype(image_dtype)
# load images here, once better MR images are acquired
for image_index in range(0, self.total_images_in_folder):
# for DICOM
image_path = folder_Path + "/" + str(image_index) + ".dcm"
scan_image = dicom.dcmread(image_path)
scan_image = scan_image.pixel_array.astype(image_dtype)
pixel_array[image_index, :scan_image.shape[0], :scan_image.shape[1], :scan_image.shape[2]] = scan_image
return pixel_array
But getting error:-
IndexError('tuple index out of range',)
i am using pillow python library for image.

How do you know scan_image.shape is of length 3? MR images should only be monochrome, which would make image_depth = 1 and the length of scan_image.shape equal to 2.
C.8.3.1.1.3 Photometric Interpretation
Enumerated Values:
MONOCHROME1
MONOCHROME2

Related

raise KeyError(key) from err KeyError: 'pixels' in my project

raise KeyError(key) from err
KeyError: 'pixels'
Hi,I am a beginner and wanted to convert row to an image and this error appeared to me,what does it mean?and what is the solution?
# import these libraries
import numpy as np
import pandas as pd
import cv2
import utils
import os
# data
data = pd.read_csv('test.csv') # Path of the .csv file
#print(data.shape) # to check the shape
#print(data.head(5)) # Use this to print the first 5 lines of the data, to understand it better
def convert2image(row):
pixels = row['pixels'] # in out dataset, the row heading was 'pixels'
img = np.array(pixels.split())
img = img.reshape(48,48) # dimensions of the image
image = np.zeros((48,48,3)) # empty matrix
image[:,:,0] = img
image[:,:,1] = img
image[:,:,2] = img
return image.astype(np.uint8) # return the image
count = 0
for i in range(1, 6): #data.shape[0]):
face = data.iloc[i] # remove one row from the data
img = convert2image(face) # send this row of data to the function convert2image
count = count + 1 # counter to save the images with different name
cv2.imwrite(r'C:/Users/sanch/Desktop/Data/Python_projects/Emotion_reco/test/'+ str(count) +'.jpg',img) # path where you want to save the image

Batch processing of Tiff files using skimage (Python)

I am looking to; open, process and save multiple TIFFs in Python.
I have the following code to open, process and save 1 (one) TIFF, but I have trouble with multiple files:
import skimage.io
import skimage.viewer
import skimage
import skimage.io
# Read 1 image.TIF:
image = skimage.io.imread(fname=path)
image[2,1]= 1.0
# Process the file (make binary)
gray_image = skimage.color.rgb2gray(image)
# Blur the image to denoise (larger sigma = more noise removed)
blurred_image = skimage.filters.gaussian(gray_image, sigma=5)
# Adding threshold, t:
t = 0.8
binary_mask = blurred_image < t
# Save the file to another location:
skimage.io.imsave(fname=path, arr = binary_mask)
Any help is appreciated!
Here's a multiprocessing approach that may help:
import skimage
from concurrent.futures import ProcessPoolExecutor
from glob import glob
import os.path
source_dir = '<your source directory>'
target_dir = '<your target directory>'
filetype = '*.tif'
def process(path):
image = skimage.io.imread(fname=path)
image[2,1] = 1.0
gray_image = skimage.color.rgb2gray(image)
blurred_image = skimage.filters.gaussian(gray_image, sigma=5)
outpath = os.path.join(target_dir, os.path.basename(path))
arr = blurred_image < 0.8
skimage.io.imsave(fname=outpath, arr=arr)
def main():
with ProcessPoolExecutor() as executor:
filelist = glob(os.path.join(source_dir, filetype))
executor.map(process, filelist)
if __name__ == '__main__':
main()
Use glob to identify all the files matching the *.tif pattern then utilise the ProcessPoolExecutor's map function to process each file in its own process. As the processing is mainly CPU intensive, multiprocessing is likely to be the best fit for this
Is it necessary that this be parallelized? It's not a huge bit of processing that you are performing. If you don't need parallel processing you can just run a for loop on your images
import skimage.io
import skimage.viewer
import skimage
import skimage.io
import os
import glob
# set up an in and out directory
in_dir = 'directory\with\images'
out_ir = 'directory\for\procecessed\images'
# make a list of all of the raw image files
os.chdir(in_dir)
filelist = glob.glob('*.png') # change to whatever file pattern you need here
for file_iter in filelist:
os.chdir(in_dir)
image = skimage.io.imread(fname=file_iter)
image[2,1]= 1.0
# Process the file (make binary)
gray_image = skimage.color.rgb2gray(image)
# Blur the image to denoise (larger sigma = more noise removed)
blurred_image = skimage.filters.gaussian(gray_image, sigma=5)
# Adding threshold, t:
t = 0.8
binary_mask = blurred_image < t
# Save the file to another location:
out_filename = file_iter[:-4] + 'processed.png' # make new filename based on old filename
os.chdir(out_dir)
skimage.io.imsave(fname=out_filename, arr = binary_mask)

How would I read a folder of images on my computer into a dataframe on Jupyter Notebooks?

This is my code right now, I have used a for loop to go through all the images in the folder and use the PIL library to read it into an array.
import cv2
import os
folder = '/Users/x/x/x/x'
def load_images_from_folder(folder):
images = []
for filename in os.listdir(folder):
img = cv2.imread(os.path.join(folder,filename))
if img is not None:
images.append(img)
return images
img = Image.fromarray(images_array,'RGB', dtype = object)

Change image size with PIL in a Google Cloud Storage Bucket (from a VM in GCloud)

This is what I need: when a user upload an image, verify if that image exceeds some size, if so change the size. This code works with no errors, but the image saved has the size without changes. The image is in a Google Cloud Storage Bucket, it is uploaded just before, but it works fine.
Any idea is welcome. Thanks in advance.
from PIL import Image
from django.core.files.storage import default_storage
from google.cloud import storage
from google.cloud.storage import Blob
import io
if default_storage.exists(image_path):
client = storage.Client()
bucket = client.get_bucket('mybucket.appspot.com')
blob = Blob(image_path, bucket)
contenido = blob.download_as_string()
fp = io.BytesIO(contenido)
im = Image.open(fp)
x, y = im.size
if x>450 or y>450:
im.thumbnail((450,450))
im.save(fp, "JPEG")
# im.show() here it shows the image thumbnail (thumbnail works)
blob.upload_from_string(fp.getvalue(), content_type="image/jpeg")
blob_dest = Blob('new_image.jpg', bucket)
blob.download_as_string()
blob_dest.rewrite(blob)
You've got a lot of extra stuff happening here, including saving the image to the local filesystem, which is unnecessary. This minimal example should work:
import io
from PIL import Image
from django.core.files.storage import default_storage
from google.cloud import storage
if default_storage.exists(image_path):
client = storage.Client()
bucket = client.get_bucket('mybucket.appspot.com')
# Download the image
blob = bucket.get_blob(data['name']).download_as_string()
bytes = io.BytesIO(blob)
im = Image.open(bytes)
x, y = im.size
if x>450 or y>450:
# Upload the new image
thumbnail_blob = bucket.blob('new_image.jpg')
thumbnail_blob.upload_from_string(im.resize(450, 450).tobytes())
I've tried the solution from #dustin-ingram and it happened to me that the file ended up corrupted when downloading it again. Using the code from this answer I reached a solution.
import io
from PIL import Image
from google.cloud import storage
__max_size = 450, 450
image_name = 'my_images/adasdasadas7c2a7367cf1f.jpg'
client = storage.Client()
bucket = client.bucket('my-bucket')
# Download the image
blob = bucket.blob(image_name).download_as_string()
blob_in_bytes = io.BytesIO(blob)
# Translating into PIL Image object and transform
pil_image = Image.open(blob_in_bytes)
pil_image.thumbnail(__max_size, Image.ANTIALIAS)
# Creating the "string" object to use upload_from_string
img_byte_array = io.BytesIO()
pil_image.save(img_byte_array, format='JPEG')
# Create the propper blob using the same bucket and upload it with it's content type
thumbnail_blob = bucket.blob(image_name)
thumbnail_blob.upload_from_string( img_byte_array.getvalue(), content_type="image/jpeg")
Regardless of what Cloud Storage you are using, you can use this method to resize the uploaded image in memory, then you can upload the image or manipulate it as you wish:
from io import BytesIO
from PIL import Image as PilImage
import os
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
def resize_uploaded_image(image, max_width, max_height):
size = (max_width, max_height)
# Uploaded file is in memory
if isinstance(image, InMemoryUploadedFile):
memory_image = BytesIO(image.read())
pil_image = PilImage.open(memory_image)
img_format = os.path.splitext(image.name)[1][1:].upper()
img_format = 'JPEG' if img_format == 'JPG' else img_format
if pil_image.width > max_width or pil_image.height > max_height:
pil_image.thumbnail(size)
new_image = BytesIO()
pil_image.save(new_image, format=img_format)
new_image = ContentFile(new_image.getvalue())
return InMemoryUploadedFile(new_image, None, image.name, image.content_type, None, None)
# Uploaded file is in disk
elif isinstance(image, TemporaryUploadedFile):
path = image.temporary_file_path()
pil_image = PilImage.open(path)
if pil_image.width > max_width or pil_image.height > max_height:
pil_image.thumbnail(size)
pil_image.save(path)
image.size = os.stat(path).st_size
return image
In case you are taking the image from a post form, you can do this:
image = request.FILES['image']
...
image = resize_uploaded_image(image, 450, 450)
...
thumbnail_blob.upload_from_string(image.read(), image.content_type)
A better way is to use it in the clean method of the image field in your form:
class ImageForm(forms.Form):
IMAGE_WIDTH = 450
IMAGE_HEIGHT = 450
image = forms.ImageField()
def clean_image(self):
image = self.cleaned_data.get('image')
image = resize_uploaded_image(image, self.IMAGE_WIDTH, self.IMAGE_HEIGHT)
return image
I achieved some results when combining your question with the answer of Dustin:
bucket = client.get_bucket('mybucket.appspot.com')
blob = Blob(image_path, bucket)
contenido = blob.download_as_string()
fp = io.BytesIO(contenido)
im = Image.open(fp)
x, y = im.size
if x > 128 or y > 128:
thumbnail_blob = bucket.blob('new_image.jpg')
thumbnail_blob.upload_from_string(im.resize((128, 128), 2).tobytes())
The 2 in resize is for resampling filter:
Use Image.NEAREST (0), Image.LANCZOS (1), Image.BILINEAR (2), Image.BICUBIC (3), Image.BOX (4) or Image.HAMMING (5)

Image drawn to reportlab pdf bigger than pdf paper size

i'm writing a program which takes all the pictures in a given folder and aggregates them into a pdf. The problem I have is that when the images are drawn, they are bigger in size and are rotated to the left oddly. I've searched everywhere, havent found anything even in the reportlab documentation.
Here's the code:
import os
from PIL import Image
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from StringIO import StringIO
def main():
images = image_search()
output = PdfFileWriter()
for image in images:
Image_file = Image.open(image) # need to convert the image to the specific size first.
width, height = Image_file.size
im_width = 1 * cm
# Using ReportLab to insert image into PDF
watermark_str = "watermark" + str(images.index(image)) + '.pdf'
imgDoc = canvas.Canvas(watermark_str)
# Draw image on Canvas and save PDF in buffer
# define the aspect ratio first
aspect = height / float(width)
## Drawing the image
imgDoc.drawImage(image, 0,0, width = im_width, height = (im_width * aspect)) ## at (399,760) with size 160x160
imgDoc.showPage()
imgDoc.save()
# Get the watermark file just created
watermark = PdfFileReader(open(watermark_str, "rb"))
#Get our files ready
pdf1File = open('sample.pdf', 'rb')
page = PdfFileReader(pdf1File).getPage(0)
page.mergePage(watermark.getPage(0))
#Save the result
output.addPage(page)
output.write(file("output.pdf","wb"))
#The function which searches the current directory for image files.
def image_search():
found_images = []
for doc in os.listdir(os.curdir):
image_ext = ['.jpg', '.png', '.PNG', '.jpeg', '.JPG']
for ext in image_ext:
if doc.endswith(ext):
found_images.append(doc)
return found_images
main()
I also tried scaling and specifying the aspect ratio using the im_width variable, which gave the same output.
After a little bit of confusion about your goal I figured out that the goal is to make a PDF overview of the images in the current folder. To do so we actual don't need PyPDF2 as Reportlab offers everything we need for this.
See the code below with the comments as guidelines:
def main():
output_file_loc = "overview.pdf"
imgDoc = canvas.Canvas(output_file_loc)
imgDoc.setPageSize(A4) # This is actually the default page size
document_width, document_height = A4
images = image_search()
for image in images:
# Open the image file to get image dimensions
Image_file = Image.open(image)
image_width, image_height = Image_file.size
image_aspect = image_height / float(image_width)
# Determine the dimensions of the image in the overview
print_width = document_width
print_height = document_width * image_aspect
# Draw the image on the current page
# Note: As reportlab uses bottom left as (0,0) we need to determine the start position by subtracting the
# dimensions of the image from those of the document
imgDoc.drawImage(image, document_width - print_width, document_height - print_height, width=print_width,
height=print_height)
# Inform Reportlab that we want a new page
imgDoc.showPage()
# Save the document
imgDoc.save()

Categories