jiaqi9720 commited on
Commit
b1eedf1
·
verified ·
1 Parent(s): 49148d5

Upload 3 files

Browse files
Files changed (3) hide show
  1. best.pt +3 -0
  2. lajifenlei.yaml +103 -0
  3. yemian.py +516 -0
best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:49331b0753c63458c0b672f769f79f0b12ae375ce6aae240e0543d74a4892b83
3
+ size 5645658
lajifenlei.yaml ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 垃圾分类数据集配置文件(YOLOv8 标准格式)
2
+ # 说明:配置文件用于定义数据集路径、类别信息及扩展映射,训练时YOLOv8仅读取path、train、val、nc、names字段
3
+
4
+ # 数据集根目录(建议使用绝对路径,避免因运行目录变化导致路径错误;若路径含空格,可加英文引号包裹)
5
+ path: D:/Study/ultralytics-main/datasets
6
+
7
+ # 图像路径(相对于path的相对路径,支持文件夹下所有图像文件,格式需统一为jpg/png等)
8
+ train: images/train # 训练集图像文件夹
9
+ val: images/val # 验证集图像文件夹
10
+ test: # 测试集图像路径(可选,若无需测试可保持空值或删除此行)
11
+
12
+ # 核心配置(YOLOv8训练必填)
13
+ nc: 40 # 类别总数(共40个小类,与names列表长度一致)
14
+ names: # 小类名称列表(顺序必须与标签文件中的类别索引严格对应,0-39连续无重复)
15
+ 0: 污损塑料
16
+ 1: 烟蒂
17
+ 2: 牙签
18
+ 3: 破碎花盆及碟碗
19
+ 4: 竹筷
20
+ 5: 剩饭剩菜 # 原6号类别前移
21
+ 6: 大骨头 # 原7号类别前移
22
+ 7: 水果果皮 # 原8号类别前移
23
+ 8: 水果果肉 # 原9号类别前移
24
+ 9: 茶叶渣 # 原10号类别前移
25
+ 10: 菜叶菜根 # 原11号类别前移
26
+ 11: 蛋壳 # 原12号类别前移
27
+ 12: 鱼骨 # 原13号类别前移
28
+ 13: 充电宝 # 原14号类别前移
29
+ 14: 包 # 原15号类别前移
30
+ 15: 化妆品瓶 # 原16号类别前移
31
+ 16: 塑料玩具 # 原17号类别前移
32
+ 17: 塑料碗盆 # 原18号类别前移
33
+ 18: 塑料衣架 # 原19号类别前移
34
+ 19: 快递纸袋 # 原20号类别前移
35
+ 20: 插头电线 # 原21号类别前移
36
+ 21: 旧衣服 # 原22号类别前移
37
+ 22: 易拉罐 # 原23号类别前移
38
+ 23: 枕头 # 原24号类别前移
39
+ 24: 毛绒玩具 # 原25号类别前移
40
+ 25: 洗发水瓶 # 原26号类别前移
41
+ 26: 玻璃杯 # 原27号类别前移
42
+ 27: 皮鞋 # 原28号类别前移
43
+ 28: 砧板 # 原29号类别前移
44
+ 29: 纸板箱 # 原30号类别前移
45
+ 30: 调料瓶 # 原31号类别前移
46
+ 31: 酒瓶 # 原32号类别前移
47
+ 32: 金属食品罐 # 原33号类别前移
48
+ 33: 锅 # 原34号类别前移
49
+ 34: 食用油桶 # 原35号类别前移
50
+ 35: 饮料瓶 # 原36号类别前移
51
+ 36: 干电池 # 原37号类别前移
52
+ 37: 软膏 # 原38号类别前移
53
+ 38: 过期药物 # 原39号类别前移
54
+ 39: 一次性快餐盒 # 调整后固定在39位
55
+
56
+ # 扩展配置(训练不依赖,用于推理时小类→大类转换,方便结果展示)
57
+ big_category_mapping: # 小类索引→大类索引(0=其他垃圾,1=厨余垃圾,2=可回收物,3=有害垃圾)
58
+ 0: 0 # 污损塑料 → 其他垃圾
59
+ 1: 0 # 烟蒂 → 其他垃圾
60
+ 2: 0 # 牙签 → 其他垃圾
61
+ 3: 0 # 破碎花盆及碟碗 → 其他垃圾
62
+ 4: 0 # 竹筷 → 其他垃圾
63
+ 5: 1 # 剩饭剩菜 → 厨余垃圾(原6号映射同步前移)
64
+ 6: 1 # 大骨头 → 厨余垃圾(原7号映射同步前移)
65
+ 7: 1 # 水果果皮 → 厨余垃圾(原8号映射同步前移)
66
+ 8: 1 # 水果果肉 → 厨余垃圾(原9号映射同步前移)
67
+ 9: 1 # 茶叶渣 → 厨余垃圾(原10号映射同步前移)
68
+ 10: 1 # 菜叶菜根 → 厨余垃圾(原11号映射同步前移)
69
+ 11: 1 # 蛋壳 → 厨余垃圾(原12号映射同步前移)
70
+ 12: 1 # 鱼骨 → 厨余垃圾(原13号映射同步前移)
71
+ 13: 2 # 充电宝 → 可回收物(原14号映射同步前移)
72
+ 14: 2 # 包 → 可回收物(原15号映射同步前移)
73
+ 15: 2 # 化妆品瓶 → 可回收物(原16号映射同步前移)
74
+ 16: 2 # 塑料玩具 → 可回收物(原17号映射同步前移)
75
+ 17: 2 # 塑料碗盆 → 可回收物(原18号映射同步前移)
76
+ 18: 2 # 塑料衣架 → 可回收物(原19号映射同步前移)
77
+ 19: 2 # 快递纸袋 → 可回收物(原20号映射同步前移)
78
+ 20: 2 # 插头电线 → 可回收物(原21号映射同步前移)
79
+ 21: 2 # 旧衣服 → 可回收物(原22号映射同步前移)
80
+ 22: 2 # 易拉罐 → 可回收物(原23号映射同步前移)
81
+ 23: 2 # 枕头 → 可回收物(原24号映射同步前移)
82
+ 24: 2 # 毛绒玩具 → 可回收物(原25号映射同步前移)
83
+ 25: 2 # 洗发水瓶 → 可回收物(原26号映射同步前移)
84
+ 26: 2 # 玻璃杯 → 可回收物(原27号映射同步前移)
85
+ 27: 2 # 皮鞋 → 可回收物(原28号映射同步前移)
86
+ 28: 2 # 砧板 → 可回收物(原29号映射同步前移)
87
+ 29: 2 # 纸板箱 → 可回收物(原30号映射同步前移)
88
+ 30: 2 # 调料瓶 → 可回收物(原31号映射同步前移)
89
+ 31: 2 # 酒瓶 → 可回收物(原32号映射同步前移)
90
+ 32: 2 # 金属食品罐 → 可回收物(原33号映射同步前移)
91
+ 33: 2 # 锅 → 可回收物(原34号映射同步前移)
92
+ 34: 2 # 食用油桶 → 可回收物(原35号映射同步前移)
93
+ 35: 2 # 饮料瓶 → 可回收物(原36号映射同步前移)
94
+ 36: 3 # 干电池 → 有害垃圾(原37号映射同步前移)
95
+ 37: 3 # 软膏 → 有害垃圾(原38号映射同步前移)
96
+ 38: 3 # 过期药物 → 有害垃圾(原39号映射同步前移)
97
+ 39: 0 # 一次性快餐盒 → 其他垃圾(原5号映射移至39位)
98
+
99
+ big_category_names: # 大类索引→名称(与big_category_mapping对应,用于结果展示)
100
+ 0: 其他垃圾
101
+ 1: 厨余垃圾
102
+ 2: 可回收物
103
+ 3: 有害垃圾
yemian.py ADDED
@@ -0,0 +1,516 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+
3
+ import gradio as gr
4
+ import yaml
5
+ import numpy as np
6
+ from ultralytics import YOLO
7
+ from PIL import Image, ImageDraw, ImageFont
8
+ import os
9
+ from pathlib import Path
10
+ import cv2
11
+
12
+ # === 新增:详细垃圾分类介绍字典(已按要求详细扩展) ===
13
+ GARBAGE_INTRODUCTION = {
14
+ # 其他垃圾(大类0)
15
+ "其他垃圾/污损塑料": "其他垃圾是无法回收且无害的废弃物,长期堆积会占用土地资源。污损塑料指被污染、破损或难以清洁的塑料制品,如沾有油污的塑料袋、食物残渣的塑料容器等。其具体作用是临时包装或盛放物品,但一旦被污染,失去再利用价值。可回收性极低,因为污染会破坏塑料的再利用价值。危害性较低,但填埋占用土地,焚烧可能释放有害气体,长期影响环境质量。对环境影响:填埋占用土地并产生甲烷,对环境有轻微但持续的危害;长期积累可能释放微塑料,影响土壤和水体质量。对人类和动物影响:直接危害较小,但可能通过食物链间接影响健康。",
16
+
17
+ "其他垃圾/烟蒂": "其他垃圾无回收价值,随意丢弃易造成视觉污染。烟蒂是香烟过滤嘴,主要成分是醋酸纤维素,含有尼古丁、焦油等化学物质。其具体作用是过滤吸烟时的有害物质,但本身是不可回收的垃圾。可回收性极低,因为含有化学物质且难以清洁。危害性较高,含有多种有害化学物质,对环境和健康都有潜在危害。对环境影响:烟蒂含尼古丁、焦油等化学物质,可能释放有害物质污染土壤和水体。对人类影响:可能引起火灾,对动物影响:可能造成误食中毒。",
18
+
19
+ "其他垃圾/牙签": "其他垃圾难以回收利用,过量堆积会增加处理压力。牙签多为木质或塑料材质,一次性使用后难以回收。其具体作用是清洁牙齿缝隙,但使用后无法再利用。可回收性低,木质牙签难以回收,塑料牙签也因污染和材质问题难以回收。危害性较低,但可能影响土壤结构,塑料牙签被动物误食可能造成伤害。对环境影响:木质牙签可能影响土壤结构,塑料牙签可能被动物误食造成伤害。对人类影响:可能造成轻微割伤。",
20
+
21
+ "其他垃圾/破碎花盆及碟碗": "其他垃圾回收价值极低,破碎陶瓷易划伤设备。破碎花盆及碟碗是陶瓷制品的废弃物,主要用途是盛放物品或作为装饰。其具体作用是日常使用,但破损后失去功能。可回收性极低,陶瓷制品通常无法回收。危害性较低,但可能造成割伤,填埋占用空间。对环境影响:破碎陶瓷制品难以降解,可能划伤土壤表面,影响土壤微生物活动。对人类和动物影响:可能造成割伤。",
22
+
23
+ "其他垃圾/竹筷": "其他垃圾无法循环利用,易污染且处理成本高。竹筷是一次性竹制品,用于进餐的工具。其具体作用是辅助进食,但使用后无法再利用。可回收性低,竹筷虽然可生物降解,但因污染和材质问题通常不被视为可回收物。危害性较低,但填埋可能影响土壤。对环境影响:竹筷填埋需要较长时间分解,可能影响土壤结构。对人类和动物影响:危害较小,但大量填埋可能影响土壤质量。",
24
+
25
+ "其他垃圾/一次性快餐盒": "其他垃圾难以清洁再生,易造成白色污染。一次性快餐盒是用于盛放快餐的容器,通常为塑料制成。其具体作用是盛放快餐。可回收性低,因为塑料快餐盒通常难以清洁和回收。危害性较低,但填埋占用空间,可能释放微塑料。对环境影响:一次性快餐盒多为塑料,填埋难降解,可能释放微塑料。对人类和动物影响:可能被动物误食。",
26
+
27
+ # 厨余垃圾(大类1)
28
+ "厨余垃圾/剩饭剩菜": "厨余垃圾是易腐烂生物质废弃物,不及时处理易发霉发臭污染环境。剩饭剩菜可通过堆肥或生物降解制有机肥,回收价值较高。投放前需沥干汤汁,挑出非厨余杂物。对环境影响:可生物降解,可堆肥处理,减少填埋污染。对人类和动物影响:若未分类,填埋会产生大量渗滤液和甲烷,污染水土环境,对人类可能传播疾病,对动物可能破坏栖息地,吸引害虫。",
29
+
30
+ "厨余垃圾/大骨头": "厨余垃圾可生物降解,随意丢弃易滋生细菌。大骨头是食物残渣,主要来自肉类食品。其具体作用是提供营养,但食用后成为废弃物。可回收性低,因为大骨头难以降解,不适合常规堆肥。危害性低,但可能影响厨余垃圾处理。对环境影响:大骨头难以堆肥,填埋时可能影响堆肥质量,产生渗滤液。对人类和动物影响:对人类危害小,但可能影响厨余垃圾处理效率。",
31
+
32
+ "厨余垃圾/水果果皮": "厨余垃圾易腐烂可循环,是优质堆肥原料,不分类会浪费资源。水果果皮可堆肥转化为有机肥料,回收价值高。投放时无需去除果蒂,大块可撕碎。对环境影响:可生物降解,可堆肥处理,减少填埋污染。对人类和动物影响:若未分类,填埋会产生渗滤液和甲烷,污染水土环境,对人类可能传播疾病,对动物可能破坏栖息地。",
33
+
34
+ "厨余垃圾/水果果肉": "厨余垃圾富含有机物,不处理易变质污染土壤水源。水果果肉可通过生物处理制沼气或有机肥,回收价值高。变质果肉仍属厨余垃圾,及时投放。对环境影响:可生物降解,可堆肥处理,减少填埋污染。对人类和动物影响:若未分类,填埋会产生渗滤液和甲烷,污染水土环境,对人类可能传播疾病,对动物可能破坏栖息地。",
35
+
36
+ "厨余垃圾/茶叶渣": "厨余垃圾可自然降解,是环保的生物质资源。茶叶渣富含纤维和矿物质,处理方式为堆肥或作为植物肥料,回收价值中等。无需清洗直接投放。对环境影响:可生物降解,可堆肥处理,减少填埋污染。对人类和动物影响:若未分类,填埋会产生渗滤液和甲烷,污染水土环境,对人类可能传播疾病,对动物可能破坏栖息地。",
37
+
38
+ "厨余垃圾/菜叶菜根": "厨余垃圾易分解可循环,不分类会增加填埋压力。菜叶菜根可堆肥制有机肥,回收价值高。投放前去除塑料绳等杂物,沥干水分。对环境影响:可生物降解,可堆肥处理,减少填埋污染。对人类和动物影响:若未分类,填埋会产生渗滤液和甲烷,污染水土环境,对人类可能传播疾病,对动物可能破坏栖息地。",
39
+
40
+ "厨余垃圾/蛋壳": "厨余垃圾可生物降解,能调节堆肥酸碱度。蛋壳主要成分为碳酸钙,处理方式为破碎后堆肥,回收价值中等。无需清洗,直接破碎投放。对环境影响:可生物降解,可堆肥处理,减少填埋污染。对人类和动物影响:若未分类,填埋会产生渗滤液和甲烷,污染水土环境,对人类可能传播疾病,对动物可能破坏栖息地。",
41
+
42
+ "厨余垃圾/鱼骨": "厨余垃圾易腐烂,是生物处理的优质原料。鱼骨(尤其是小鱼骨)质地较软,处理方式为堆肥或生物降解,回收价值高。与其他厨余垃圾一同投放即可。对环境影响:可生物降解,可堆肥处理,减少填埋污染。对人类和动物影响:若未分类,填埋会产生渗滤液和甲烷,污染水土环境,对人类可能传播疾病,对动物可能破坏栖息地。",
43
+
44
+ # 可回收物(大类2)
45
+ "可回收物/充电宝": "可回收物能循环利用,减少资源开采和环境污染。充电宝含锂、铜等可回收成分,处理方式为专业拆解回收,回收价值较高。投放时保持干燥,不拆解。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋浪费资源,焚烧可能释放有害气体,对环境有轻微危害,对人类有益,减少环境污染,对动物可能造成电池泄漏污染。",
46
+
47
+ "可回收物/包": "可回收物循环利用可节约原材料,降低碳排放。包的皮革、帆布等材质可再生加工,回收价值中等。投放前清理内部杂物,破损严重仍可回收。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
48
+
49
+ "可回收物/化妆品瓶": "可回收物再生能减少塑料/玻璃消耗,保护资源。化妆品瓶(玻璃/塑料材质)可重新加工为容器,回收价值较高。投放前清空冲洗,取下非同类部件。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
50
+
51
+ "可回收物/塑料玩具": "可回收物循环利用可降低塑料污染,节约石油资源。塑料玩具多为PP/PE材质,处理方式为熔融再生,回收价值中等。投放前去除电池,清洗污渍。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
52
+
53
+ "可回收物/塑料碗盆": "可回收物再生能减少白色污染,提升资源利用率。塑料碗盆(PP/PE材质)可熔融重塑,回收价值中等。破损严重的按其他垃圾投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
54
+
55
+ "可回收物/塑料衣架": "可回收物循环利用���节约塑料原料,减少环境压力。塑料衣架可熔融再生为新塑料制品,回收价值较低。无需拆解,直接放入可回收物箱。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
56
+
57
+ "可回收物/快递纸袋": "可回收物再生能节约木材资源,减少森林砍伐。快递纸袋可重新制成再生纸,回收价值较高。投放前去除胶带,折叠压平,潮湿的需晾干。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
58
+
59
+ "可回收物/插头电线": "可回收物回收能节约金属资源,减少矿产开采。插头电线含铜、铝等金属,处理方式为拆解回收金属,回收价值较高。盘绕整齐后投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类可致电击风险,对动物可能造成中毒。",
60
+
61
+ "可回收物/旧衣服": "可回收物再利用能减少纺织业污染,节约能源。旧衣服可捐赠、纤维化再生,回收价值中等。投放前清洗打包,破损的仍可回收。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
62
+
63
+ "可回收物/易拉罐": "可回收物再生能耗仅为原生产的5%,节约能源效果显著。易拉罐(铝/铁材质)可100%再生,回收价值高。冲洗干净,压扁投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
64
+
65
+ "可回收物/枕头": "可回收物再利用能减少资源浪费,降低填埋压力。枕头的布料、填充物可再生加工,回收价值较低。投放前拆解分类,破损的可整体投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
66
+
67
+ "可回收物/毛绒玩具": "可回收物再生能减少塑料和纺织废料污染。毛绒玩具的布料、PP棉可回收,处理方式为分类再生,回收价值较低。去除电池,清洗后投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
68
+
69
+ "可回收物/洗发水瓶": "可回收物再生能减少塑料垃圾,节约石油资源。洗发水瓶(PET材质)可制成纤维、塑料管材,回收价值中等。清空冲洗,泵头可一同投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
70
+
71
+ "可回收物/玻璃杯": "可回收物可无限循环利用,再生无环境污染。玻璃杯再生能节约石英砂等原料,回收价值较高。避免破碎,破损的需包裹投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
72
+
73
+ "可回收物/皮鞋": "可回收物再生能减少皮革和橡胶浪费。皮鞋的皮革、橡胶鞋底可加工为再生制品,回收价值较低。清理鞋内杂物后投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
74
+
75
+ "可回收物/砧板": "可回收物再生能提升资源利用率,减少木材/塑料消耗。木质砧板可作生物质原料,塑料砧板可熔融再生,回收价值中等。清洗干净后投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
76
+
77
+ "可回收物/纸板箱": "可回收物再生能节约木材,减少造纸污染。纸板箱可制成新纸箱或纸浆制品,回收价值较高。拆除胶带,折叠压平,潮湿的需晾干。对环境影响:可回收再利用,节约资源,减少污��。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
78
+
79
+ "可回收物/调料瓶": "可回收物再生能减少玻璃/塑料垃圾,保护资源。调料瓶(玻璃/塑料材质)可重新利用,回收价值中等。清空冲洗,金属盖可一同投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
80
+
81
+ "可回收物/酒瓶": "可回收物再生能节约玻璃原料,降低能耗。酒瓶(尤其是无色玻璃)回收价值高,可循环制成新玻璃制品。冲洗干净,去除纸质标签。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
82
+
83
+ "可回收物/金属食品罐": "可回收物再生能减少矿产开采,节约能源。金属食品罐(铁/铝材质)再生利用率超90%,回收价值高。冲洗干净,压扁投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
84
+
85
+ "可回收物/锅": "可回收物再生能节约金属资源,减少冶炼污染。铁锅、铝锅等金属锅具可回炉重炼,回收价值较高。无需修复,直接投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
86
+
87
+ "可回收物/食用油桶": "可回收物再生能减少塑料污染,提升资源循环率。食用油桶(PET/HDPE材质)可制成非食品接触类产品,回收价值中等。彻底清洗后投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
88
+
89
+ "可回收物/饮料瓶": "可回收物再生能大幅减少塑料污染,节约资源。饮料瓶(PET材质)回收体系成熟,可制成纤维、容器等,回收价值高。清空冲洗,压扁投放。对环境影响:可回收再利用,节约资源,减少污染。对人类和动物影响:若未回收,填埋占用土地,焚烧可能释放有害气体,对环境有轻微危害,对人类和动物的危害较小。",
90
+
91
+ # 有害垃圾(大类3)
92
+ "有害垃圾/干电池": "有害垃圾含有毒物质,随意丢弃会污染土壤和水源。干电池含汞、镉等重金属,属于有害垃圾。其具体作用是提供电力,但含有有害物质。可回收性低,因为含有有害物质,需特殊处理。危害性高,含有重金属等有害物质。对环境影响:含剧毒物质,如重金属、化学品,污染环境和健康。对人类和动物影响:对人类可致病或中毒,对动物可致死。",
93
+
94
+ "有害垃圾/软膏": "有害垃圾含化学物质,会危害生态环境和人体健康。过期软膏含残留化学成分,属于有害垃圾。其具体作用是治疗皮肤问题,但含有有害成分。可回收性低,因为含有药物成分,需特殊处理。危害性高,含有化学成分。对环境影响:含剧毒物质,如重金属、化学品,污染环境和健康。对人类和动物影响:对人类可致病或中毒,对动物可致死。",
95
+
96
+ "有害垃圾/过期药物": "有害垃圾含变质成分,随意丢弃会污染土壤和水源,危害生物。过期药物需专业无害化处理,属于有害垃圾。其具体作用是治疗疾病,但过期后失去药效。可回收性低,因为含有化学成分,需特殊处理。危害性高,含有化学成分。对环境影响:含剧毒物质,如重金属、化学品,污染环境和健康。对人类和动物影响:对人类可致病或中毒,对动物可致死。"
97
+ }
98
+
99
+ # 固定模型和配置文件路径
100
+ MODEL_PATH = r"best.pt"
101
+ YAML_PATH = r"lajifenlei.yaml"
102
+
103
+ # 全局变量:模型和标签映射
104
+ model = None
105
+ big_category_mapping = None
106
+ big_category_names = None
107
+ small_category_names = None
108
+
109
+ # 历史记录存储
110
+ history_messages = []
111
+
112
+
113
+ def init_model():
114
+ """初始化模型和配置(页面加载时执行)"""
115
+ global model, big_category_mapping, big_category_names, small_category_names
116
+ try:
117
+ if not os.path.exists(MODEL_PATH):
118
+ return f"❌ 模型文件不存在:\n{MODEL_PATH}"
119
+ if not os.path.exists(YAML_PATH):
120
+ return f"❌ 配置文件不存在:\n{YAML_PATH}"
121
+
122
+ model = YOLO(MODEL_PATH)
123
+ with open(YAML_PATH, "r", encoding="utf-8") as f:
124
+ cfg = yaml.safe_load(f)
125
+ big_category_mapping = cfg["big_category_mapping"]
126
+ big_category_names = cfg["big_category_names"]
127
+ small_category_names = cfg["names"]
128
+ return "✅ 模型加载成功,点击「开始检测」启用摄像头检测"
129
+ except Exception as e:
130
+ return f"❌ 初始化失败:{str(e)}"
131
+
132
+
133
+ def get_ai_introduction(big_name, small_name):
134
+ """获取垃圾分类详细介绍(已替换为本地字典)"""
135
+ key = f"{big_name}/{small_name}"
136
+ intro = GARBAGE_INTRODUCTION.get(key, "未找到该垃圾类别介绍")
137
+
138
+ # 为保持与原格式兼容,返回两个部分(实际介绍已包含完整信息)
139
+ return f"{intro}/"
140
+
141
+
142
+ def process_frame(frame, is_detecting, last_detected_label, is_mirrored):
143
+ """处理帧函数,新增镜像参数"""
144
+ global model, big_category_mapping, big_category_names, small_category_names
145
+
146
+ current_introduction = "暂无检测物体"
147
+ current_label = last_detected_label
148
+
149
+ if model is None or frame is None:
150
+ return frame, current_introduction, current_label, ""
151
+
152
+ try:
153
+ # 如果需要镜像,先翻转画面
154
+ if is_mirrored:
155
+ frame = cv2.flip(frame, 1) # 水平翻转
156
+
157
+ # 格式转换:RGB(Gradio输入)→ BGR(模型处理)
158
+ frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
159
+ # 模型推理
160
+ results = model(frame_bgr, conf=0.5, imgsz=640)
161
+
162
+ # 绘制检测结果
163
+ pil_img = Image.fromarray(cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB))
164
+ draw = ImageDraw.Draw(pil_img)
165
+ try:
166
+ font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 20)
167
+ except:
168
+ font = ImageFont.load_default()
169
+
170
+ detected_objects = []
171
+
172
+ for result in results:
173
+ for box in result.boxes:
174
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
175
+ conf = float(box.conf[0].cpu().numpy())
176
+ small_idx = int(box.cls[0].cpu().numpy())
177
+ big_idx = big_category_mapping.get(small_idx, -1)
178
+ small_name = small_category_names.get(small_idx, "未知小类")
179
+ big_name = big_category_names.get(big_idx, "未知大类") if big_idx != -1 else "未知大类"
180
+
181
+ # 记录检测到的物体
182
+ label = f"{big_name}/{small_name}"
183
+ detected_objects.append({
184
+ "big_name": big_name,
185
+ "small_name": small_name,
186
+ "label": label,
187
+ "confidence": conf
188
+ })
189
+
190
+ # 绘制边界框
191
+ draw.rectangle([(x1, y1), (x2, y2)], outline=(0, 255, 0), width=3)
192
+
193
+ # 绘制标签背景
194
+ display_label = f"{big_name}/{small_name} {conf:.2f}"
195
+ text_bbox = draw.textbbox((x1, y1 - 25), display_label, font=font)
196
+ draw.rectangle(text_bbox, fill=(0, 255, 0))
197
+
198
+ # 绘制标签文字
199
+ draw.text((x1, y1 - 25), display_label, font=font, fill=(0, 0, 0))
200
+
201
+ # 如果有检测到的物体,获取第一个物体的AI介绍
202
+ if detected_objects and is_detecting:
203
+ # 按置信度排序,选择最可信的物体
204
+ detected_objects.sort(key=lambda x: x["confidence"], reverse=True)
205
+ best_object = detected_objects[0]
206
+ current_label = best_object["label"]
207
+
208
+ # 只有当标签变化时才重新获取介绍
209
+ if current_label != last_detected_label:
210
+ current_introduction = get_ai_introduction(best_object["big_name"], best_object["small_name"])
211
+ # 添加到历史记录
212
+ history_messages.append(f"检测到: {best_object['label']}\n{current_introduction}\n")
213
+ else:
214
+ current_introduction = "正在获取介绍..." # 保持原有介绍
215
+ else:
216
+ current_introduction = "暂无检测物体" if is_detecting else "检测已暂停"
217
+ current_label = ""
218
+
219
+ # 生成历史记录文本
220
+ history_text = "\n".join(history_messages[-10:]) # 只保留最近10条
221
+
222
+ return np.array(pil_img), current_introduction, current_label, history_text
223
+
224
+ except Exception as e:
225
+ print(f"处理帧时出错: {e}")
226
+ return frame, f"处理错误: {str(e)}", "", ""
227
+
228
+
229
+ def process_image(image, is_mirrored):
230
+ """处理上传的图片,支持镜像设置"""
231
+ if image is None:
232
+ return None, "请上传图片", ""
233
+
234
+ try:
235
+ # 转换图像格式
236
+ if isinstance(image, str):
237
+ # 如果是文件路径
238
+ image = cv2.imread(image)
239
+ image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
240
+ else:
241
+ # 如果是numpy数组
242
+ image = np.array(image)
243
+
244
+ # 应用镜像
245
+ if is_mirrored:
246
+ image = cv2.flip(image, 1)
247
+
248
+ # 处理图像
249
+ processed_image, introduction, _, history_text = process_frame(image, True, "", is_mirrored)
250
+
251
+ return processed_image, introduction, history_text
252
+ except Exception as e:
253
+ print(f"处理图片时出错: {e}")
254
+ return image, f"处理图片时出错: {str(e)}", ""
255
+
256
+
257
+ def process_video(video_path, is_mirrored):
258
+ """处理上传的视频,支持镜像设置"""
259
+ if video_path is None:
260
+ return None, "请上传视频", ""
261
+
262
+ try:
263
+ # 读取视频
264
+ cap = cv2.VideoCapture(video_path)
265
+ if not cap.isOpened():
266
+ return None, "无法打开视频文件", ""
267
+
268
+ # 获取视频信息
269
+ fps = cap.get(cv2.CAP_PROP_FPS)
270
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
271
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
272
+
273
+ # 创建临时输出文件
274
+ temp_dir = tempfile.gettempdir()
275
+ output_path = os.path.join(temp_dir, f"processed_{os.path.basename(video_path)}")
276
+
277
+ # 创建视频写入器
278
+ fourcc = cv2.VideoWriter_fourcc(*'mp4v')
279
+ out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
280
+
281
+ frame_count = 0
282
+ detected_objects = set()
283
+
284
+ while True:
285
+ ret, frame = cap.read()
286
+ if not ret:
287
+ break
288
+
289
+ # 处理每一帧
290
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
291
+
292
+ # 应用镜像
293
+ if is_mirrored:
294
+ frame_rgb = cv2.flip(frame_rgb, 1)
295
+
296
+ processed_frame, introduction, _, _ = process_frame(frame_rgb, True, "", is_mirrored)
297
+
298
+ # 转换回BGR并写入
299
+ if processed_frame is not None:
300
+ processed_frame_bgr = cv2.cvtColor(processed_frame, cv2.COLOR_RGB2BGR)
301
+ out.write(processed_frame_bgr)
302
+
303
+ frame_count += 1
304
+
305
+ # 每10帧更新一次进度
306
+ if frame_count % 100 == 0:
307
+ yield f"正在处理第 {frame_count} 帧...", ""
308
+
309
+ cap.release()
310
+ out.release()
311
+
312
+ # 生成最终介绍
313
+ if detected_objects:
314
+ objects_str = ", ".join(detected_objects)
315
+ final_introduction = f"视频中检测到的物体: {objects_str}\n请查看处理后的视频文件。"
316
+ else:
317
+ final_introduction = "视频处理完成,但未检测到特定物体。"
318
+
319
+ # 添加到历史记录
320
+ history_messages.append(f"视频处理完成: {os.path.basename(video_path)}\n{final_introduction}\n")
321
+ history_text = "\n".join(history_messages[-10:])
322
+
323
+ return output_path, final_introduction, history_text
324
+
325
+ except Exception as e:
326
+ print(f"处理视频时出错: {e}")
327
+ return None, f"处理视频时出错: {str(e)}", ""
328
+
329
+
330
+ # 创建界面
331
+ with gr.Blocks(title="垃圾分类实时检测系统", theme=gr.themes.Soft()) as demo:
332
+ # 状态变量
333
+ is_detecting = gr.State(False)
334
+ last_detected_label = gr.State("")
335
+ is_mirrored = gr.State(False) # 新增镜像状态变量
336
+
337
+ gr.Markdown("""
338
+ # 🗑️ 垃圾分类实时检测系统
339
+
340
+ **使用说明:**
341
+ 1. 等待系统状态显示「模型加载成功」
342
+ 2. 点击「开始检测」按钮开启实时检测
343
+ 3. 检测结果将直接在画面中显示边界框和分类标签
344
+ 4. AI会自动介绍检测到的垃圾类别(包含详细环境影响和健康危害分析)
345
+ 5. 可以上传图片或视频进行检测
346
+ """)
347
+
348
+ # 系统状态和控制按钮区域
349
+ with gr.Row():
350
+ status = gr.Textbox(
351
+ label="系统状态",
352
+ value="初始化中...",
353
+ interactive=False,
354
+ lines=2,
355
+ scale=4
356
+ )
357
+ with gr.Column(scale=1):
358
+ start_btn = gr.Button("▶️ 开始检测", variant="primary", size="lg")
359
+ stop_btn = gr.Button("⏹️ 停止检测", variant="secondary", size="lg")
360
+ mirror_btn = gr.Button("🔄 切换镜像", variant="secondary", size="lg") # 新增镜像按钮
361
+
362
+ # 主要显示区域
363
+ with gr.Row():
364
+ # 摄像头显示和上传区域
365
+ with gr.Column(scale=2):
366
+ with gr.Tab("实时摄像头"):
367
+ webcam = gr.Image(
368
+ sources=["webcam"],
369
+ streaming=True,
370
+ label="实时检测画面",
371
+ height=400,
372
+ type="numpy",
373
+ show_download_button=False
374
+ )
375
+
376
+ with gr.Tab("图片上传"):
377
+ image_input = gr.Image(
378
+ label="上传图片",
379
+ type="filepath",
380
+ height=400
381
+ )
382
+ image_output = gr.Image(
383
+ label="检测结果",
384
+ height=400,
385
+ show_download_button=True
386
+ )
387
+ image_btn = gr.Button("🔍 检测图片", variant="primary")
388
+
389
+ with gr.Tab("视频上传"):
390
+ video_input = gr.Video(
391
+ label="上传视频",
392
+ height=400
393
+ )
394
+ video_output = gr.Video(
395
+ label="处理后的视频",
396
+ height=400
397
+ )
398
+ video_btn = gr.Button("🎬 处理视频", variant="primary")
399
+
400
+ # AI介绍区域
401
+ with gr.Column(scale=1):
402
+ ai_introduction = gr.Textbox(
403
+ label="🧠 详细垃圾分类介绍",
404
+ value="等待检测物体...",
405
+ interactive=False,
406
+ lines=12,
407
+ max_lines=15
408
+ )
409
+
410
+ ai_history = gr.Textbox(
411
+ label="📜 历史记录",
412
+ value="",
413
+ interactive=False,
414
+ lines=10,
415
+ max_lines=15
416
+ )
417
+
418
+ gr.Markdown("""
419
+ **介绍内容说明:**
420
+ - 包含垃圾类别的详细环境影响分析
421
+ - 说明对人类和动物的健康危害
422
+ - 详细描述垃圾的具体作用和可回收性
423
+ - 两部分信息已整合为完整介绍
424
+ """)
425
+
426
+ # 页面加载时初始化模型
427
+ demo.load(init_model, inputs=[], outputs=status)
428
+
429
+
430
+ # 视频流处理函数
431
+ def video_stream(frame, detecting_state, last_label, mirror_state):
432
+ """处理视频流,新增镜像参数"""
433
+ return process_frame(frame, detecting_state, last_label, mirror_state)
434
+
435
+
436
+ # 绑定视频流处理
437
+ webcam.stream(
438
+ video_stream,
439
+ inputs=[webcam, is_detecting, last_detected_label, is_mirrored],
440
+ outputs=[webcam, ai_introduction, last_detected_label, ai_history],
441
+ show_progress="hidden"
442
+ )
443
+
444
+
445
+ # 按钮事件处理
446
+ def start_detection():
447
+ """开始检测"""
448
+ return True, "🔴 检测中...实时识别已开启"
449
+
450
+
451
+ def stop_detection():
452
+ """停止检测"""
453
+ return False, "✅ 检测已暂停,点击「开始检测」重新启用"
454
+
455
+
456
+ def toggle_mirror(current_state):
457
+ """切换镜像状态"""
458
+ new_state = not current_state
459
+ status_msg = "镜像模式已开启" if new_state else "镜像模式已关闭"
460
+ return new_state, f"ℹ️ {status_msg}"
461
+
462
+
463
+ # 图片处理
464
+ def process_image_wrapper(image, mirror_state):
465
+ """包装图片处理函数,传递镜像参数"""
466
+ return process_image(image, mirror_state)
467
+
468
+
469
+ # 视频处理
470
+ def process_video_wrapper(video, mirror_state):
471
+ """包装视频处理函数,传递镜像参数"""
472
+ if video is None:
473
+ return None, "请上传视频", ""
474
+ return process_video(video, mirror_state)
475
+
476
+
477
+ # 绑定事件
478
+ start_btn.click(
479
+ start_detection,
480
+ inputs=[],
481
+ outputs=[is_detecting, status]
482
+ )
483
+
484
+ stop_btn.click(
485
+ stop_detection,
486
+ inputs=[],
487
+ outputs=[is_detecting, status]
488
+ )
489
+
490
+ # 绑定镜像切换按钮事件
491
+ mirror_btn.click(
492
+ toggle_mirror,
493
+ inputs=[is_mirrored],
494
+ outputs=[is_mirrored, status]
495
+ )
496
+
497
+ image_btn.click(
498
+ process_image_wrapper,
499
+ inputs=[image_input, is_mirrored],
500
+ outputs=[image_output, ai_introduction, ai_history]
501
+ )
502
+
503
+ video_btn.click(
504
+ process_video_wrapper,
505
+ inputs=[video_input, is_mirrored],
506
+ outputs=[video_output, ai_introduction, ai_history]
507
+ )
508
+
509
+ # 启动界面
510
+ if __name__ == "__main__":
511
+ demo.launch(
512
+ server_name="0.0.0.0",
513
+ server_port=7860,
514
+ share=True,
515
+ inbrowser=True
516
+ )