santa hat
deerdeer nosedeer glow
Sign In

Gradio and Image File Names

Gradio and Image File Names

Preface

When I had the idea of writing an upscaler for my AI generated images, the first question was whether I wanted to use just the terminal or whether I wanted to use the terminal together with a graphical user interface (GUI).

I decided to write a Python script and I decided to write a GUI for the image management. There are some ways to realise a GUI in Python. Finally I decided to use Gradio.

The advantage of Gradio is, that any browser can be used as web UI. The disadvantage is, as with all other Python modules, there will some limitations.

In this article, I describe how a problem with images can be dealt with. One reason is that my Internet research did not really provide a quick answer to my problem. There were hints, but they were not directly related to images.

I then solved my problem by inspecting the Gradio source code, the Gradio documentation and over trial and error scripting.

Introduction

For my Upscaler UI, I wanted to preserve the Exif metadata in order to keep them for the image file to be written. To realise this, I needed the original image file, to be able to extract the Exif metadata from this file.

The Gradio Image component works in my case using jpg images with a numpy array. In a numpy array there are no longer Exif metadata. This was my first problem. From the numpy array it was not possible to infer the original image file name. This was my second problem.

How to overcome both problems is shown below. I am starting the the presentation of a demo web UI. Afterwards I explain the solution using my demo Python code.

Simple Gradio Web UI Demo

Web UI Start

On starts the local server for setting up the Web UI by following command:

hades@olymp:~$ python3 image_filename_demo.py

Afterwards one sees in the Terminal window something li8ke this:

* Running on local URL:  http://127.0.0.1:7861

To create a public link, set share=True in launch().

The server runs on localhost using port 7861:

http://127.0.0.1:7861

http://localhost:7861

Using one of the given URL in an arbitrary Browser the Web UI is started.

Empty Initialised Web UI

For this demo, the Gradio user interface to be created should be as simple as possible, but should show what it is all about. I created a UI, where we have three components. An input frame for the input image, an output frame for a cloned version of the input image and a textbox, where the name of the original image file can be found in.

Figure 1: Simple gradio web UI demo

Web UI with Loaded Image

I used drag and drop to put an image in the UI. After doing this the UI looked like the image below shows.

Figure 2: Simple gradio web UI demo with loaded image

Cross Check

In the textbox one can find a path like this:

/tmp/gradio/0f46a1eceb50023c17682ccf07ed1e0502ec0d6d60bbbdb1078ae46a3cef19f0/00016-1021663174-masterpiece best quality intricate photo front view of colorful butterflies in a floating in the sky over the ocean.jpg

This image is shown in the left input image frame. The image in the right output image frame is the graphical representation of a numpy array.

If one uses the path together with an arbitrary image viewer one can check, that this image is really the original image.

Figure 1: Simple gradio web UI demo

When reading the image Gradio makes a temporary copy of the original image file and puts this temporary copy in my case in a subdirectory of the tmp directory.

Python Script

Raw Python Source Code

This Python script is attached to this article. With this more or less simple script one realises the above presented GUI.

#!/usr/bin/python3

import gradio as gr
import numpy as np
from PIL import Image

with gr.Blocks(css="footer{display:none !important}", fill_width=True) as webui:
    with gr.Row():
        with gr.Column():
            image_input = gr.Image(type='filepath', height=512)
            file_name = gr.TextArea(lines=1, show_label=False)
        with gr.Column():
            image_output = gr.Image(height=512)
    def output_image(img_fileobj):
        pilImage = Image.open(img_fileobj)
        numpyImage = np.array(pilImage)
        filename = img_fileobj
        return [numpyImage, filename]
    image_input.change(
        output_image,
        inputs=[image_input],
        outputs=[image_output, file_name]
    )

if __name__ == "__main__":
    webui.launch()

I am using in the source code numpy as well as PIL like Gradio do too. This css style

css="footer{display:none !important}", fill_width=True

removes the Gradio footer from the web UI.

The script declares one block, with one row and two columns in it.

Parameter type and Value filepath

The important line in the script is:

image_input = gr.Image(type='filepath')

image_input is the identifier for the Image component. By using type='filepath' in the declaration of the Image component, one has to deal with (in my case) a jpg image.

Event Listener

Following Event Listener waits up the point an image is loaded e.g. per drag & drop.

image_input.change(
        output_image,
        inputs=[image_input],
        outputs=[image_output, file_name]
    )

Called Function

After the image is loaded into the left image, the function output_image is called. This function

def output_image(img_fileobj):
    pilImage = Image.open(img_fileobj)
    numpyImage = np.array(pilImage)
    filename = img_fileobj
    return [numpyImage, filename]

need an addition step, that one is able to work with the loaded image. One has to convert the jpg image (image & file object) in a numpy array. This numpy array can be outputted to the right output image frame.

One internal behaviour of Gradio is, that an declared component like e.g. image_input is used as input for a function. Then this component is interpreted in the function output_image with its value. In other cases this behavior is important to understand. In our case the value is the file path to the cloned image.

File Path

With this file path one can work within the web UI (in the Python script) or in a separate Terminal window (see also Figure 2 and Section Cross Check).

E.g. use exiftool in a terminal

exiftool "/tmp/gradio/0f46a1eceb50023c17682ccf07ed1e0502ec0d6d60bbbdb1078ae46a3cef19f0/00016-1021663174-masterpiece best quality intricate photo front view of colorful butterflies in a floating in the sky over the ocean.jpg"

results in my original Exif metadata:

ExifTool Version Number         : 12.40
File Name                       : 00016-1021663174-masterpiece best quality intricate photo front view of colorful butterflies in a floating in the sky over the ocean.jpg
Directory                       : /tmp/gradio/0f46a1eceb50023c17682ccf07ed1e0502ec0d6d60bbbdb1078ae46a3cef19f0
File Size                       : 162 KiB
File Modification Date/Time     : 2024:11:16 08:24:06+01:00
File Access Date/Time           : 2024:11:16 08:24:06+01:00
File Inode Change Date/Time     : 2024:11:16 08:24:06+01:00
File Permissions                : -rw-------
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
Exif Byte Order                 : Big-endian (Motorola, MM)
User Comment                    : masterpiece, best quality, intricate photo, front view of colorful butterflies in a floating in the sky over the ocean glass sphere, Background blue cloudy sky, hyper realistic, highly detailed, sharp focus, high resolution, 8K, <hypernet:GlassSphereHypernet:0.6>.Negative prompt: cartoon, painting, drawing, sketch, anime.Steps: 25, Sampler: DPM++ 2M, Schedule type: Karras, CFG scale: 7.5, Seed: 1021663174, Size: 512x512, Model hash: 463d6a9fe8, Model: absolutereality_v181, Denoising strength: 0, Hires upscale: 2, Hires upscaler: 4x-UltraSharp, Version: v1.10.0
Image Width                     : 1024
Image Height                    : 1024
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 1024x1024
Megapixels                      : 1.0

Conclusion

It could be shown, that one can use an original image to work with instead of a black box, which is given by Gradio per default.

Finale Words

Have a nice day. Have fun coding. Be inspired!

Resources

[1] https://www.gradio.app/

[2] https://www.gradio.app/docs/gradio/image

0

Comments