DEMO 3-1: Remote Sensing Imagery Visulization

from osgeo import gdal,osr
import gradio as gr
import numpy as np
import matplotlib.pyplot as plt
import logging

# using logging to record the status of the app
logging.basicConfig(filename='app.log', level=logging.INFO,format='%(asctime)s:%(levelname)s:%(message)s')

# Define the upload interface, which returns a temporary path after data upload and processes the image into an array
def stretch_n(band, lower_percent=5, higher_percent=95): 
    band=np.array(band,dtype=np.float32)
    c = np.percentile(band, lower_percent)*1.0
    d = np.percentile(band, higher_percent)*1.0       
    band[band<c] = c
    band[band>d] = d
    out =  (band - c)  / (d - c)  
    # print(np.max(out),np.min(out),c,d)  
    return out.astype(np.float32)

# Loop through each band for stretching
def adjust_contrast(data,n_band=3):    
    data=np.array(data,dtype=np.float32)
    for img in data:
        for k in range(n_band):
            img[:,:,k] = stretch_n(img[:,:,k])
    return data

def Load_image_by_Gdal(file_path):
    img_file = gdal.Open(file_path, gdal.GA_ReadOnly)
    img_bands = img_file.RasterCount # Number of bands
    img_height = img_file.RasterYSize # Height
    img_width = img_file.RasterXSize # Width
    img_arr = img_file.ReadAsArray() # Get projection information
    geomatrix = img_file.GetGeoTransform() # Get transformation matrix information
    projection = img_file.GetProjectionRef()
    return img_bands,img_arr, geomatrix, projection

# Define the tiff reading function
def read_tiff(file):
    img_bands,img_arr, geomatrix, projection =Load_image_by_Gdal(file)
    if img_bands >1 :
        img_arr=img_arr.transpose(( 1, 2,0))
    return img_arr, geomatrix, projection

# Define the reset function
def reset_state():
    return None,None,None,[]

# Define the visulization function
def upload_file(files):
    logging.info(f"File uploaded: {files.name}")
    
    file_patchs=files.name
    img_arr, geomatrix, projection=read_tiff(file_patchs)
    rgb=img_arr.copy()[:,:,:3]
    mask=img_arr.copy()[:,:,-1]
    img=adjust_contrast(np.expand_dims(rgb,axis=0))
    # print(img.shape)
    palette = np.array([ [83,49,125],   [56,173,20],   [210,10,115], [19,188,106], [16,96,160]]) 
    predc=palette[mask]
    
    dict_info={"image shape":img_arr.shape,"max value":np.max(img_arr)}
    if isinstance(projection, str):
        spatial_ref = osr.SpatialReference()
        spatial_ref.ImportFromWkt(projection)
        utm_zone = spatial_ref.GetUTMZone()
        if utm_zone:
            dict_info["UTM zone"] = utm_zone
            dict_info["Projection"] = f"WGS 84 / UTM Zone {utm_zone}"

    # Convert the dictionary into a string with each key-value pair on a new line
    info_lines = "\n".join([f"{key}: {value}" for key, value in dict_info.items()])
    
    logging.info(f"File info: {dict_info}")
    return img[0],predc,info_lines # return rgb image, mask image, and image info

#  Build the main interface with gr.Blocks
with gr.Blocks(theme="gradio/sketch") as demo: # sketch-like theme

    gr.Markdown('''# <center>Remote Sensing Imagery Visulization</center>''')  # Title, markdown syntax
    upload_button = gr.UploadButton("Click to Upload a Tiff", file_types=["image"], file_count="single") #定义上传接口
    # Define intermediate parameters
    with gr.Row():
        showimg=gr.Image(label="RGB") # output 1 recive the RGB array
        img_output = gr.Image(label="label") # output 2 recive the mask array
    outtext=gr.Textbox(label="img_info") # output 3 recive the image info
    emptyBtn = gr.Button("Restart",variant="secondary") 

    # Define buttons
    upload_button.upload(upload_file, upload_button, [showimg,img_output,outtext]) 

    # Define button actions
    emptyBtn.click(reset_state,outputs=[upload_button,showimg,img_output,outtext],show_progress=True)  
        
demo.launch()