如何修改OpenCV代码实现单一大目标跟踪并调整参考线方向
Solution to Your Object Tracking Issues
Let's fix your three requirements one by one: merging split contours for large objects, switching horizontal reference lines to vertical ones, and removing Firebase dependencies.
Key Modifications Explained
1. Fixing Split Contours for Large Objects
The original code detects separate contours for parts of a single large object because of minor brightness variations or gaps in the thresholded image. We'll add a morphological closing operation (dilate followed by erode) to fill small gaps and merge adjacent contours. This ensures the entire large object is captured as one contour.
2. Switching to Vertical Reference Lines
- Replace horizontal y-coordinate reference lines with vertical x-coordinate lines
- Update the line-crossing detection functions to check the x-centroid of objects instead of y-centroid
- Adjust the line drawing logic to span the full height of the frame instead of width
3. Removing Firebase Logic
We'll strip out all Firebase imports and API calls since you don't need that functionality.
Modified Full Code
import datetime import math import cv2 import numpy as np # 全局变量 width = 0 height = 0 EntranceCounter = 0 ExitCounter = 0 min_area = 3000 # 根据实际使用调整该值 _threshold = 70 # 根据实际使用调整该值 OffsetRefLines = 150 # 根据实际使用调整该值 # 检测目标是否进入监控区域(改为垂直参考线) def check_entrance_line_crossing(x, coor_x_entrance, coor_x_exit): abs_distance = abs(x - coor_x_entrance) if ((abs_distance <= 2) and (x > coor_x_exit)): return 1 else: return 0 # 检测目标是否离开监控区域(改为垂直参考线) def check_exit_line_crossing(x, coor_x_entrance, coor_x_exit): abs_distance = abs(x - coor_x_exit) if ((abs_distance <= 2) and (x < coor_x_entrance)): return 1 else: return 0 camera = cv2.VideoCapture(0) # 强制设置摄像头分辨率为640x480 camera.set(3, 640) camera.set(4, 480) ReferenceFrame = None # 调整光线时丢弃部分帧 for i in range(0, 20): (grabbed, Frame) = camera.read() while True: (grabbed, Frame) = camera.read() height = np.size(Frame, 0) width = np.size(Frame, 1) # 若无法捕获帧则终止程序 if not grabbed: break # 转换为灰度图并应用高斯模糊 GrayFrame = cv2.cvtColor(Frame, cv2.COLOR_BGR2GRAY) GrayFrame = cv2.GaussianBlur(GrayFrame, (21, 21), 0) if ReferenceFrame is None: ReferenceFrame = GrayFrame continue # 背景减法与图像处理 FrameDelta = cv2.absdiff(ReferenceFrame, GrayFrame) FrameThresh = cv2.threshold(FrameDelta, _threshold, 255, cv2.THRESH_BINARY)[1] # 新增:形态学闭运算,填充小缺口,合并相邻轮廓 kernel = np.ones((5,5), np.uint8) FrameThresh = cv2.morphologyEx(FrameThresh, cv2.MORPH_CLOSE, kernel) # 膨胀图像并查找所有轮廓 FrameThresh = cv2.dilate(FrameThresh, None, iterations=2) _, cnts, _ = cv2.findContours(FrameThresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) qtty_of_count = 0 # 绘制垂直参考线(入口线与出口线) coor_x_entrance = (width // 2) - OffsetRefLines coor_x_exit = (width // 2) + OffsetRefLines cv2.line(Frame, (coor_x_entrance, 0), (coor_x_entrance, height), (255, 0, 0), 2) cv2.line(Frame, (coor_x_exit, 0), (coor_x_exit, height), (0, 0, 255), 2) # 遍历所有检测到的轮廓 for c in cnts: # 忽略面积过小的轮廓 if cv2.contourArea(c) < min_area: continue qtty_of_count = qtty_of_count + 1 # 在目标周围绘制矩形框 (x, y, w, h) = cv2.boundingRect(c) cv2.rectangle(Frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # 计算目标质心 coor_x_centroid = (x + x + w) // 2 coor_y_centroid = (y + y + h) // 2 ObjectCentroid = (coor_x_centroid, coor_y_centroid) cv2.circle(Frame, ObjectCentroid, 1, (0, 0, 0), 5) # 调整为检测垂直参考线穿越 if (check_entrance_line_crossing(coor_x_centroid, coor_x_entrance, coor_x_exit)): EntranceCounter += 1 if (check_exit_line_crossing(coor_x_centroid, coor_x_entrance, coor_x_exit)): ExitCounter += 1 print("Total countours found: " + str(qtty_of_count)) # 在帧上绘制出入口计数并显示 cv2.putText(Frame, "Entrances: {}".format(str(EntranceCounter)), (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (250, 0, 1), 2) cv2.putText(Frame, "Exits: {}".format(str(ExitCounter)), (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) cv2.imshow("Original Frame", Frame) cv2.waitKey(1) # 释放摄像头并关闭所有窗口 camera.release() cv2.destroyAllWindows()
Additional Notes
- If you still see split contours, you can increase the size of the morphological kernel (e.g.,
(7,7)instead of(5,5)). - Adjust
min_areabased on your camera's distance to objects—larger objects need a higher threshold. - The line-crossing logic assumes entrances are from left to right past the blue line, and exits are right to left past the red line. Tweak the
check_entrance_line_crossingandcheck_exit_line_crossingfunctions if your direction needs are reversed.
内容的提问来源于stack exchange,提问作者Derek Fennessy
相关产品推荐
相关产品推荐

