Images are not displayed after altering

So I want to display images as hoverdata to a graph.
This works quite well(although a bit slow) if I do it with an app callback the following way:

    #getting the path of the image
    image=image_dict[ID]
    #base64 encode the image
    encoded=base64.b64encode(open(image, 'rb').read())
    return 'data:image/png;base64,{}'.format(encoded.decode())

Since each image is the source of multiple datapoints on the graph I want to mark the region the of the image
the datapoint is taken from.
I can manipulate a region of the image quite simply this way:

    image=image_dict[ID]
    #base64 encode the image   
    
    #testcode
    #reading the image as np array
    img=imageio.imread(image)
    #getting x and y coordinates from the data table,
    x_coord=int(data[data['unique_time']==ID_or]['Location_Center_X'].values)
    y_coord=int(data[data['unique_time']==ID_or]['Location_Center_Y'].values)
    #manipulating a range of pixels around the center into being green
    img[y_coord-5:y_coord+5, x_coord-5:x_coord+5]=[0, 255, 0]
    encoded=base64.b64encode(img)
    print('encoding complete')
    return 'data:image/png;base64,{}'.format(encoded.decode()) 

However the image is not displayed. No error message is given, just a blank box appears.
I suspected that it was just very slow , and therefore took time, but eventually any sign of activity in either the browser or the terminal stops and it still is not displayed.
The print argument (‘encoding complete’) also is displayed basically instantaneously. So the code does run until that point. just the image is not displayed.
Does anybody know what is going wrong here and how to fix it?

Also tips about how to handle images faster would be appreciated.

So I tried a couple more things.
I looked into the data type that I get with

open(image, 'rb').read()

which is a bytes object.
So I figured, to get the same output with the second type of code, I would first need to change the np array to a bytes object as well.
However, when I do this I never get the same bytes object as when I use the open method:

(io.BytesIO(imageio.imread(img_path))).getvalue()[0:20]
Out[70]: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

(imageio.imread(img_path)).tobytes()[0:20]
Out[71]: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

(open(img_path, 'rb').read())[0:20]
Out[72]: b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x04\x00'

Why is this? How can I get the same output as with open.read()? is this even the right approach?

edit: this definitely is the right approach as saving the altered image and then reloading it does work:

    temp=Image.fromarray(img)
    temp.save('temp.png')
    with open('temp.png', 'rb') as f:
        encoded=base64.b64encode(f.read())

So how can I circumvent this and directly display it, without the need of loading the image twice?

I found a solution

    img=imageio.imread(image)
    #getting x and y coordinates from the data table,
    x_coord=int(data[data['unique_time']==ID_or]['Location_Center_X'].values)
    y_coord=int(data[data['unique_time']==ID_or]['Location_Center_Y'].values)
    #manipulating a range of pixels around the center into being green
    img[y_coord-5:y_coord+5, x_coord-5:x_coord+5]=[0, 255, 0]
    imgByteArr = io.BytesIO()
    img.save(imgByteArr, format='PNG')
    imgByteArr = imgByteArr.getvalue()
    encoded=base64.b64encode(imgByteArr)
    print('encoding complete')
    return 'data:image/png;base64,{}'.format(encoded.decode())