fanfuhan OpenCV 教學090 ~ opencv-090-視頻分析(對象移動 偵測/抓取/標記/定位/分析/軌跡繪製)
fanfuhan OpenCV 教學090 ~ opencv-090-視頻分析(對象移動 偵測/抓取/標記/定位/分析/軌跡繪製)
資料來源: https://fanfuhan.github.io/
https://fanfuhan.github.io/2019/05/08/opencv-090/
GITHUB:https://github.com/jash-git/fanfuhan_ML_OpenCV
移動對象分析,我們可以繪製對象運行軌跡曲線,這個主要是根據移動對象窗口輪廓,獲取中心位置,然後使用中心位置進行替換即可得到。大致的程序步驟如下:
01.初始化路徑點尺寸
02.對每幀的預測輪廓提取中心位置添加到路徑數組
03.繪製路徑曲線
C++
#include <opencv2/opencv.hpp>" #include <iostream> using namespace cv; using namespace std; Mat image; bool selectObject = false; int trackObject = 0; bool showHist = true; Point origin; Rect selection; int vmin = 10, vmax = 256, smin = 30; int main(int argc, const char** argv) { // VideoCapture cap(0); VideoCapture cap("D:/images/video/balltest.mp4"); Rect trackWindow; int hsize = 16; float hranges[] = { 0,180 }; const float* phranges = hranges; if (!cap.isOpened()) { printf("could not open camera...\n"); return -1; } namedWindow("Histogram", WINDOW_AUTOSIZE); namedWindow("CamShift Demo", WINDOW_AUTOSIZE); Mat frame, hsv, hue, mask, hist, histimg = Mat::zeros(200, 320, CV_8UC3), backproj; bool paused = false; cap.read(frame); Rect selection = selectROI("CamShift Demo", frame, true, false); vector<Point> tracking_path; while (true) { bool ret = cap.read(frame); if (!ret) break; frame.copyTo(image); cvtColor(image, hsv, COLOR_BGR2HSV); int _vmin = vmin, _vmax = vmax; inRange(hsv, Scalar(26, 43, 46), Scalar(34, 255, 255), mask); int ch[] = { 0, 0 }; hue.create(hsv.size(), hsv.depth()); mixChannels(&hsv, 1, &hue, 1, ch, 1); if (trackObject <= 0) { // Object has been selected by user, set up CAMShift search properties once Mat roi(hue, selection), maskroi(mask, selection); calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges); normalize(hist, hist, 0, 255, NORM_MINMAX); trackWindow = selection; trackObject = 1; // Don't set up again, unless user selects new ROI histimg = Scalar::all(0); int binW = histimg.cols / hsize; Mat buf(1, hsize, CV_8UC3); for (int i = 0; i < hsize; i++) buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180. / hsize), 255, 255); cvtColor(buf, buf, COLOR_HSV2BGR); for (int i = 0; i < hsize; i++) { int val = saturate_cast<int>(hist.at<float>(i)*histimg.rows / 255); rectangle(histimg, Point(i*binW, histimg.rows), Point((i + 1)*binW, histimg.rows - val), Scalar(buf.at<Vec3b>(i)), -1, 8); } } // Perform CA-MeanShift calcBackProject(&hue, 1, 0, hist, backproj, &phranges); backproj &= mask; RotatedRect trackBox = CamShift(backproj, trackWindow, TermCriteria(TermCriteria::EPS | TermCriteria::COUNT, 10, 1)); if (trackBox.center.x>0 && trackBox.center.y>0) tracking_path.push_back(trackBox.center); ellipse(image, trackBox, Scalar(0, 0, 255), 3, LINE_AA); for (int i = 1; i < tracking_path.size(); i++) { line(image, tracking_path[i - 1], tracking_path[i], Scalar(255, 0, 0), 2, 8, 0); } imshow("CamShift Demo", image); imshow("Histogram", histimg); char c = (char)waitKey(50); if (c == 27) break; } return 0; }
Python
""" 视频分析(对象移动轨迹绘制) """ import cv2 as cv import numpy as np cap = cv.VideoCapture('images/balltest.mp4') if not cap.isOpened(): print("could not read video") exit(0) # 读取第一帧 ret, frame = cap.read() # 选择ROI区域 x, y, w, h = cv.selectROI("CAM Demo", frame, True, False) track_window = (x, y, w, h) # 获取ROI直方图 roi = frame[y:y + h, x:x + w] hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV) mask = cv.inRange(hsv_roi, (26, 43, 46), (34, 255, 255)) roi_hist = cv.calcHist([hsv_roi], [0], mask, [180], [0, 180]) cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX) # 搜索跟踪分析 tracking_path = [] term_crit = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1) while True: ret, frame = cap.read() if not ret: break hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1) # 搜索更新roi区域,保持运行轨迹 track_box = cv.CamShift(dst, track_window, term_crit) track_window = track_box[1] pt = np.int32(track_box[0][0]) if pt[0] > 0 and pt[1] > 0: tracking_path.append(pt) # 绘制窗口 cv.ellipse(frame, track_box[0], (0, 0, 255), 3, 8) # 绘制运动轨迹 if len(tracking_path) > 40: tracking_path = tracking_path[-40:-1] for i in range(1, len(tracking_path)): cv.line(frame, (tracking_path[i-1][0], tracking_path[i-1][1]), (tracking_path[i][0], tracking_path[i][1]), (255, 0, 0), 2, 8, 0) cv.imshow("CAM Demo", frame) k = cv.waitKey(50) & 0xff if k == 27: break cv.destroyAllWindows() cap.release()