使用Gradio构建交互式Web应用
这是一个关于如何使用 Gradio 构建 Web 应用程序的开源系列教程。你将从设置 Python 环境开始,学习文本、图像等各类输入组件,自定义界面,设计复杂的交互等。本课程还将涵盖使用 Gradio 和 GDAL 处理遥感数据,用于图像增强、地理坐标转换、坡度分析等任务;学习如何使用 Gradio 和 Foliumap 创建交互式地图,实现动态地理空间数据可视化;如何集成机器学习模型并在 Hugging Face Spaces 上发布 web 应用程序。本教程包括实例、演示和作业。完成本教程后,你将能够高效地构建、部署和共享交互式 Web 应用程序。
课程相关资源链接GITHUB
Part3 :Gradio与遥感数据处理(下)
EMO 3-3: 地理空间坐标转换和shp矢量生成
本案例中将展示如何实现“度分秒”与“度”格式的经纬度进行转换,并且根据经纬度生成shp矢量,并下载到本地。构建该应用需要注意以下两点:
利用gepandas生成shp的时候,需要四个坐标点,这四个点是以左上为启示,逆时针依次循环的至右上。
生成的shp有多个文件构成,因此要使用zipfile对多个文件进行打包。下载打包后的文件需要利用gr.DownloadButton函数,注意它在generate_shp函数中是作为输入组件使用,而image_button使用的gr.DownloadButton是作为输出组件使用。
import geopandas as gpd
from shapely.geometry import box
from pathlib import Path
from shapely.geometry import Polygon
from pyproj import CRS
import zipfile
import os
import gradio as gr
# 定义起点和终点的十进制度数和度分秒格式
=["109°35'57'',E", "41°50'49'',N"]
start_point = ["110°12'24'',E","41°43'16'',N"]
end_point
= ["109.57,E", "41.59,N"]
start_point = ["110.12,E","41.16,N"]
end_point
# 将十进制度数转换为度、分和秒(DMS)格式的函数
def deg_to_dms(coord):
= coord.split(',')
deg, direction = float(deg)
deg = 1 if direction in ['N', 'E'] else -1
sign = abs(deg)
deg_abs = int(deg_abs)*sign
deg_int = (deg_abs - deg_int) * 60
minutes = (minutes - int(minutes)) * 60
seconds return f"{deg_int}° {int(minutes)}' {int(seconds)}'',{direction}",deg
# 将度、分和秒(DMS)格式转换为十进制度数的函数
def dms_to_deg(coord):
= coord.replace('°', "'").replace("''", "'").replace(",", "'").split("'")
parts = float(parts[0])
deg = float(parts[1])
minutes = float(parts[2])
seconds = parts[-1]
direction = deg + (minutes / 60) + (seconds / 3600)
decimal_deg = 1 if direction in ['N', 'E'] else -1
sign = decimal_deg*sign
decimal_deg return f"{decimal_deg:.4f},{direction}",decimal_deg
# 坐标转换器
def coord_convert(start_pointx,start_pointy,end_pointx,end_pointy,dms='True'):
# print(dms)
if dms=='True':
=dms_to_deg(start_pointx)
textlon_min,lon_min=dms_to_deg(start_pointy)
textlat_max,lat_max=dms_to_deg(end_pointx)
textlon_max,lon_max=dms_to_deg(end_pointy)
textlat_min,lat_minelse:
=deg_to_dms(start_pointx)
textlon_min,lon_min=deg_to_dms(start_pointy)
textlat_max,lat_max=deg_to_dms(end_pointx)
textlon_max,lon_max=deg_to_dms(end_pointy)
textlat_min,lat_min=lon_min,lat_max
start_point=lon_max,lat_min
end_point=textlon_min,textlat_min
textstart_point=textlon_max,textlat_max
textend_pointreturn textstart_point,textend_point,start_point,end_point
# 将Shapefile压缩成.zip文件以便下载的函数
def shp_to_zip(shp_file):
= os.path.dirname(shp_file)
directory = os.path.splitext(os.path.basename(shp_file))[0]
basename = ['.dbf', '.shx', '.cpg', '.prj','.shp']
extensions = os.path.join(directory, f"{basename}.zip")
zip_filename with zipfile.ZipFile(zip_filename, 'w') as zipf:
for ext in extensions:
= os.path.join(directory, f"{basename}{ext}")
filename if os.path.exists(filename):
=f"{basename}{ext}")
zipf.write(filename, arcname# print(zip_filename)
return zip_filename
# 从转换后的坐标生成Shapefile的函数
def generate_shp(start_point,end_point):
print(start_point)
print(end_point)
= [(start_point[0], start_point[1]), (start_point[0], end_point[1]),(end_point[0], end_point[1]),(end_point[0], start_point[1])]
vertices = Polygon(vertices)
polygon = gpd.GeoDataFrame(geometry=[polygon], crs=CRS('EPSG:4326').to_wkt())
gdf ='./result.shp'
shpfile
gdf.to_file(shpfile)=shp_to_zip(shpfile)
tempfilereturn gr.DownloadButton(label=f"Download {Path(tempfile).stem}", value=tempfile, visible=True)
with gr.Blocks(theme='NoCrypt/Miku') as demo:
=gr.State(None)
start_point=gr.State(None)
end_pointtype=gr.State('False')
with gr.Tab("Convert dms coord to shp"): # 度分秒格式坐标生成 shp
with gr.Row():
=gr.Textbox(value="115°25'00'',E",label="Longtitude (top left)",interactive=True)
start_pointx=gr.Textbox(value="41°03'00'',N",label="Latitude (top left)",interactive=True)
start_pointy=gr.Textbox(value="117°30'00'',E",label="Longtitude (bottom right)",interactive=True)
end_pointx=gr.Textbox(value="39°26'00'',N",label="Latitude(bottom right)",interactive=True)
end_pointywith gr.Row():
=gr.Textbox(placeholder='',label="converted top left point")
convert_start=gr.Textbox(placeholder='',label="converted bottom right point")
convert_endwith gr.Row():
=gr.Button("Read the corrd",visible=True,variant='primary')
read_button=gr.Button("Generate SHP",variant='primary')
runbutton=gr.DownloadButton("Download",visible=True,variant='secondary')
image_button
read_button.click(coord_convert,[start_pointx,start_pointy,end_pointx,end_pointy],[convert_start,convert_end,start_point,end_point])
runbutton.click(generate_shp, [start_point,end_point],image_button)
with gr.Tab("Convert degree coord to shp"): # 以度为单位的坐标生成shp
with gr.Row():
=gr.Textbox(value="115.42,E",label="Longtitude (top left)",interactive=True)
start_pointx=gr.Textbox(value="41.05,N",label="Latitude (top left)",interactive=True)
start_pointy=gr.Textbox(value="117.50,E",label="Longtitude (bottom right)",interactive=True)
end_pointx=gr.Textbox(value="39.43,N",label="Latitude(bottom right)",interactive=True)
end_pointywith gr.Row():
=gr.Textbox(placeholder='',label="converted top left point")
convert_start=gr.Textbox(placeholder='',label="converted bottom right point")
convert_endwith gr.Row():
=gr.Button("Read the corrd",visible=True,variant='primary')
read_button=gr.Button("Generate SHP",variant='primary')
runbutton=gr.DownloadButton("Download",visible=True,variant='secondary')
image_button
type],[convert_start,convert_end,start_point,end_point])
read_button.click(coord_convert,[start_pointx,start_pointy,end_pointx,end_pointy, runbutton.click(generate_shp, [start_point,end_point],image_button)
请关注微信公众号【45度科研人】回复“@gradio”获取该教程配套数据,欢迎后台留言! |
为了促进沟通与交流,我们建立了「养生科研」学术交流群。这个平台不仅能够让大家迅速获取本公众号的资源,还为各位提供了一个共同探讨问题、交流思想的空间。有意向加入交流群的朋友们,可以通过添加小编的微信来获得入群邀请。请注意,在添加时请按照“加群-单位-研究方向-姓名”的格式备注您的信息,否则您的申请可能无法通过。