Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Export a Uint8 array as an image using Images in Julia

Tags:

image

julia

I recently asked how to convert Float32 or Uint8 arrays into images in the Images package. I got an answer for the Float32 case, but am still having trouble figuring out how to save a Uint8 array.

As an example, let's create a random Uint8 array using the traditional Matlab scheme where the dimensions are (m,n,3):

array = rand(Uint8, 50, 50, 3);
img = convert(Image, array);

Using the same approach as works for the Float32 case,

imwrite(img, "out.png")

fails with message

ERROR: method 'mapinfo' has no method matching mapinfo(::Type{ImageMagick}, ::Image{Uint8, 3, Image{Uint8, 3, Array{Uint8, 3}}}).

I checked the documentation, and it says

If data encodes color information along one of the dimensions of the array (as opposed to using a ColorValue array, from the Color.jl package), be sure to specify the "colordim" and "colorspace" in properties.

However, inspecting the img object previously created shows that it has colordim = 3 and colorspace = RGB already set up, so this can't be the problem.

I then searched the documentation for all instances of MapInfo. In core.md there is one occurrence:

scalei: a property that controls default contrast scaling upon display. This should be a MapInfo value, to be used for setting the contrast upon display. In the absence of this property, the range 0 to 1 will be used.

But there was no information on what exactly a MapInfo object is, so I looked further, and in function_reference.md it says:

Here is how to directly construct the major concrete MapInfo types:

MapNone(T), indicating that the only form of scaling is conversion to type T. This is not very safe, as values "wrap around": for example, converting 258 to a Uint8 results in 0x02, which would look dimmer than 255 = 0xff.

...

and some other examples. So I tried to specify scalei = MapNone(Uint8) as follows:

img2 = Image(img, colordim = 3, colorspace = "RGB", scalei = MapNone(Uint8));
imwrite(img, "out.png")

but got the same error again.

How do you encode Uint8 image data using Images in Julia?

like image 470
DumpsterDoofus Avatar asked Sep 08 '14 00:09

DumpsterDoofus


1 Answers

You can convert back and forth between arrays of primitive types such as UInt8 and arrays of color types. These conversions are achieved in a unified way via two functions: colorview and channelview.

Example

Convert array of UInt8 to array of RGB:

arr = rand(UInt8, 3, 50, 50)
img = colorview(RGB, arr / 255)

Convert back to channel view:

channelview(img)

Notes

  • In this example the RGB color type requires that the entries of the array live in [0,1] as floating point. I manually converted UInt8 to Float64 using an explicit division by 255. There is probably a more generic way of achieving this result with reinterpret or some other function in Images.jl

  • The colorview and channelview functions assume that the channel dimension is the first dimension of the array. You can use permutedims in case your channels live in a different dimension, or use some function in Images.jl (maybe reinterpretc?) to do it efficiently without memory copies.

like image 108
juliohm Avatar answered Nov 11 '22 01:11

juliohm