本文分析了使用flask和yolov5開發html網頁時,攝像頭實時檢測無法顯示檢測框和置信度的問題,并提出了可能的解決方案。
前端代碼使用JavaScript捕獲攝像頭畫面并將其發送到后端進行處理:
<div class="row" style="padding:3%;"> <div class="col-lg-6"> <h5>輸入數據:</h5> <div><video autoplay="" id="video"></video></div> </div> <div class="col-lg-6"> <h5>輸出結果:</h5> <div class="custom-file-container__image-preview"> @@##@@</img></div> </div> </div> <script> function start() { navigator.mediaDevices.getUserMedia({ video: true }) .then(function (stream) { var video = document.querySelector('video'); video.srcObject = stream; var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); setInterval(function () { var videoWidth = video.videoWidth; var videoHeight = video.videoHeight; canvas.width = videoWidth; canvas.height = videoHeight; ctx.drawImage(video, 0, 0, videoWidth, videoHeight); var imageData = canvas.toDataURL('image/png',1); // 壓縮圖片 // 發送數據到后端 $.ajax({ type: 'POST', url: '/image_data', data: { id :$("#uid").val(), image_data: imageData }, success: function (response) { console.log(response); } }); }, 1000 / 30); // 每秒30幀 }) .catch(function (error) { console.error(error); }); } </script>
后端python代碼使用opencv處理圖像并進行視頻流傳輸:
import cv2 import time import io import base64 from flask import Flask, request, Response from PIL import Image app = Flask(__name__) # ... (假設d.detect函數已定義,用于YOLOv5檢測) ... # 視頻推流 def gen(path): cap = cv2.VideoCapture(path) while cap.isOpened(): try: start_time = time.time() success, frame = cap.read() if success: im, label, c = d.detect(frame) # YOLOv5 檢測 ret, jpeg = cv2.imencode('.png', im) if ret: frame = jpeg.tobytes() elapsed_time = time.time() - start_time print(f"frame processing time: {elapsed_time:.3f} seconds") yield (b'--framern' b'Content-Type: image/jpegrnrn' + frame + b'rnrn') else: break else: break except Exception as e: print(e) continue cap.release() # 視頻流結果 @app.route('/video_feed') def video_feed(): f = request.args.get("f") print(f'upload/{f}') return Response(gen(f'upload/{f}'), mimetype='multipart/x-mixed-replace; boundary=frame') # 前臺推流 @app.route('/image_data', methods=["POST"]) def image_data(): image_data = request.form.get('image_data') uid = request.form.get('id') try: image_data = io.BytesIO(base64.b64decode(image_data.split(',')[1])) img = Image.open(image_data) img.save(f'upload/temp{uid}.png') return "ok" except Exception as e: print(f"Error processing image: {e}") return "error" if __name__ == '__main__': app.run(debug=True)
問題可能原因及解決方案:
立即學習“前端免費學習筆記(深入)”;
-
cv2.VideoCapture(path) 路徑錯誤: path 應為正確的攝像頭索引 (例如 0 為默認攝像頭) 或 RTSP 地址。 前端代碼應將正確的攝像頭信息傳遞給后端。
-
前端未調用 /video_feed: 前端代碼缺少調用 /video_feed 接口的代碼。 應在 start() 函數中添加以下代碼:
$("#res").attr("src", "/video_feed?f=temp" + $("#uid").val());
-
錯誤處理: 后端代碼缺少更全面的錯誤處理。 建議使用 try…except 塊捕獲并處理可能的異常,例如文件IO錯誤、圖像處理錯誤等。 同時,前端也應該處理AJAX請求失敗的情況。
-
YOLOv5 檢測結果顯示: 后端代碼的 d.detect(frame) 函數應該返回包含檢測框和置信度的結果,并將其整合到 im 中,然后才能正確顯示。 需要仔細檢查 d.detect 函數的實現以及如何將檢測結果繪制到圖像上。
-
圖片格式: 確保 cv2.imencode(‘.png’, im) 編碼后的圖片格式與前端顯示的圖片格式一致。
通過修正以上幾點,特別是攝像頭路徑、前端調用后端視頻流接口以及完善錯誤處理機制,就能解決這個問題。 記住檢查YOLOv5的檢測結果是否正確地繪制在圖像上。 如果問題仍然存在,請提供完整的錯誤日志信息,以便進一步排查。