Spaces:
Running
Running
| import gradio as gr | |
| import requests | |
| import os | |
| API_KEY = os.environ.get("PLANTNET_API_KEY") | |
| PROJECT = "all" | |
| API_URL = f"https://my-api.plantnet.org/v2/identify/{PROJECT}?api-key={API_KEY}" | |
| def identify_plant(image, organ): | |
| if not API_KEY: | |
| return "⚠️ 未检测到 API Key,请检查 Space 的 Secrets 配置" | |
| if image is None: | |
| return "请先上传一张植物照片" | |
| try: | |
| with open(image, "rb") as f: | |
| files = [("images", ("image.jpg", f, "image/jpeg"))] | |
| data = {"organs": [organ]} | |
| response = requests.post(API_URL, files=files, data=data, timeout=20) | |
| except requests.exceptions.Timeout: | |
| return "请求超时,请稍后重试" | |
| except requests.exceptions.RequestException as e: | |
| return f"网络请求失败:{e}" | |
| if response.status_code == 401: | |
| return "❌ API Key 无效或已过期" | |
| elif response.status_code == 429: | |
| return "⚠️ 已超出当日调用配额" | |
| elif response.status_code != 200: | |
| return f"识别失败,状态码:{response.status_code}" | |
| result = response.json() | |
| results = result.get("results", []) | |
| if not results: | |
| return "未识别到匹配物种,建议换一张更清晰的照片重试" | |
| output = [] | |
| for i, r in enumerate(results[:5], start=1): | |
| name = r["species"]["scientificNameWithoutAuthor"] | |
| family = r["species"].get("family", {}).get("scientificNameWithoutAuthor", "") | |
| common_names = r["species"].get("commonNames", []) | |
| common = "、".join(common_names[:2]) if common_names else "暂无常用名" | |
| score = r["score"] | |
| output.append(f"**{i}. {name}**({family})\n常用名:{common} 置信度:{score:.1%}") | |
| return "\n\n---\n\n".join(output) | |
| with gr.Blocks(title="植物识别助手") as demo: | |
| gr.Markdown("# 🌿 植物识别助手\n上传一张植物照片,识别引擎来自 [Pl@ntNet](https://plantnet.org)") | |
| with gr.Row(): | |
| with gr.Column(): | |
| image_input = gr.Image(type="filepath", label="上传植物照片") | |
| organ_input = gr.Dropdown( | |
| choices=["auto", "leaf", "flower", "fruit", "bark", "habit"], | |
| value="auto", | |
| label="拍摄部位", | |
| info="明确指定部位(如leaf/flower)通常比auto识别更准确" | |
| ) | |
| submit_btn = gr.Button("开始识别", variant="primary") | |
| with gr.Column(): | |
| output_text = gr.Markdown(label="识别结果") | |
| submit_btn.click(fn=identify_plant, inputs=[image_input, organ_input], outputs=output_text) | |
| gr.Markdown("---\n数据与识别能力来自 Pl@ntNet 官方 API,遵循 CC BY-SA / CC BY 授权协议。识别结果仅供参考。") | |
| demo.launch(server_name="0.0.0.0", server_port=7860) |