计算机毕设指导师
⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。
⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!也可以在主页上或文末下与博主交流~~
⚡⚡Java、Python、小程序、大数据实战项目集](https://blog.csdn.net/2301_80395604/category_12487856.html)
⚡⚡文末获取源码
温馨提示:文末有CSDN平台官方免费提供的博客联系方式!
温馨提示:文末有CSDN平台官方免费提供的博客联系方式!
温馨提示:文末有CSDN平台官方免费提供的博客联系方式!
电子垃圾图像分类系统-简介
这套电子垃圾图像分类系统是纯Python技术栈做的:后端是Django框架,前端是Vue2,中间靠接口通信,属于典型的前后端分离毕设项目。它要做的事情是把图片里的东西分到17个类别里,10类电子设备加7类混合材料,比如电池、键盘、微波炉、手机、鼠标、电路板、打印机、电视机、洗衣机是一组,纸板、玻璃、金属、有机物、纸张、塑料、其他垃圾是另一组。数据集有6782张图,来自Kaggle公开数据集,每类样本量都在395到400张之间,分布很均衡。数据这一步做得比较细:先对全量图片做了校验和画像,统计了分辨率、色彩模式、损坏率这些指标,又用工具查出了重复图和疑似错标的样本;划分训练、验证、测试集的时候按7比1.5比1.5来,重复的图片会被归到同一个集合里,避免测试指标虚高。模型训练用的是ResNet-50做迁移学习,开标签平滑来容忍数据里少量噪声,配合早停机制,65轮左右就收敛了,测试集上Macro-F1到0.96左右。训好的模型导出成ONNX文件,网站后端加载它来推理,推理时还配了能量分数和KNN两道门做域外判断,遇到训练集里没见过的东西会给出提示而不是硬分类。网页端给了图片、视频、摄像头三种识别方式,每次识别的记录都会落库,历史页面支持搜索、分页、看详情,管理员还能管理用户。首页的数据大屏用ECharts画了六张图,识别总量和各类别分布一目了然。
电子垃圾图像分类系统-核心功能
- 图片识别
上传一张或多张图片,后端预处理后交给模型推理,返回TopK分类结果和置信度,页面上能看到每张图识别成了什么、把握有多大。 - 视频识别
本地选一个视频播放,系统在关键帧位置自动抽帧送模型识别,适合演示一段画面里不同物品陆续出现的过程。 - 摄像头实时识别
打开电脑摄像头定时抓帧识别,拿着实物对着镜头就能看到识别结果实时变化,是答辩演示环节最直观的一个功能。 - 识别历史管理
每次识别自动落库,历史页面支持条件搜索、分页浏览,点进详情能看到原图、识别类别和完整字段信息,不想要的记录可以删除。 - 数据大屏
用ECharts画了六张图,加上识别总数统计,把系统运行以来的识别情况汇总展示,深色主题视觉效果也不错。 - 用户与权限
分管理员和普通用户两种角色,支持注册登录,管理员可以管理用户账号,普通用户有自己的个人中心和修改密码入口,两边看到的菜单不一样。
电子垃圾图像分类系统-视频
基于深度学习的电子垃圾与混合材料图像分类系统实战
电子垃圾图像分类系统-图片展示












电子垃圾图像分类系统-代码
python
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("EwasteClassificationStats").master("local[*]").getOrCreate()
# ========== 核心功能1:图像识别推理处理(图片上传 -> 预处理 -> ONNX推理 -> 域外判断 -> 落库) ==========
def ai_predict(request):
upload = request.FILES.get('image')
if upload is None:
return JsonResponse({'code': 1, 'msg': '未收到图片文件'})
save_dir = os.path.join(settings.MEDIA_ROOT, 'detection')
if not os.path.exists(save_dir):
os.makedirs(save_dir)
file_name = datetime.datetime.now().strftime('%Y%m%d%H%M%S%f') + os.path.splitext(upload.name)[1]
file_path = os.path.join(save_dir, file_name)
with open(file_path, 'wb') as fp:
for chunk in upload.chunks():
fp.write(chunk)
img = Image.open(file_path).convert('RGB')
proto = json.load(open('models/resnet50/preprocess.json', encoding='utf-8'))
img = img.resize((proto['size'], proto['size']), Image.BILINEAR)
arr = np.asarray(img, dtype=np.float32) / 255.0
arr = (arr - np.array(proto['mean'], dtype=np.float32)) / np.array(proto['std'], dtype=np.float32)
arr = arr.transpose(2, 0, 1)[np.newaxis, ...]
session = get_inference_session()
logits = session.run(None, {session.get_inputs()[0].name: arr})[0][0]
probs = softmax(logits)
energy = float(-np.log(np.sum(np.exp(logits) + 1e-9)))
ood_cfg = json.load(open('models/resnet50/inference_config.json', encoding='utf-8'))
knn_score = query_feat_bank(arr, ood_cfg)
if energy > ood_cfg['energy_threshold'] and knn_score < ood_cfg['knn_threshold']:
return JsonResponse({'code': 3, 'msg': '疑似域外对象,已拒识', 'energy': energy})
labels_zh = json.load(open('models/resnet50/labels_zh.json', encoding='utf-8'))
topk_idx = np.argsort(-probs)[:5]
topk = [{'class_id': int(i), 'name': labels_zh[str(i)], 'prob': round(float(probs[i]), 4)} for i in topk_idx]
detected = topk[0]['name']
detectionrecord.objects.create(
user_id=request.session.get('uid'), task_type='image',
image_path='media/detection/' + file_name,
detected_classes=detected, confidence=topk[0]['prob'],
topk_json=json.dumps(topk, ensure_ascii=False), is_deleted=False)
return JsonResponse({'code': 0, 'data': {'topk': topk, 'energy': round(energy, 4)}})
# ========== 核心功能2:识别历史分页查询与条件搜索(归属校验+软删过滤+关键词匹配) ==========
def detectionrecord_page(request):
page = int(request.POST.get('page', 1))
limit = int(request.POST.get('limit', 10))
keyword = request.POST.get('search_keyword', '').strip()
task_type = request.POST.get('task_type', '').strip()
role = request.session.get('role')
uid = request.session.get('uid')
if role != '管理员' and not uid:
return JsonResponse({'code': 1, 'msg': '登录状态失效,请重新登录'})
queryset = detectionrecord.objects.filter(is_deleted=False)
if role != '管理员':
queryset = queryset.filter(user_id=uid)
if task_type in ('image', 'video', 'camera'):
queryset = queryset.filter(task_type=task_type)
if keyword:
queryset = queryset.filter(Q(detected_classes__icontains=keyword) | Q(image_path__icontains=keyword))
total = queryset.count()
rows = queryset.order_by('-create_time')[(page - 1) * limit: page * limit]
data_list = []
for row in rows:
item = {
'id': row.id, 'task_type': row.task_type, 'image_path': row.image_path,
'detected_classes': row.detected_classes, 'confidence': float(row.confidence),
'create_time': row.create_time.strftime('%Y-%m-%d %H:%M:%S')}
img_abs = os.path.join(settings.BASE_DIR, row.image_path)
if os.path.exists(img_abs):
with open(img_abs, 'rb') as fp:
item['thumb_base64'] = 'data:image/jpeg;base64,' + base64.b64encode(make_thumb(fp.read())).decode()
data_list.append(item)
return JsonResponse({'code': 0, 'data': {'total': total, 'list': data_list, 'page': page, 'limit': limit}})
# ========== 核心功能3:识别数据大屏聚合统计(六图数据+总数对账,Spark侧做分组汇总) ==========
def recognition_dash(request):
uid = request.session.get('uid')
if not uid:
return JsonResponse({'code': 1, 'msg': '登录状态失效,请重新登录'})
role = request.session.get('role')
df = spark.read.jdbc(url=SPARK_JDBC_URL, table='detectionrecord', properties=SPARK_PROPS)
df = df.filter((df.is_deleted == False) & (df.detected_classes.isNotNull()))
if role != '管理员':
df = df.filter(df.user_id == uid)
total = df.count()
class_pdf = df.groupBy('detected_classes').count().orderBy(F.desc('count')).toPandas()
type_pdf = df.groupBy('task_type').count().toPandas()
df = df.withColumn('day', F.substring('create_time', 1, 10))
trend_pdf = df.groupBy('day').count().orderBy('day').toPandas()
conf_pdf = df.groupBy('detected_classes').agg(F.round(F.avg('confidence'), 4).alias('avg_conf')).toPandas()
hour_pdf = df.withColumn('hour', F.substring('create_time', 12, 2)).groupBy('hour').count().orderBy('hour').toPandas()
rank_pdf = df.groupBy('detected_classes').agg(F.count('id').alias('times')).orderBy(F.desc('times')).limit(5).toPandas()
charts = {
'class_bar': {'categories': class_pdf['detected_classes'].tolist(), 'values': class_pdf['count'].tolist()},
'type_pie': [{'name': r['task_type'], 'value': int(r['count'])} for _, r in type_pdf.iterrows()],
'trend_line': {'days': trend_pdf['day'].tolist(), 'values': trend_pdf['count'].tolist()},
'conf_bar': {'categories': conf_pdf['detected_classes'].tolist(), 'values': conf_pdf['avg_conf'].tolist()},
'hour_bar': {'hours': hour_pdf['hour'].tolist(), 'values': hour_pdf['count'].tolist()},
'top_rank': [{'name': r['detected_classes'], 'value': int(r['times'])} for _, r in rank_pdf.iterrows()]}
chart_total = sum(len(v) if isinstance(v, list) else len(v.get('values', [])) for v in charts.values())
return JsonResponse({'code': 0, 'data': {'total': total, 'charts': charts, 'reconcile': chart_total}})
电子垃圾图像分类系统-结语
不少同学私信问毕设选题和这个系统的细节,回复不过来啦。想深入了解这套电子垃圾图像分类系统的同学,可以去我主页看看,那边能联系到技术员,很多问题聊两句就清楚了。觉得内容有用的话,顺手点个赞、收藏一下,关注不迷路,后面还会更新别的毕设项目。有疑问也欢迎在评论区留言,看到都会回,大家一起把毕设这关稳稳过掉。
实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!
如果遇到具体的技术问题或其他需求,你也可以问我,我会尽力帮你分析和解决问题所在,支持我记得点赞、收藏,再点个关注,学习不迷路!~~