0

Using pyscript it's easy to load in raw data from GitHub, like in the intro tutorial where you read in a Pandas DataFrame like so:

url = (
    "https://raw.githubusercontent.com/Cheukting/pyscript-ice-cream/main/bj-products.csv"
)
ice_data = pd.read_csv(open_url(url))

I would like to do something similar, but load in a jpg file and plot it using matplotlib. Would someone be able to help me understand what I should be doing here? I am very new to using pyscript.

I would think that the code required to do that would look something like the below, but I haven't been able to get anything working.

from pyodide.http import open_url
import matplotlib.pyplot as plt
from PIL import Image

fig, ax = plt.subplots(figsize=(15, 15))

image = Image.open(open_url("https://raw.githubusercontent.com/path/to/img.jpg"))
ax.imshow(image)
display(fig, target="graph-area", append=False)
  • 1
    Use `requests.get()` and `BytesIO` like this https://stackoverflow.com/a/64716673/2836621 but pass the `BytesIO` to `Image.open()` – Mark Setchell Mar 12 '23 at 23:36

3 Answers3

1

This should do the trick, as Mark proposed

import requests
from io import BytesIO
from PIL import Image
import matplotlib.pyplot as plt

req = requests.get(
    "https://github.com/opencv/opencv/blob/4.x/doc/images/meanshift_basics.jpg?raw=true"
)

image = Image.open(BytesIO(req.content))

plt.imshow(image)

Klops
  • 951
  • 6
  • 18
  • Thanks for the quick response, based on what searching I've done I don't think that you can use the `requests` library within `pyscript` though. Please correct me if I'm wrong – Justin Essert Mar 13 '23 at 23:32
  • I have never used pyscript before, sorry – Klops Mar 14 '23 at 01:23
  • @JustinEssert You're correct, the stdlib library `requests` doesn't work in PyScript/Pyodide. However, the `pyodide-http` library patches some of the main functions of `requests` to allow for some interoperability - see, for instance, this example from the PyScript docs: https://docs.pyscript.net/latest/tutorials/requests.html – Jeff Glass Mar 20 '23 at 02:40
0

This code seems to work in the online version of pyodide:

from pyodide.http import open_url
import matplotlib.pyplot as plt
from PIL import Image
import io

img = await pyodide.http.pyfetch("https://raw.githubusercontent.com/pyodide/pyodide/main/docs/_static/img/pyodide-logo-readme.png")
res = await img.bytes()
iobuf = io.BytesIO(res)
image = Image.open(iobuf)

ax.imshow(image)
display(fig, target="graph-area", append=False)

The idea was that you have to get files (pyfetch was recommended by the pyodide documentation), then you have to wait for all the coroutines and wrap the bytes into an io.BytesIO, in order to be read like a file.

Edit: The last part of the code is taken from your example, but won't work, because display seems not to be bound to anything. ax.imshow should plot the image in a gui environment of pyodide.

TachyonicBytes
  • 700
  • 1
  • 8
0

Thanks TachyonicBytes, I was able to get that work in the most recent pyscript version by doing the following

import asyncio
from pyodide.http import pyfetch
from PIL import Image
import matplotlib.pyplot as plt
import io

async def plot_image(url):
    img = await pyfetch(url)
    res = await img.bytes()
    iobuf = io.BytesIO(res)
    image = Image.open(iobuf)
    fig, ax = plt.subplots(figsize=(15, 15))
    ax.imshow(image)

    display(fig, target="graph-area", append=False)

asyncio.ensure_future(plot_image(url))