目录前言初学yolo flask时,需要此功能,Csdn、Github、B站找到很多代码,效果并不满足。 近期,再度实验,实现简单功能。 实现功能:上传图片并辨认,可以点击图片放大查看 上传视频并辨认 辨认后的文件下载功能 效果图如下文件结构如下:[code]project/ static/ 空 templates/ index.html app.py[/code]相关代码:app.py [code]import cv2 import numpy as np import torch from flask import Flask, request, jsonify, render_template import base64 import os from datetime import datetime app = Flask(__name__) # 全局变量:模子 model = None # 提前加载模子 def load_model(): global model model = torch.hub.load('', 'custom', path='yolov5s.pt', source='local') # 路由处理惩罚图片检测哀求 @app.route('/predict_image', methods=['POST']) def predict_image(): global model # 获取图像文件 file = request.files['image'] # 读取图像数据并转换为RGB格式 image_data = file.read() nparr = np.frombuffer(image_data, np.uint8) image = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED) results = model(image) image = results.render()[0] # 将图像转换为 base64 编码的字符串 _, buffer = cv2.imencode('.png', image) image_str = base64.b64encode(buffer).decode('utf-8') # 获取当前时间,并将其格式化为字符串 current_time = datetime.now().strftime('%Y%m%d%H%M%S') # 构建保存路径 save_dir = 'static' if not os.path.exists(save_dir): os.makedirs(save_dir) filename, extension = os.path.splitext(file.filename) # 获取上传文件的文件名和扩展名 save_filename = f'{filename}_{current_time}{extension}' save_path = os.path.join(save_dir, save_filename) cv2.imwrite(save_path, image) return jsonify({'image': image_str}) # 函数用于在视频帧上绘制检测结果 def detect_objects(frame, model): results = model(frame) detections = results.xyxy[0].cpu().numpy() # 获取检测结果 # 在帧上绘制检测结果 for det in detections: # 获取边界框信息 x1, y1, x2, y2, conf, class_id = det[:6] # 在帧上绘制边界框 cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) # 在帧上绘制种别和置信度 label = f'{model.names[int(class_id)]} {conf:.2f}' cv2.putText(frame, label, (int(x1), int(y1) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) return frame # 路由处理惩罚视频检测哀求 @app.route("/predict_video", methods=["POST"]) def predict_video(): global model # 从哀求中获取视频文件 video_file = request.files["video"] # 保存视频到临时文件 temp_video_path = "temp_video.mp4" video_file.save(temp_video_path) # 逐帧读取视频 video = cv2.VideoCapture(temp_video_path) # 获取视频的帧率和尺寸 fps = video.get(cv2.CAP_PROP_FPS) width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 视频写入对象 output_video_filename = f"output_video_{datetime.now().strftime('%Y%m%d%H%M%S')}.mp4" output_video_path = os.path.join("static", output_video_filename) fourcc = cv2.VideoWriter_fourcc(*"avc1") out_video = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height)) # 逐帧处理惩罚视频并进行目标检测 while True: ret, frame = video.read() if not ret: break # 进行目标检测 detection_result = detect_objects(frame, model) # 将处理惩罚后的帧写入输出视频 out_video.write(detection_result) # 开释视频对象 video.release() out_video.release() return jsonify({"output_video_path": output_video_filename}) @app.route('/') def index(): return render_template('index.html') # 初始加载模子 load_model() if __name__ == '__main__': app.run(debug=True) [/code]index.html [code]<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Object Detection</title> <style> body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f3f3f3; display: flex; justify-content: center; align-items: center; height: 100vh; flex-direction: column; } #content { text-align: center; max-width: 820px; margin-top: 20px; } h1 { color: #333; } h2 { color: #666; } input[type="file"] { margin-bottom: 10px; } .media-container { display: flex; max-width: 100%; margin-bottom: 20px; } .media-container:first-child { margin-right: 20px; /* 在第一个容器的右侧添加间隔 */ } .media-container img, .media-container video { max-width: 100%; height: auto; } .original { width: 400px; overflow: hidden; } .processed { flex: 2; /* 右边容器占据剩余空间 */ } button { padding: 10px 20px; background-color: #007bff; color: #fff; border: none; border-radius: 5px; cursor: pointer; margin-bottom: 10px; } /* 新增样式:模态框 */ .modal { display: none; /* 默认埋伏 */ position: fixed; z-index: 1; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0, 0, 0, 0.9); /* 半透明玄色背景 */ } .modal-content { margin: auto; display: block; width: 80%; max-width: 800px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); text-align: center; /* 居中显示图片 */ } .close { color: #ccc; font-size: 36px; font-weight: bold; cursor: pointer; position: absolute; top: 10px; right: 10px; } .close:hover, .close:focus { color: #fff; text-decoration: none; } #downloadButton { padding: 10px 20px; background-color: #007bff; color: #fff; border: none; border-radius: 5px; cursor: pointer; margin-bottom: 10px; } /* 新增样式:相应式图片 */ .modal-content img, .modal-content video { max-width: 100%; height: auto; } </style> </head> <body> <!-- 新增模态框 --> <div id="myModal" class="modal" onclick="closeModal()"> <div class="modal-content" id="modalContent" onclick="stopPropagation(event)"> <!-- 放大后的图片或视频将在这里显示 --> <span class="close" onclick="closeModal()">×</span> </div> </div> <div id="content"> <h1>照片/视频检测</h1> <!-- 上传图片 --> <h2>上传图片</h2> <input type="file" id="imageFile" accept="image/*" onchange="displaySelectedImage()"> <button onclick="uploadImage()">上传</button> <button id="downloadImageButton" onclick="downloadProcessedImage()">下载</button> <br> <div class="media-container"> <div class="original media-container" onclick="enlargeImage()"> <img id="uploadedImage" src="#" alt="Uploaded Image" style="display:none;"> <button id="zoomInButton" style="display:none;">Zoom In</button> </div> <div class="processed media-container" onclick="enlargeImage2()"> <img id="processedImage" src="#" alt="Processed Image" style="display:none;"> </div> </div> <br> <!-- 上传视频 --> <h2>上传视频</h2> <input type="file" id="videoFile" accept="video/mp4,video/x-m4v,video/*" onchange="displaySelectedVideo()"> <button onclick="uploadVideo()">上传</button> <button id="downloadButton" onclick="downloadProcessedVideo()">下载</button> <br> <div class="media-container"> <div class="original media-container" > <video id="uploadedVideo" src="#" controls style="display:none;"></video> </div> <div class="processed media-container"> <video id="processedVideo" controls style="display:none;"></video> </div> </div> <br> </div> <script> // 显示选择的权重文件 // 显示选择的图片并添加点击放大功能 function displaySelectedImage() { var fileInput = document.getElementById('imageFile'); var file = fileInput.files[0]; var imageElement = document.getElementById('uploadedImage'); imageElement.src = URL.createObjectURL(file); imageElement.style.display = 'inline'; document.getElementById('zoomInButton').style.display = 'inline'; } // 显示模态框并放大图片 function enlargeImage() { var modal = document.getElementById('myModal'); var modalImg = document.getElementById('modalContent'); var img = document.getElementById('uploadedImage'); modal.style.display = 'block'; modalImg.innerHTML = '<img src="' + img.src + '">'; } // 显示模态框并放大图片 function enlargeImage2() { var modal = document.getElementById('myModal'); var modalImg = document.getElementById('modalContent'); var img = document.getElementById('processedImage'); modal.style.display = 'block'; modalImg.innerHTML = '<img src="' + img.src + '">'; } // 显示选择的视频并添加点击放大功能 function displaySelectedVideo() { var fileInput = document.getElementById('videoFile'); var file = fileInput.files[0]; var videoElement = document.getElementById('uploadedVideo'); videoElement.src = URL.createObjectURL(file); videoElement.style.display = 'block'; } // 上传图片并向后端发送哀求 function uploadImage() { var fileInput = document.getElementById('imageFile'); var file = fileInput.files[0]; var formData = new FormData(); formData.append('image', file); fetch('/predict_image', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { var imageElement = document.getElementById('processedImage'); imageElement.src = 'data:image/png;base64,' + data.image; imageElement.style.display = 'inline'; document.getElementById('downloadImageButton').style.display = 'inline'; }) .catch(error => console.error('Error:', error)); } // 下载处理惩罚后的图片 function downloadProcessedImage() { var imageElement = document.getElementById('processedImage'); var url = imageElement.src; var a = document.createElement('a'); a.href = url; a.download = 'processed_image.png'; document.body.appendChild(a); a.click(); document.body.removeChild(a); } // 上传视频并向后端发送哀求 function uploadVideo() { var fileInput = document.getElementById('videoFile'); var file = fileInput.files[0]; var formData = new FormData(); formData.append('video', file); fetch('/predict_video', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { var videoElement = document.getElementById('processedVideo'); // 修改路径为正确的 Flask url_for 生成的路径 videoElement.src = '{{ url_for("static", filename="") }}' + data.output_video_path; videoElement.style.display = 'block'; var downloadButton = document.getElementById('downloadButton'); downloadButton.style.display = 'block'; }) .catch(error => console.error('Error:', error)); } // 下载处理惩罚后的视频 function downloadProcessedVideo() { var videoElement = document.getElementById('processedVideo'); var url = videoElement.src; var a = document.createElement('a'); a.href = url; a.download = 'processed_video.mp4'; document.body.appendChild(a); a.click(); document.body.removeChild(a); } // 关闭模态框 function closeModal() { var modal = document.getElementById('myModal'); modal.style.display = 'none'; } </script> </body> </html>[/code]利用说明:index.html放入templates文件夹中 运行app.py 注:此处加载模子路径更改为本身的 [code]model = torch.hub.load('', 'custom', path='yolov5s.pt', source='local')[/code]如果模子读取不到,显示 去yolov5官网,下载yolov5-master到项目文件夹 并将yolov5s.pt文件复制到yolov5-master文件夹中,修改model路径 [code]model = torch.hub.load('yolov5-master', 'custom', path='yolov5s.pt', source='local')[/code]总结到此这篇关于yolov5利用flask部署至前端实现照片\视频辨认功能的文章就介绍到这了,更多相关yolov5 flask部署前端照片视频辨认内容请搜索脚本之家以前的文章或继承浏览下面的相关文章渴望大家以后多多支持脚本之家! 来源:https://www.jb51.net/python/32809711f.htm 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
|手机版|小黑屋|梦想之都-俊月星空
( 粤ICP备18056059号 )|网站地图
GMT+8, 2025-7-1 19:01 , Processed in 0.035168 second(s), 19 queries .
Powered by Mxzdjyxk! X3.5
© 2001-2025 Discuz! Team.