0

I get an image from PySide6 Canvas.

Initial Image

I can show it in the browser properly. But while saving this one, I get the black square.

Saved Image

While converting the image into a NumPy array I get correct figures in the array.

Large screenshot of Numpy array

I can't understand what is going wrong while saving image.

I expected to save the image properly but I can't find a way to.

the class code

import numpy as np from PIL import Image, ImageOps from numpy.typing import NDArray from typing import Tuple, Union

THRESHOLD = 100 FINAL_SIZE = 28

class Utils:

@classmethod
def get_formatted_image(cls, pil_im: Image, as_ndarray=True) -> Union[Image.Image, NDArray]:
    """
    Converts an image of the number into NumPy array
    """
    pil_im = cls._get_cropped_image(cls._get_gscale_image(pil_im))
    pil_im = pil_im.resize((FINAL_SIZE, FINAL_SIZE), resample=1)
    pil_im = cls._get_gscale_image(pil_im, inverse=False)
    return np.array(pil_im) if as_ndarray else pil_im

@staticmethod
def _get_gscale_image(img: Image, inverse=True) -> Image:
    """
    Converts image into a black-white one
    """
    converted_image = img.convert('L')
    return ImageOps.invert(converted_image) if inverse else converted_image

@classmethod
def _get_cropped_image(cls, img: Image) -> Image:
    """
    Crops the image (converts the image into a squared one)
    """
    img_np = np.array(img)
    boundaries = cls._get_boundaries(img_np)
    img_np = img_np[boundaries[0]: boundaries[2], boundaries[1]: boundaries[3]]
    return Image.fromarray(img_np)

@staticmethod
def _get_boundaries(np_img: NDArray, inverted_image=True) -> Tuple:
    """
    Gets boundaries of the image
    """
    x = {k: v for k, v in enumerate(np_img.sum(axis=1) / np_img.shape[1])}
    y = {k: v for k, v in enumerate(np_img.sum(axis=0) / np_img.shape[0])}

    if inverted_image:
        x = list(filter(lambda z: z[1] > 0, x.items()))
        y = list(filter(lambda z: z[1] > 0, y.items()))
    else:
        x = list(filter(lambda z: z[1] < 255, x.items()))
        y = list(filter(lambda z: z[1] < 255, y.items()))

    return min(x)[0], min(y)[0], max(x)[0], max(y)[0]

Anything else is given above. There is nothing else I can add.

processed_own_image.show()

gives expected result, but

processes_own_image.save('temp.png', 'PNG') gives a black square

  • Can you include a self-contained example of the code you're trying to get working? Answering your question will be easier if you include some code that we can run ourselves. – jar Nov 20 '22 at 19:05
  • I can add the whole code of the class – Denys Murakhovskyi Nov 20 '22 at 19:19
  • Just to check, do something like: `temp = np.array(Image.open('temp.png')); print(temp.shape); print(temp)`. Basically check if after saving the image/array is still the same size or not when you reopen it. – Mercury Nov 20 '22 at 19:21
  • I've checked the shape. The shape is correct - (28, 28). Even more, the code processed_own_image.save('temp.png', 'PNG') the_image = PIL.Image.open('temp.png') the_image.show() gives the correct result. But viewing in the browser giver black square again. – Denys Murakhovskyi Nov 20 '22 at 19:23
  • The thing is that img.show() giver correct result even after saving and loading image. But while viewing the same PNG image in the browser I see a black square. – Denys Murakhovskyi Nov 20 '22 at 19:26
  • Your question is quite difficult to follow. Have you tried simply opening a *"correct"* image and saving it immediately? Have you tried printing the shape and dtype of your image just before saving it? – Mark Setchell Nov 20 '22 at 20:39
  • I can't think of an obvious answer, it might be the way your browser handles transparency. 'image.save(path, "PNG", transparency = 255)' tells PIL to use color 255 as transparency. Maybe that helps for your browser? – jar Nov 21 '22 at 06:52
  • Finally, I changed pillow grayscale mode to '1' and it solved the problem for my images. – Denys Murakhovskyi Nov 21 '22 at 11:44

0 Answers0