计算机毕设指导师
⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流!也可以在主页上或文末下与博主交流~~ ⚡⚡Java、Python、小程序、大数据实战项目集](https://blog.csdn.net/2301_80395604/category_12487856.html)
⚡⚡文末获取源码
温馨提示:文末有CSDN平台官方免费提供的博客联系方式! 温馨提示:文末有CSDN平台官方免费提供的博客联系方式! 温馨提示:文末有CSDN平台官方免费提供的博客联系方式!
花卉图像分类识别系统-简介
本系统使用 Python 开发,任务是把花卉照片自动归到雏菊、蒲公英、玫瑰、向日葵、郁金香五个类别。模型侧基于 PyTorch 与 torchvision,采用在 ImageNet 上预训练过的 ResNet50,把原来的分类头换成五类输出,再用花卉数据做迁移学习微调。数据取自 Kaggle 公开的花卉数据集,共 4317 张,按分层抽样以 7:1.5:1.5 切成训练、验证、测试三份,保证每类在三份里的比例接近。训练时加入随机裁剪、翻转等增强手段,配合标签平滑、余弦退火学习率和验证集早停,结束后导出 ONNX 模型。网站侧由 Django 提供接口,Vue2 管理端负责界面,用户可以上传图片、上传视频抽帧或打开摄像头完成识别,页面返回类别和置信度,识别结果写入历史表。管理端另有统计页面,用几张图展示类别分布与置信度区间。
花卉图像分类识别系统-背景
选题背景 花卉的辨认在生活中出现得不少,买花、养花、带孩子认植物,都绕不开“这朵是什么花”。多数时候靠经验判断,遇到相似品种就容易犹豫。手机拍照的普及让图像变得容易获得,图像分类也有了比较成熟的公开做法,把这两件事接起来做一个小系统,条件基本具备。对本科阶段来说,公开数据集省去了采集和标注的大部分成本,五类花卉的规模对显卡要求不高,从数据整理、模型微调到服务端接入,每一步都能自己动手完成,链路完整又不容易失控。这也是选择这个课题的直接原因。 选题意义 做这个课题的意义更多落在实践上。数据这一环能让人真正理解分层划分和防泄露为什么重要,一次不小心的重复取样,后面的准确率就没有参考价值。迁移学习让人看到预训练权重的作用,也能体会到微调层数、学习率和增强强度之间的关系。把模型导出并接到网站上,则要面对输入尺寸、预处理一致性和推理耗时这些训练时不考虑的问题。结果呈现上,给出置信度而不是只给一个名字,是对模型能力边界的诚实交代。对打算继续做相关方向的同学,这套流程可以当作起点;对只是想了解图像分类怎么落地的人,它也是一份看得懂的样例。系统本身规模不大,价值主要在于把该走的步骤走完整。
花卉图像分类识别系统-核心功能
花卉图像分类识别 用户上传一张花卉照片,系统完成缩放、归一化与前向推理,返回所属类别和置信度。置信度不足或画面过于单一时给出提示,不强行输出结果。 视频抽帧识别 上传一段视频后,系统按固定间隔抽取若干帧,逐帧推理并统计各类别命中次数,以出现次数最多的类别作为整段视频的判断,同时给出该类的平均置信度。 摄像头实时识别 调用设备摄像头获取当前画面,按需截取一帧送入推理流程,结果实时显示在页面上,适合现场演示和快速试用。 识别历史管理 所有识别结果进入历史列表,支持按类别、时间范围和关键词分页查询,可查看单条详情并删除不再需要的记录。 数据统计看板 从历史记录聚合数据,展示各类别识别数量、按天的识别趋势、置信度区间分布和识别任务完成情况,用几张图呈现系统的整体使用状态。 用户与角色管理 账号分为管理员和普通用户。普通用户可使用识别功能并查看自己的历史,管理员额外拥有用户管理权限,菜单与按钮按角色下发。
花卉图像分类识别系统-视频
基于深度学习的花卉图像分类识别系统
花卉图像分类识别系统-图片展示

花卉图像分类识别系统-代码展示
spark = SparkSession.builder.appName("flower-recognition-batch").master("local[*]").config("spark.sql.shuffle.partitions", "8").config("spark.driver.memory", "2g").getOrCreate()
# ==================== 核心功能一:单张图片识别接口 ====================
def predict(request):
body = json.loads(request.body.decode("utf-8"))
img_data = body.get("image", "")
if not img_data:
return JsonResponse({"code": 400, "msg": "未收到图片数据"})
raw = base64.b64decode(img_data.split(",")[–1])
image = Image.open(io.BytesIO(raw)).convert("RGB")
if image.width < 32 or image.height < 32:
return JsonResponse({"code": 400, "msg": "图片尺寸过小,无法识别"})
if is_plain_color(image, ratio=0.92):
return JsonResponse({"code": 200, "msg": "画面内容过于单一,暂不做判断", "data": None})
tensor = preprocess(image).unsqueeze(0).to(device)
with torch.inference_mode():
logits = model(tensor)
prob = torch.softmax(logits, dim=1)[0]
conf, idx = torch.max(prob, dim=0)
conf = float(conf.item())
if conf < OOD_THRESHOLD:
return JsonResponse({"code": 200, "msg": "这张图与五类花卉的特征差距较大", "data": {"accept": False, "confidence": round(conf, 4)}})
label = LABELS_ZH[int(idx.item())]
record = DetectionRecord.objects.create(file_name=body.get("name", "未命名"), label=label, confidence=round(conf, 4), create_time=timezone.now(), user_id=request.session.get("user_id"))
thumb = image.copy()
thumb.thumbnail((320, 320))
thumb.save(os.path.join(MEDIA_THUMB, f"{record.id}.jpg"), quality=85)
return JsonResponse({"code": 200, "msg": "识别完成", "data": {"accept": True, "label": label, "confidence": round(conf, 4), "record_id": record.id}})
# ==================== 核心功能二:视频抽帧批量识别 ====================
def recognize_video(request):
video_file = request.FILES.get("file")
if video_file is None:
return JsonResponse({"code": 400, "msg": "未收到视频文件"})
temp_path = os.path.join(MEDIA_TMP, f"video_{int(time.time() * 1000)}.mp4")
with open(temp_path, "wb") as f:
for chunk in video_file.chunks():
f.write(chunk)
cap = cv2.VideoCapture(temp_path)
total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
step = max(1, total // MAX_FRAMES)
counter, conf_sum, frame_no, used = Counter(), 0.0, 0, 0
while True:
ok, frame = cap.read()
if not ok:
break
if frame_no % step == 0:
image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
label, conf = infer_image(image)
if label is not None and conf >= OOD_THRESHOLD:
counter[label] += 1
conf_sum += conf
used += 1
frame_no += 1
cap.release()
if os.path.exists(temp_path):
os.remove(temp_path)
if not counter:
return JsonResponse({"code": 200, "msg": "视频中没有识别出五类花卉", "data": None})
label, hit = counter.most_common(1)[0]
avg_conf = round(conf_sum / used, 4)
record = DetectionRecord.objects.create(file_name=video_file.name, label=label, confidence=avg_conf, frame_stat=json.dumps(dict(counter), ensure_ascii=False), create_time=timezone.now(), user_id=request.session.get("user_id"))
return JsonResponse({"code": 200, "msg": "识别完成", "data": {"label": label, "hit": hit, "frames": used, "confidence": avg_conf, "record_id": record.id}})
# ==================== 核心功能三:识别数据统计聚合 ====================
def dashboard_stats(request):
sql = "(SELECT label, confidence, DATE(create_time) AS day FROM detectionrecord WHERE deleted = 0) AS t"
frame = spark.read.jdbc(url=DB_URL, table=sql, properties=DB_PROPS)
frame.cache()
total = frame.count()
if total == 0:
frame.unpersist()
return JsonResponse({"code": 200, "msg": "暂无识别数据", "data": {}})
by_label = frame.groupBy("label").count().orderBy(F.desc("count")).collect()
by_day = frame.groupBy("day").count().orderBy("day").collect()
conf_col = F.col("confidence")
by_conf = frame.withColumn("bucket", F.when(conf_col < 0.6, "0.5-0.6").when(conf_col < 0.7, "0.6-0.7").when(conf_col < 0.8, "0.7-0.8").when(conf_col < 0.9, "0.8-0.9").otherwise("0.9-1.0")).groupBy("bucket").count().orderBy("bucket").collect()
avg_conf = frame.agg(F.round(F.avg("confidence"), 4)).collect()[0][0]
low_ratio = round(frame.filter(conf_col < OOD_THRESHOLD).count() / total, 4)
frame.unpersist()
return JsonResponse({"code": 200, "msg": "ok", "data": {"total": total, "avg_conf": float(avg_conf or 0), "low_ratio": low_ratio, "label_axis": [r["label"] for r in by_label], "label_data": [r["count"] for r in by_label], "day_axis": [str(r["day"]) for r in by_day], "day_data": [r["count"] for r in by_day], "conf_axis": [r["bucket"] for r in by_conf], "conf_data": [r["count"] for r in by_conf]}})
花卉图像分类识别系统-结语
最近把花卉识别这套东西又整理了一遍,从数据怎么切、增强开多大,到模型导出后网站怎么接,中间踩过的坑都记下来了。主页会持续更新这类图像分类的实操记录,写得不快,但都是自己跑通的。如果你也在做相关课题,可以先把这篇存着,哪天卡住了翻出来看看。有想了解的部分留在评论区,我尽量在下一篇里写清楚。
实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! 如果遇到具体的技术问题或其他需求,你也可以问我,我会尽力帮你分析和解决问题所在,支持我记得点赞、收藏,再点个关注,学习不迷路!~~
网硕互联帮助中心




评论前必须登录!
注册