OpenCV3.3深度神经网络DNN模块 实例7:GOTURN模型实现视频对象跟踪

发布时间 2023-08-18 09:35:59作者: 一杯清酒邀明月
  1 #include <opencv2/opencv.hpp>
  2 #include <opencv2/dnn.hpp>
  3 #include <iostream>
  4  
  5 using namespace cv;
  6 using namespace cv::dnn;
  7 using namespace std;
  8  
  9 String  goturn_model = "D:/opencv3.3/opencv/sources/samples/data/dnn/goturn.caffemodel";
 10 String goturn_prototxt = "D:/opencv3.3/opencv/sources/samples/data/dnn/goturn.prototxt";
 11  
 12 Net net;
 13 void initGoturn();
 14 Rect trackObjects(Mat& frame, Mat& prevFrame);
 15 Mat frame, prevFrame;
 16 Rect prevBB;
 17 int main(int argc, char** argv) {
 18     initGoturn();
 19     VideoCapture capture;
 20     capture.open("01.mp4");
 21     capture.read(frame);
 22     frame.copyTo(prevFrame);
 23     prevBB = selectROI(frame, true, true);
 24     namedWindow("frame", CV_WINDOW_AUTOSIZE);
 25     while (capture.read(frame)) {
 26         Rect currentBB = trackObjects(frame, prevFrame);
 27         rectangle(frame, currentBB, Scalar(0, 0, 255), 2, 8, 0);
 28  
 29         // ready for next frame
 30         frame.copyTo(prevFrame);
 31         prevBB.x = currentBB.x;
 32         prevBB.y = currentBB.y;
 33         prevBB.width = currentBB.width;
 34         prevBB.height = currentBB.height;
 35  
 36         imshow("frame", frame);
 37         char c = waitKey(50);
 38         if (c == 27) {
 39             break;
 40         }
 41     }
 42 }
 43  
 44 void initGoturn() {
 45     Ptr<Importer> importer;
 46     importer = createCaffeImporter(goturn_prototxt, goturn_model);
 47     importer->populateNet(net);
 48     importer.release();
 49 }
 50  
 51 Rect trackObjects(Mat& frame, Mat& prevFrame) {
 52     Rect rect;
 53     int INPUT_SIZE = 227;
 54     //Using prevFrame & prevBB from model and curFrame GOTURN calculating curBB
 55     Mat curFrame = frame.clone();
 56     Rect2d curBB;
 57  
 58     float padTargetPatch = 2.0;
 59     Rect2f searchPatchRect, targetPatchRect;
 60     Point2f currCenter, prevCenter;
 61     Mat prevFramePadded, curFramePadded;
 62     Mat searchPatch, targetPatch;
 63  
 64     prevCenter.x = (float)(prevBB.x + prevBB.width / 2);
 65     prevCenter.y = (float)(prevBB.y + prevBB.height / 2);
 66  
 67     targetPatchRect.width = (float)(prevBB.width * padTargetPatch);
 68     targetPatchRect.height = (float)(prevBB.height * padTargetPatch);
 69     targetPatchRect.x = (float)(prevCenter.x - prevBB.width * padTargetPatch / 2.0 + targetPatchRect.width);
 70     targetPatchRect.y = (float)(prevCenter.y - prevBB.height * padTargetPatch / 2.0 + targetPatchRect.height);
 71  
 72     copyMakeBorder(prevFrame, prevFramePadded, (int)targetPatchRect.height, (int)targetPatchRect.height, (int)targetPatchRect.width, (int)targetPatchRect.width, BORDER_REPLICATE);
 73     targetPatch = prevFramePadded(targetPatchRect).clone();
 74  
 75     copyMakeBorder(curFrame, curFramePadded, (int)targetPatchRect.height, (int)targetPatchRect.height, (int)targetPatchRect.width, (int)targetPatchRect.width, BORDER_REPLICATE);
 76     searchPatch = curFramePadded(targetPatchRect).clone();
 77  
 78     //Preprocess
 79     //Resize
 80     resize(targetPatch, targetPatch, Size(INPUT_SIZE, INPUT_SIZE));
 81     resize(searchPatch, searchPatch, Size(INPUT_SIZE, INPUT_SIZE));
 82  
 83     //Mean Subtract
 84     targetPatch = targetPatch - 128;
 85     searchPatch = searchPatch - 128;
 86  
 87     //Convert to Float type
 88     targetPatch.convertTo(targetPatch, CV_32F);
 89     searchPatch.convertTo(searchPatch, CV_32F);
 90  
 91     Mat targetBlob = blobFromImage(targetPatch);
 92     Mat searchBlob = blobFromImage(searchPatch);
 93  
 94     net.setInput(targetBlob, ".data1");
 95     net.setInput(searchBlob, ".data2");
 96  
 97     Mat res = net.forward("scale");
 98     Mat resMat = res.reshape(1, 1);
 99     //printf("width : %d, height : %d\n", (resMat.at<float>(2) - resMat.at<float>(0)), (resMat.at<float>(3) - resMat.at<float>(1)));
100  
101     curBB.x = targetPatchRect.x + (resMat.at<float>(0) * targetPatchRect.width / INPUT_SIZE) - targetPatchRect.width;
102     curBB.y = targetPatchRect.y + (resMat.at<float>(1) * targetPatchRect.height / INPUT_SIZE) - targetPatchRect.height;
103     curBB.width = (resMat.at<float>(2) - resMat.at<float>(0)) * targetPatchRect.width / INPUT_SIZE;
104     curBB.height = (resMat.at<float>(3) - resMat.at<float>(1)) * targetPatchRect.height / INPUT_SIZE;
105  
106     //Predicted BB
107     Rect boundingBox = curBB;
108     return boundingBox;
109 }