8
$\begingroup$

Version 11.2 has a new import/export format PythonExpression.

Unfortunately, it doesn't work out-of-the-box with images:

enter image description here

And using the ImageData directly is too slow:

enter image description here

Anyhow, I have some image processing functionality in Python, my question is how can I use ExternalEvaluate to call my function on an image from within Mathematica?

Here's the naive approach (which clearly fails at ToString):

script = FileNameJoin[{$TemporaryDirectory, "functions.py"}];
Export[script, "
  from scipy import misc

  def process_image(img):
    new_img = img # process the image with python
    return misc.imresize(new_img, (20,20), interp='bilinear')

  ", "Text"];
session = StartExternalSession["Python"];
ExternalEvaluate[session, File[script]];

img = ExampleData[{"TestImage", "Mandrill"}];
ExternalEvaluate[session, "img = " <> ExportString[img, {"Base64", "PNG"}]] (*fixme*)
ExternalEvaluate[session, "process_image(img)"]

enter image description here

$\endgroup$
4
  • 1
    $\begingroup$ Try ExportString as PNG. Presumably scipy can import that data (I believe PIL can import from PNG string). $\endgroup$
    – b3m2a1
    Sep 19 '17 at 0:48
  • $\begingroup$ @b3m2a1 I'm not sure that would be efficient or simple $\endgroup$
    – M.R.
    Sep 19 '17 at 2:53
  • 1
    $\begingroup$ I mean you could export to file? But this is one of the major flaws Szabolcs identified with ExternalEvaluate. Can't pass these things in memory. $\endgroup$
    – b3m2a1
    Sep 19 '17 at 2:55
  • 2
    $\begingroup$ This may be worth trying again with v12, there have been some upgrades to this area. $\endgroup$
    – Carl Lange
    Apr 26 '19 at 8:50
2
$\begingroup$

Here I successfully received, decode and show the image with the help of io, PIL, base64 libraries (PIL should be installed):

img = ExampleData[{"TestImage", "House"}];

session = StartExternalSession["Python"];

ExternalEvaluate[session, 
  "import io;from PIL import Image;import base64;"];

ExternalEvaluate[session, 
 "img = " <> 
  ExportString[ExportString[img, {"Base64", "PNG"}], 
   "PythonExpression"] <> ";"] 

ExternalEvaluate[session, "image = Image.open(io.BytesIO(base64.b64decode(img)));image.show();"]

DeleteObject[session]

Because there is \n in ExportString[img, {"Base64", "PNG"}], you could also use ''' (triple quotes):

ExternalEvaluate[session, 
 "img = '''" <> ExportString[img, {"Base64", "PNG"}] <> "''';"]
$\endgroup$

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.