Python decoding of particular image - python

I am trying to decode and display a particular image format for a planetary image encoded according the PDS standard. I am using Pillow and I need to implement a bit decoder but after various attempts I have no good results. Could anyone help me to implement this particular Pillow decoder? I would provide more information when needed
For sure, I will provide information of the encoding for the PDS file I want to use. These are the important lines from the header of the file :
POINTERS TO DATA OBJECTS
BROWSE_IMAGE= = 20480 <BYTES>
IMAGE = 53248 <BYTES>
OBJECT DESCRIPTION
OBJECT = IMAGE
FIRST_LINE = 1
LINE_PREFIX_BYTES = 0
LINE_SUFFIX_BYTES = 0
LINES = 1024
LINE_SAMPLES = 1024
SAMPLE_TYPE = MSB_UNSIGNED_INTEGER
SAMPLE_BITS = 16
SAMPLE_BIT_MASK = "2#0000001111111111#"
END_OBJECT = IMAGE
Is that clear enough? that is the part of the header defining the encoding method of the image. The whole file contains both the header and the image itself. I obviously need a pillow decoder, and precisely a bit decoder, but mine does not work.
And this will be my code for the bit decoder:
from PIL import Image, ImageFile
class DarkImageFile( ImageFile.ImageFile ) :
format = 'IMG'
format_description = 'IMG dark frame'
def _open( self ) :
self.size = (1024,1024)
self.mode = 'F' # data representation mode
self.tile = [ ("bit", ( 0,0 ) + self.size, 53248, (10,6, 0, 3) ) ]
Image.register_open( "IMG", DarkImageFile )
Image.register_extension( "IMG", ".img" )

Related

How to use from_tensor_slices properly on MRI images?

I'm working with MRI images and I'd like to use from_tensor_slices to preprocess the paths but I don't know how to use that properly. Below are my code, the problem message and link for the dataset.
First I rearrange my data. 484 images and 484 labels
image_data_path = './drive/MyDrive/Brain Tumour/Task01_BrainTumour/imagesTr/'
label_data_path = './drive/MyDrive/Brain Tumour/Task01_BrainTumour/labelsTr/'
image_paths = [image_data_path + name
for name in os.listdir(image_data_path)
if not name.startswith(".")]
label_paths = [label_data_path + name
for name in os.listdir(label_data_path)
if not name.startswith(".")]
image_paths = sorted(image_paths)
label_paths = sorted(label_paths)
Then, the function to load 1 example (I use nibabel to load nii files)
def load_one_sample(image_path, label_path):
image = nib.load(image_path).get_fdata()
image = tf.convert_to_tensor(image, dtype = 'float32')
label = nib.load(label_path).get_fdata()
label = tf.convert_to_tensor(label, dtype = 'uint8')
return image, label
Next, I tried using from_tensor_slices
image_filenames = tf.constant(image_paths)
label_filenames = tf.constant(label_paths)
dataset = tf.data.Dataset.from_tensor_slices((image_filenames, label_filenames))
all_data = dataset.map(load_one_sample)
And the error comes: TypeError: stat: path should be string, bytes, os.PathLike or integer, not Tensor
What can be wrong and how can I fix it?
Datalink: https://drive.google.com/drive/folders/1HqEgzS8BV2c7xYNrZdEAnrHk7osJJ--2 (task 1 - Brain Tumour)
Please tell me if you need more information.
nib.load is not a TensorFlow function.
If you want to use anything in tf.data pipeline that is not a TensorFlow function then you have to wrap it using a tf.py_function.
Code:
image_data_path = 'Task01_BrainTumour/imagesTr/'
label_data_path = 'Task01_BrainTumour/labelsTr/'
image_paths = [image_data_path + name
for name in os.listdir(image_data_path)
if not name.startswith(".")]
label_paths = [label_data_path + name
for name in os.listdir(label_data_path)
if not name.startswith(".")]
image_paths = sorted(image_paths)
label_paths = sorted(label_paths)
def load_one_sample(image_path, label_path):
image = nib.load(image_path.numpy().decode()).get_fdata()
image = tf.convert_to_tensor(image, dtype = 'float32')
label = nib.load(label_path.numpy().decode()).get_fdata()
label = tf.convert_to_tensor(label, dtype = 'uint8')
return image, label
def wrapper_load(img_path, label_path):
img, label = tf.py_function(func = load_one_sample, inp = [img_path, label_path], Tout = [tf.float32, tf.uint8])
return img, label
dataset = tf.data.Dataset.from_tensor_slices((image_paths, label_paths)).map(wrapper_load)
The error is not due to the from_tensor_slices function but arises as nibs.load is expecting a string but gets a tensor.
However, a better way would be to create tfrecords and use them to train the model.

Load image on python CheckListCtrl with transparency

I'm starting to use WX GUI on python, and on my "Hello Word" project I'm trying to create a program with the ability to read any image and show it as icon into a CheckListCtrl column. I've done the first part (read the image and draw it into the CheckListCtrl), but I'm not able to load a PNG image and keep the transparency on that icon.
My code is the following:
'''
17 June 2018
#autor: Daniel Carrasco
'''
import wx
from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
import sys
from pathlib import Path
BACKGROUNDCOLOR = (240, 240, 240, 255);
class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER,
size=wx.Size(395, 467), pos=wx.Point(10, 20));
CheckListCtrlMixin.__init__(self);
ListCtrlAutoWidthMixin.__init__(self);
#====================================================================
class MainFrame(wx.Frame):
def __init__(self, *args, **kwargs):
self.dataFolder = {
"images": Path("images/")
}
wx.Frame.__init__(self, *args, **kwargs);
icon = wx.Icon("icons.ico", wx.BITMAP_TYPE_ICO)
self.SetIcon(icon);
self.createWidgets();
self.createButtons();
self.Show();
#----------------------------------------------------------
def exitGUI(self, event): # callback
self.Destroy();
#----------------------------------------------------------
def createWidgets(self):
self.CreateStatusBar(); # wxPython built-in method
self.createMenu();
# Creamos el panel
boxSizer = wx.BoxSizer();
panel = wx.Panel(self);
panel.SetBackgroundColour(BACKGROUNDCOLOR);
panel.SetSizerAndFit(boxSizer);
staticBox = wx.StaticBox( panel, -1, "Listado de Saves", size=(415, 500),
pos=wx.Point(5, 0) )
self.statBoxSizerV = wx.StaticBoxSizer(staticBox, wx.VERTICAL)
# Lista de items
self.itemList = CheckListCtrl(staticBox);
self.itemList.InsertColumn(0, '', width=32);
self.itemList.InsertColumn(1, 'Icono', width=52);
self.itemList.InsertColumn(2, 'Título', width=140);
self.il_Small = self.itemList.GetImageList(wx.IMAGE_LIST_SMALL);
self.il = wx.ImageList(48, 48, wx.IMAGE_LIST_SMALL);
self.itemList.SetImageList(self.il, wx.IMAGE_LIST_SMALL);
image = wx.Image(str(self.dataFolder["images"] / "tick_1.png"), wx.BITMAP_TYPE_ANY);
self.il.Add(wx.Bitmap(image));
image = wx.Image(str(self.dataFolder["images"] / 'tick_2.png'), wx.BITMAP_TYPE_ANY);
self.il.Add(wx.Bitmap(image));
image = wx.Image(str(self.dataFolder["images"] / 'exit.png'), wx.BITMAP_TYPE_ANY );
for x in range(0, 4):
for y in range(0, 4):
image.SetAlpha(x, y, 0);
image = image.Scale(40, 40, wx.IMAGE_QUALITY_HIGH);
image = image.Size(wx.Size(48,48), wx.Point(4,4), 255, 255, 255);
# image.ClearAlpha();
self.il.Add(wx.Bitmap(image));
image = wx.Image(str(self.dataFolder["images"] / 'test.png'), wx.BITMAP_TYPE_ANY );
image = image.Scale(40, 40, wx.IMAGE_QUALITY_HIGH);
image = image.Size(wx.Size(48,48), wx.Point(4,4), 255, 255, 255);
self.il.Add(image.ConvertToBitmap());
index = self.itemList.InsertItem(sys.maxsize, "test");
self.itemList.SetItemColumnImage(0, 1, 3)
#self.itemList.Append("Prueba");
#----------------------------------------------------------
def createButtons(self):
pass
#----------------------------------------------------------
def createMenu(self):
# Menú Archivo
APP_EXIT = 1;
mArchivo = wx.Menu();
qmi = wx.MenuItem(mArchivo, APP_EXIT, '&Salir\tCtrl+Q');
image = wx.Image(str(self.dataFolder["images"] / 'exit.png'),wx.BITMAP_TYPE_PNG);
image = image.Scale(16, 16, wx.IMAGE_QUALITY_HIGH);
qmi.SetBitmap(image.ConvertToBitmap());
mArchivo.Append(qmi);
self.Bind(wx.EVT_MENU, self.exitGUI, id=APP_EXIT);
# Barra de menús
menuBar = wx.MenuBar();
menuBar.Append(mArchivo, "&Archivo");
# Seteamos la barra de menús
self.SetMenuBar(menuBar);
#======================
# Start GUI
#======================
app = wx.App()
MainFrame(None, style= wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX, title="Savegame Linker", size=(485,587))
app.MainLoop()
This code just read the image into and Image object, then scale the image and add a border resizing. The problem is that PNG transparency is not kept and only the border is transparent:
If I remove the image transparency with Photoshop (adding white background), then the image is showed with the transparency I want:
Is there any way to keep the PNG transparency on CheckListCtrl, or at least add a white background to the image (that looks like an alternative solution). I want to do it if posible using only WX, because I think that use pillow module for example, just for remove transparency, is not an optimal solution.
Thanks!!
I don't know how you run that code but try as I might, I have been unable to do so and thus cannot be sure of the answer below.
A wx.Image has a range of "image handlers", of which, only the BMPHandler is loaded by default. I suspect that you need to load the PNGHandler before attempting SetAlpha and you should probably check the image with HasAlpha beforehand.
See: https://docs.wxpython.org/wx.Image.html
Alpha channel support
Starting from wxWidgets 2.5.0 wx.Image supports alpha channel data, that is in addition to a byte for the red, green and blue colour components for each pixel it also stores a byte representing the pixel opacity. An alpha value of 0 corresponds to a transparent pixel (null opacity) while a value of 255 means that the pixel is 100% opaque. The constants IMAGE_ALPHA_TRANSPARENT and IMAGE_ALPHA_OPAQUE can be used to indicate those values in a more readable form. While all images have RGB data, not all images have an alpha channel. Before using wx.Image.GetAlpha you should check if this image contains an alpha channel with wx.Image.HasAlpha . Currently the BMP, PNG, TGA, and TIFF format handlers have full alpha channel support for loading so if you want to use alpha you have to use one of these formats. If you initialize the image alpha channel yourself using wx.Image.SetAlpha , you should save it in either PNG, TGA, or TIFF format to avoid losing it as these are the only handlers that currently support saving with alpha.
Available image handlers The following image handlers are
available. BMPHandler is always installed by default. To use other
image formats, install the appropriate handler with
wx.Image.AddHandler or call wx.InitAllImageHandlers .
BMPHandler: For loading (including alpha support) and saving, always
installed.
wx.PNGHandler: For loading and saving. Includes alpha
support.
wx.JPEGHandler: For loading and saving.
wx.GIFHandler: For loading and saving (see below).
wx.PCXHandler: For loading and saving (see below).
wx.PNMHandler: For loading and saving (see below).
wx.TIFFHandler: For loading and saving. Includes alpha support.
wx.TGAHandler: For loading and saving. Includes alpha support.
wx.IFFHandler: For loading only. wx.XPMHandler: For loading and saving.
ICOHandler: For loading and saving. CURHandler: For loading and saving.
ANIHandler: For loading only.
When saving in PCX format, wx.PCXHandler will count the number of different colours in the image; if there are 256 or less colours, it will save as 8 bit, else it will> save as 24 bit. Loading PNMs only works for ASCII or raw RGB images.
When saving in PNM format, wx.PNMHandler will always save as raw RGB.
Saving GIFs requires images of maximum 8 bpp (see Quantize ), and the
alpha channel converted to a mask (see wx.Image.ConvertAlphaToMask ).
Saving an animated GIF requires images of the same size (see
wx.GIFHandler.SaveAnimation )
See also wx.Bitmap, wx.InitAllImageHandlers , PixelData
I think that the right way is converting the transparency into mask. I've already tested it, but looks like I've used the function after other that made it fail.
image = wx.Image(str(self.dataFolder["images"] / 'test.png'), wx.BITMAP_TYPE_ANY );
image = image.Scale(40, 40, wx.IMAGE_QUALITY_HIGH);
image.ConvertAlphaToMask(threshold=50);
image = image.Size(wx.Size(48,48), wx.Point(4,4), 255, 255, 255);
self.il.Add(image.ConvertToBitmap());
The last time I'd tried the function was after the image.Size function, and then it fails (maybe the Size function removes the transparency), but if is done before then works.
Thanks again and greetings!!
EDIT:
A few months later I've continued the project and I've found another way to make the background transparent: Remove the transparency converting it to solid white:
def remove_transparency(im, bg_colour=(255, 255, 255)):
# Only process if image has transparency (http://stackoverflow.com/a/1963146)
if im.mode in ('RGBA', 'LA') or (im.mode == 'P' and 'transparency' in im.info):
# Need to convert to RGBA if LA format due to a bug in PIL (http://stackoverflow.com/a/1963146)
alpha = im.convert('RGBA').split()[-1]
# Create a new background image of our matt color.
# Must be RGBA because paste requires both images have the same format
# (http://stackoverflow.com/a/8720632 and http://stackoverflow.com/a/9459208)
bg = Image.new("RGBA", im.size, bg_colour + (255,))
bg.paste(im, mask=alpha)
return bg
else:
return im
# Open the image
sbuf = BytesIO(campo[4])
im = Image.open(sbuf)
# Remove transparency (white background will be transparent on ImageList)
im2 = remove_transparency(im).convert("RGB")
im.close()
# Create an wx.Image from image
width, height = im2.size
image = wx.Image(width, height, im2.tobytes())
image = image.Size(wx.Size(48,48), wx.Point(2,2), 255, 255, 255)
# Convert it to Bitmap and add it to ImageList
image = image.ConvertToBitmap()
icon_image = self.il.Add(image)
sbuf.close()
I've changed slightly the way I store the images, and now they comes from a PNG stored on an SQLite DB BLOB (campo[4]).
Greetings!!

NAO fails to save captured image to local computer

I'm trying to save a captured 640x480 RGB image with NAO's front camera to my computer. I'm using python and PIL to do so. Unfortunately, the image just won't save on my computer, no matter what image type or path I use for the parameters of the Image.save()- Method. the image created with PIL contains valid RGB-information though. Here's my code sample from choregraphe:
import Image
def onInput_onStart(self):
cam_input = ALProxy("ALVideoDevice")
nameId = cam_input.subscribeCamera("Test_Cam", 1, 2, 13, 20)
image = cam_input.getImageRemote(nameId) #captures an image
w = image[0] #get the image width
h = image[1] #get the image height
pixel_array = image[6] #contains the image data
result = Image.fromstring("RGB", (w, h), pixel_array)
#the following line doesnt work
result.save("C:\Users\Claudia\Desktop\NAO\Bilder\test.png", "PNG")
cam_input.releaseImage(nameId)
cam_input.unsubscribe(nameId)
pass
Thank you so much for your help in advance!
- a frustrated student
In the comment, you say the code is pasted from choregraphe, so I guess you launch it using choregraphe.
If so, then the code is injected into your robot then started.
So your image is saved to the NAO hard drive and I guess your robot doesn't have a folder named: "C:\Users\Claudia\Desktop\NAO\Bilder\test.png".
So change the path to "/home/nao/test.png", start your code, then log into your NAO using putty or browse folder using winscp (as it looks like you're using windows).
And you should see your image-file.
In order for your code to run correctly it needs to be properly indented. Your code should look like this:
import Image
def onInput_onStart(self):
cam_input = ALProxy("ALVideoDevice")
nameId = cam_input.subscribeCamera("Test_Cam", 1, 2, 13, 20)
image = cam_input.getImageRemote(nameId) #captures an image
w = image[0] #get the image width
h = image[1] #get the image height
pixel_array = image[6] #contains the image data
...
Make sure to indent everything that's inside the def onInput_onStart(self): method.
Sorry for the late response, but it maybe helpful for someone. You should try it with naoqi. Here is the documentation for retriving images
http://doc.aldebaran.com/2-4/dev/python/examples/vision/get_image.html
The original code was not working for me so I made some tweeks.
parser = argparse.ArgumentParser()
parser.add_argument("--ip", type=str, default="nao.local.",
help="Robot IP address. On robot or Local Naoqi: use
'nao.local.'.")
parser.add_argument("--port", type=int, default=9559,
help="Naoqi port number")
args = parser.parse_args()
session = qi.Session()
try:
session.connect("tcp://" + args.ip + ":" + str(args.port))
except RuntimeError:
pass
"""
First get an image, then show it on the screen with PIL.
"""
# Get the service ALVideoDevice.
video_service = session.service("ALVideoDevice")
resolution = 2 # VGA
colorSpace = 11 # RGB
videoClient = video_service.subscribe("python_client",0,3,13,1)
t0 = time.time()
# Get a camera image.
# image[6] contains the image data passed as an array of ASCII chars.
naoImage = video_service.getImageRemote(videoClient)
t1 = time.time()
# Time the image transfer.
print ("acquisition delay ", t1 - t0)
#video_service.unsubscribe(videoClient)
# Now we work with the image returned and save it as a PNG using ImageDraw
# package.
# Get the image size and pixel array.
imageWidth = naoImage[0]
imageHeight = naoImage[1]
array = naoImage[6]
image_string = str(bytearray(array))
# Create a PIL Image from our pixel array.
im = Image.fromstring("RGB", (imageWidth, imageHeight), image_string)
# Save the image.
im.save("C:\\Users\\Lenovo\\Desktop\\PROJEKTI\\python2-
connect4\\camImage.png", "PNG")
Be careful to use Python 2.7.
The code runs on your computer not the NAO robot!

Trying to convert PDF to Jpg with Wand, but pdf is not being recognized

I am trying to convert a PDF to a JPG using wand.
I would like to adjust the size of the jpg based on the docHeight, which is a global variable.
The size of the jpg would be determined by the max dimension's ratio with the target page it will be placed on.
I seem to be failing right from the starting gate, and I cannot figure out why.
It seems the file is not being read in my with statement.
my with Image statement returns
>>>>with Image(filename = thumbOriginal, resolution = (RESOLUTION,RESOLUTION)) as img:
print img
'NoneType' object has no attribute '__getitem__'
What is wrong with how I am reading the file?
it is mostly borrowed from this question. I can barely find any info on how to properly make this conversion.
with Image(filename = thumbOriginal, resolution = (RESOLUTION,RESOLUTION)) as img:
print img # prints 'NoneType' object has no attribute '__getitem__'
img_width = img.width
print "img_width: "+str(img_width) # prints 0 if I comment out "print img" statement
img_height = img.height
print "img_height: "+str(img_height) # prints 0 if I comment out "print img" statement
if img_width > img_height:
ratio = float(dest_width / img_width) # Fails for float divided by 0 if I comment out "print img" statement
else: ratio = float(dest_height / img_height) # Fails for float divided by 0 if I comment out "print img" statement
img.resize(int(ratio*img_width), int(ratio *img.height))
img.alpha_channel = False
img.format = 'jpg'
img.save(filename = thumb)
I've also tried a simpler version I found on a different stackoverflow question:
with Image(filename = thumbOriginal, resolution = 300) as img:
print img
img.compression_quality = 99
img.save(filename=thumb)
but am getting the same error
'NoneType' object has no attribute '__getitem__'
I know that the pdf is there. I can open it manually and it works just fine.
I have also tried removing the resolution argument altogether with no luck.
When I include a ...
print thumbOriginal
.... statement, it returns the correct and complete file path.
img is not a string, it is an Image object (look at the Wand source code to understand). When you try to print an Image object python has no idea how to do that. When you say:
print thumbObject
you have defined this (ostensibly) as a path to a filename which is a string. The print method knows how to print a string.
I think if you try the below code you'll have better luck. Notice that I specified resolution:
with Image(filename=thumbOriginal, resolution=300) as img:
img_width = img.width
print "img_width: "+str(img_width)
img_height = img.height
print "img_height: "+str(img_height)
if img_width > img_height:
ratio = float(dest_width / img_width)
else: ratio = float(dest_height / img_height)
img.resize(int(ratio*img_width), int(ratio *img.height))
img.alpha_channel = False
img.format = 'jpg'
img.save(filename = thumb)

Python PIL - All areas of PNG with opacity > 0 have their opacity set to 1

Imagine a red circle with a black dropshadow that fades away on top of a fully transparent background. When I open and resave the image with PIL the background remains fully transparent but the dropshadow becomes full black.
The problem appears without even altering the image:
image = Image.open('input.png')
image = image.convert('RGBA')
image.save('output.png')
I want to keep the image looking exactly as the original so that I can crop or resize it.
EDIT: Here's a PNG that demonstrates the effect. It was converted to 8bit by using PNGNQ.
When using the above Python code it comes out as the following:
It looks like PIL currently doesn't support full alpha for PNG8.
There is a patch here for read-only support: http://mail.python.org/pipermail/image-sig/2010-October/006533.html
If you're feeling naughty, you could monkeypatch PIL:
from PIL import Image, ImageFile, PngImagePlugin
def patched_chunk_tRNS(self, pos, len):
i16 = PngImagePlugin.i16
s = ImageFile._safe_read(self.fp, len)
if self.im_mode == "P":
self.im_info["transparency"] = map(ord, s)
elif self.im_mode == "L":
self.im_info["transparency"] = i16(s)
elif self.im_mode == "RGB":
self.im_info["transparency"] = i16(s), i16(s[2:]), i16(s[4:])
return s
PngImagePlugin.PngStream.chunk_tRNS = patched_chunk_tRNS
def patched_load(self):
if self.im and self.palette and self.palette.dirty:
apply(self.im.putpalette, self.palette.getdata())
self.palette.dirty = 0
self.palette.rawmode = None
try:
trans = self.info["transparency"]
except KeyError:
self.palette.mode = "RGB"
else:
try:
for i, a in enumerate(trans):
self.im.putpalettealpha(i, a)
except TypeError:
self.im.putpalettealpha(trans, 0)
self.palette.mode = "RGBA"
if self.im:
return self.im.pixel_access(self.readonly)
Image.Image.load = patched_load
Image.open('kHrY6.png').convert('RGBA').save('kHrY6-out.png')
I think that the problem has been somewhat resolved, but is it possible that you need to set the depth of the alpha channel?

Categories