gorro
gorro

Reputation: 41

PythonMagick data extraction for JPEG2000

I am working in an application which (among other things) need to read a satellite image (with only one band per image) and process the pixel data.

The format is JPEG-2000 and therefore I cannot use the PIL library (which simplifies everything). I have found the PythonMagick library and I can perfectly read the image and extract the value of the pixel. But only for one pixel!

im=PythonMagick.Image(dirimage)      # (This is very slow....)
a=im.pixelColor(j-1,i-1).intensity() # the value intensity is extracted for one pixel
a=a/int(XML_var[37][2])              # the reflectance values are normalised to the range [0,1]

Therefore, I need a for-loop to get all the pixel values (the images are very large). I tried with Blob function to get the data but it crashes.

Are there any better options? How could I quickly get the pixel data of a JPEG2000 image and save it into an array?

Upvotes: 1

Views: 2503

Answers (3)

Sjieke
Sjieke

Reputation: 412

I downloaded Kakadu (free software for non commercial purposes) and I use the module kdu_expand.

os.system('kdu_expand -i image.jp2 -o temp_image.tif')

Slight off-topic comment for those running the Kakadu (KDU) demo. Would like to add that if running kdu_expand, like above: os.system('kdu_expand -i image.jp2 -o temp_image.tif') and this gives you an error:

dyld: Library not loaded: /usr/local/lib/libkdu_v78R.dylib
  Referenced from: /usr/local/bin/kdu_expand
  Reason: no suitable image found.  Did find:
    /usr/local/lib/libkdu_v78R.dylib: open() failed with errno=13
    /usr/local/lib/libkdu_v78R.dylib: open() failed with errno=13
Trace/BPT trap: 5

Check the permissions of libkdu_v78R.dylib and change them to 644 or 666, or something with read/write access.

Upvotes: 0

gorro
gorro

Reputation: 41

The answer you gave me is great and extract perfectly the pixel information (changing uint8 to uint16). However, the values I obtain are higher than the real ones. There is an offset and because of the LOSSY compression in JPEG2000 there is a little error of 1 or 2 in the value.

I don't like to use external calls but in this case I found this as a better and faster solution:

I downloaded Kakadu (free software for non commercial purposes) and I use the module kdu_expand.

os.system('kdu_expand -i image.jp2 -o temp_image.tif')

im=PIL.Image.open('temp_image.tif')

pixels=array(im.getdata()).reshape((im.size[0], im.size[1]))

I convert the image from JPEG2000 to TIF but it is quick and the static memory is not usually a limitation (nowadays) in a computer. Then, the PIL library perfectly manages to extarct the data.

Note: I tried the conversion straight with PythonMagick but it gives me the same offset as before

Note 2: I found another interesting library in OpenCV but the result is incorrect

pixels_cv2=cv2.imread('image.jp2',0)

Note3: The images I used are satellite images codified with 12 bites. Possibly in other type of data the PythonMagick behaves better.

Upvotes: 2

cgohlke
cgohlke

Reputation: 9437

Using a Blob should work:

import numpy
from PythonMagick import Image, Blob

i = Image('http://www.microimages.com/gallery/jp2/potholes2.jp2')
b = Blob()
i.write(b, 'GRAY')
a = numpy.fromstring(b.data, 'uint8').reshape((i.rows(), i.columns()))

Upvotes: 2

Related Questions