10
$\begingroup$

It is easy to see that NumericArray is a construct underlying Image:

img = Import["ExampleData/coneflower.jpg", IncludeMetaInformation -> None];
ResourceFunction["ShortInputForm"][img]

output

At the same time, unlike Image, we can directly manipulate NumericArray using such handy functions as Part, Flatten etc. Of course, we can convert Image into a packed array using ImageData, but resulting array will occupy much more memory than the original image:

ByteCount /@ {img, ImageData[img, "Byte"]}
{55248, 407016}

The function ShortInputForm uses a hack identical to the Nucleus function by Carl Woll for accessing the internal structure of atomic objects. This hack allows extracting the NumericArray:

Nucleus[img][[1]]

output

But of course it would be much better to have a non-hackish way to do this, which wouldn't depend on undocumented details of implementation of LinkWrite and LinkRead, and hopefully would also be more efficient.

Hence my question: What is the idiomatic way to extract NumericArray from Image?

$\endgroup$
4
  • 4
    $\begingroup$ Like any NoEntryQ object you can grab its parts all you want via Replace[img, _[x_, ___] :> x], but that's hardly idiomatic is it? I would think you are unlikely to find a builtin solution that doesn't have the words "Private" or "Internal" in the function name. $\endgroup$
    – Jason B.
    May 23 at 19:50
  • $\begingroup$ @JasonB. I will be happy also with a function from the Internal` context. At least, do not define a special hackish function for such a basic task... $\endgroup$ May 23 at 19:52
  • $\begingroup$ @JasonB. Replace[img, _[x_, ___] :> x] could be an acceptable solution, thank you! You can post this as an answer. $\endgroup$ May 23 at 19:56
  • 1
    $\begingroup$ the Replace method I think is a bit heavy handed so I posted a couple of other methods. $\endgroup$
    – Jason B.
    May 23 at 20:48

1 Answer 1

11
$\begingroup$

I think this is the most idiomatic way to get the image data as a numeric array:

In[141]:= img = Import["ExampleData/coneflower.jpg", IncludeMetaInformation -> None];

In[143]:= NumericArray[ImageData[img, "Byte"]] // OutputForm

Out[143]//OutputForm= NumericArray[<113,150,3>, UnsignedInteger8]

This does require recreating the NumericArray object from the image data, so has that level of inefficiency.

If you were to go spelunking, by calling PrintDefinitions on Image to see the formatting value, you would see the suggestively named Image`InternalImageData. Being the curious type, you would find it gives the same data as above

In[147]:= SameQ[%143, Image`InternalImageData[img]]

Out[147]= True

All the usual caveats about undocumented functionality apply (namely that this internal function could disappear in a future release).

$\endgroup$
1
  • $\begingroup$ Excellent. I would add that Image`InternalImageData accepts the usual option Interleaving, what is also very handy. For example: Image`InternalImageData[img, Interleaving -> True]. Also it accepts the option DataReversed. $\endgroup$ May 24 at 4:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.