2
\$\begingroup\$

I am using OpenCV 3.3 to implement a project. My project allows to detect pedestrian and car using background subtraction from video sequence which get from camera. First, I detect the object region and then apply blob tracking method to locate the location of the moving object individually.

  1. How to improve the tracking of any object as it is not able to track the object for a very long period of time.which means the same object is assigned with new tracking id.

Could you see my code and give me some optimal way to make tracking better?

int main(void) {

    VideoCapture capVideo;


    Mat frame;
    std::vector<Blob> blobs;
    bool blnFirstFrame = true;
    int frameCount = 2;
    CvScalar color;

    Point center =Point(0,0);
    std::vector<Blob> currentFrameBlobs;
    Mat frameCopy;
    Mat imgFrame2Copy;


    VideoCapture cap("/home/pawan/Downloads/4.mp4");
    if (!cap.isOpened())  // if not success, exit program
    {
        cout << "Cannot open the video cam" << endl;
        return -1;
    }

    double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
    double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video
    cout << "Frame size : " << dWidth << " x " << dHeight << endl;
    while(1){

        Mat frame;
        // Capture frame-by-frame
        cap >> frame;
        frameCopy = frame;
        // If the frame is empty, break immediately
        if (frame.empty())
            break;

        Mat gray;
        setMouseCallback( "Output", onMouse, 0 );
        if (startPoint == true and endPoint == true)
        {
            frame = draw_polylines(frame,dWidth,dHeight);
            cvtColor(frame, gray, CV_BGR2GRAY);
            equalizeHist(gray,gray);
            GaussianBlur(gray, gray, cvSize(21, 21), 0);

            if (bFirstFrame == false)
            {
                //  cout << "Refresh"<<endl;
                FirstFrame = gray;
                bFirstFrame = true;
                continue;
            }
            absdiff(FirstFrame, gray, FrameDelta);
            threshold(FrameDelta, thresh, 15, 255, THRESH_BINARY);



            dilate(thresh, thresh, structuringElement5x5);
            dilate(thresh, thresh, structuringElement5x5);
            erode(thresh, thresh, structuringElement5x5);
            imshow("thresh",thresh);
            std::vector<std::vector<cv::Point> > contours;
            findContours(thresh, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
            drawAndShowContours(thresh.size(), contours, "imgContours");

            std::vector<std::vector<cv::Point> > convexHulls(contours.size());

            for (unsigned int i = 0; i < contours.size(); i++) {
                cv::convexHull(contours[i], convexHulls[i]);
            }

            drawAndShowContours(thresh.size(), convexHulls, "imgConvexHulls");

            for (auto &convexHull : convexHulls) {
                Blob possibleBlob(convexHull);

                if (possibleBlob.currentBoundingRect.area() > 1000 )
                {
                    currentFrameBlobs.push_back(possibleBlob);
                    text = "OCCUPIED";
                    if(c > 0 ){
                        c--;
                        fr = FastRefreshTime;
                    }else{
                        c = RefreshTime;
                        blnFirstFrame = false;
                        fr = FastRefreshTime;
                    }

                }else {
                    text = "UNOCCUPIED";
                    if(fr > 0){
                        fr --;
                        c= RefreshTime;
                    }else{
                        fr = FastRefreshTime ;
                        blnFirstFrame = false;
                        c= RefreshTime;
                        currentFrameBlobs.clear();
                    }
                }

            }
            int intFontFace = CV_FONT_HERSHEY_SIMPLEX;
            double dblFontScale = 1;
            int intFontThickness = 2;
            cv::putText(frame, text,Point (10,40),intFontFace, dblFontScale, SCALAR_GREEN, intFontThickness);
            drawAndShowContours(thresh.size(), currentFrameBlobs, "imgCurrentFrameBlobs");
            if (blnFirstFrame == true) {
                for (auto &currentFrameBlob : currentFrameBlobs) {
                    blobs.push_back(currentFrameBlob);
                }
            }
            else {
                matchCurrentFrameBlobsToExistingBlobs(blobs, currentFrameBlobs);
            }

            drawAndShowContours(thresh.size(), blobs, "imgBlobs");

            imgFrame2Copy = frame.clone();          // get another copy of frame 2 since we changed the previous frame 2 copy in the processing above

            drawBlobInfoOnImage(blobs, frameCopy);

            bool blnAtLeastOneBlobCrossedTheLine = checkIfBlobsCrossedTheLine(blobs);

            if (blnAtLeastOneBlobCrossedTheLine == true) {
                cv::line(frame, startingPoint, endingPoint, SCALAR_BLACK, 2);
            }
            else {
                cv::line(frame, startingPoint, endingPoint, SCALAR_GREEN, 2);
            }

            //  drawCarCountOnImage(carCount, frameCopy);
            frame = frameCopy.clone();

            //frame = detect(frame,dWidth,dHeight);

        }
        cv::imshow("Output", frame);

        // now we prepare for the next iteration

        currentFrameBlobs.clear();

        blnFirstFrame = false;
        frameCount++;
        char c=(char)waitKey(25);
        if(c==27)
            break;

    }


    // note that if the user did press esc, we don't need to hold the windows open, we can simply let the program end which will close the windows


}


void matchCurrentFrameBlobsToExistingBlobs(std::vector<Blob> &existingBlobs, std::vector<Blob> &currentFrameBlobs) {

    for (auto &existingBlob : existingBlobs) {

        existingBlob.blnCurrentMatchFoundOrNewBlob = false;

        existingBlob.predictNextPosition();
    }

    for (auto &currentFrameBlob : currentFrameBlobs) {

        int intIndexOfLeastDistance = 0;
        double dblLeastDistance = 100.0;

        for (unsigned int i = 0; i < existingBlobs.size(); i++) {

            if (existingBlobs[i].blnStillBeingTracked == true) {

                double dblDistance = distanceBetweenPoints(currentFrameBlob.centerPositions.back(), existingBlobs[i].predictedNextPosition);

                if (dblDistance < dblLeastDistance) {
                    dblLeastDistance = dblDistance;
                    intIndexOfLeastDistance = i;
                }
            }
        }

        if (dblLeastDistance < currentFrameBlob.dblCurrentDiagonalSize * 0.5) {
            addBlobToExistingBlobs(currentFrameBlob, existingBlobs, intIndexOfLeastDistance);
        }
        else {
            addNewBlob(currentFrameBlob, existingBlobs);
        }

    }

    for (auto &existingBlob : existingBlobs) {

        if (existingBlob.blnCurrentMatchFoundOrNewBlob == false) {
            existingBlob.intNumOfConsecutiveFramesWithoutAMatch++;
        }

        if (existingBlob.intNumOfConsecutiveFramesWithoutAMatch >= 10) {
            existingBlob.blnStillBeingTracked = false;
        }

    }

}


void addBlobToExistingBlobs(Blob &currentFrameBlob, std::vector<Blob> &existingBlobs, int &intIndex) {

    existingBlobs[intIndex].currentContour = currentFrameBlob.currentContour;
    existingBlobs[intIndex].currentBoundingRect = currentFrameBlob.currentBoundingRect;

    existingBlobs[intIndex].centerPositions.push_back(currentFrameBlob.centerPositions.back());

    existingBlobs[intIndex].dblCurrentDiagonalSize = currentFrameBlob.dblCurrentDiagonalSize;
    existingBlobs[intIndex].dblCurrentAspectRatio = currentFrameBlob.dblCurrentAspectRatio;

    existingBlobs[intIndex].blnStillBeingTracked = true;
    existingBlobs[intIndex].blnCurrentMatchFoundOrNewBlob = true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void addNewBlob(Blob &currentFrameBlob, std::vector<Blob> &existingBlobs) {

    currentFrameBlob.blnCurrentMatchFoundOrNewBlob = true;

    existingBlobs.push_back(currentFrameBlob);
}


double distanceBetweenPoints(cv::Point point1, cv::Point point2) {

    int intX = abs(point1.x - point2.x);
    int intY = abs(point1.y - point2.y);

    return(sqrt(pow(intX, 2) + pow(intY, 2)));
}

///////////////////////////////////////////////////////////////////////////////////////////////////
void drawAndShowContours(cv::Size imageSize, std::vector<std::vector<cv::Point> > contours, std::string strImageName) {
    cv::Mat image(imageSize, CV_8UC3, SCALAR_BLACK);

    cv::drawContours(image, contours, -1, SCALAR_WHITE, -1);

    //cv::imshow(strImageName, image);
}


void drawAndShowContours(cv::Size imageSize, std::vector<Blob> blobs, std::string strImageName) {

    cv::Mat image(imageSize, CV_8UC3, SCALAR_BLACK);

    std::vector<std::vector<cv::Point> > contours;

    for (auto &blob : blobs) {
        if (blob.blnStillBeingTracked == true) {
            contours.push_back(blob.currentContour);
        }
    }

    cv::drawContours(image, contours, -1, SCALAR_WHITE, -1);

    //  cv::imshow(strImageName, image);
}


bool checkIfBlobsCrossedTheLine(std::vector<Blob> &blobs) {
    bool blnAtLeastOneBlobCrossedTheLine = false;

    for (auto blob : blobs) {

        if (blob.blnStillBeingTracked == true && blob.centerPositions.size() >= 2) {
            int prevFrameIndex = (int)blob.centerPositions.size() - 2;
            int currFrameIndex = (int)blob.centerPositions.size() - 1;
            //  if (text == "Occupied") {
            if (fenceSide == "left")
            {

                //the object detected object is passing from outer area to inner area of the fence so action need to be taken
                //the object detected object is passing from inner area to outer area of the fence no action has to taken

                if (blob.centerPositions[prevFrameIndex].x > startingPoint.x && blob.centerPositions[currFrameIndex].x <= startingPoint.x && blob.centerPositions[currFrameIndex].y > startingPoint.y && blob.centerPositions[prevFrameIndex].y > startingPoint.y)
                {
                    status = "Intruder Alert!Alarm is triggered";
                    cout << status << endl;

                    blob.lastDetectStatus = blob.detectArea;
                    blnAtLeastOneBlobCrossedTheLine = true;
                    //  bAlarm = true;
                }
                else if (blob.centerPositions[prevFrameIndex].x < startingPoint.x && blob.centerPositions[currFrameIndex].x >= startingPoint.x && blob.centerPositions[currFrameIndex].y > startingPoint.y && blob.centerPositions[prevFrameIndex].y > startingPoint.y)
                {
                    status = "No Intruder alert";
                    cout << status << endl;
                    blob.lastDetectStatus = blob.detectArea;
                }
                //Detection in the inner area
                if (blob.centerPositions[prevFrameIndex].x < startingPoint.x && blob.centerPositions[currFrameIndex].x <= startingPoint.x && blob.centerPositions[currFrameIndex].y > startingPoint.y && blob.centerPositions[prevFrameIndex].y > startingPoint.y)
                {
                    status = "Detected object is in inner Area";
                    cout << status << endl;
                    blob.detectArea = "inner";
                }

                else if (blob.centerPositions[prevFrameIndex].x > endingPoint.x && blob.centerPositions[currFrameIndex].x >= endingPoint.x && blob.centerPositions[currFrameIndex].y > startingPoint.y && blob.centerPositions[prevFrameIndex].y > startingPoint.y)
                {
                    status = "Detected object is in outer Area";
                    cout << status << endl;

                    blob.detectArea = "outer";
                    //  bPrealarm = true;
                }

                if (blob.lastDetectStatus == "")
                {
                    blob.lastDetectStatus = blob.detectArea;

                }

            }
            else if (fenceSide == "right") {
                if (blob.centerPositions[prevFrameIndex].x < startingPoint.x && blob.centerPositions[currFrameIndex].x >= startingPoint.x && blob.centerPositions[currFrameIndex].y > startingPoint.y && blob.centerPositions[prevFrameIndex].y > startingPoint.y)
                {
                    status = "Intruder Alert!Alarm is triggered";
                    cout << status << endl;
                    blob.lastDetectStatus = blob.detectArea;
                    blnAtLeastOneBlobCrossedTheLine = true;
                    //  bAlarm = true;
                }
                //the object detected object is passing from inner area to outer area of the fence no action has to taken
                else if (blob.centerPositions[prevFrameIndex].x > startingPoint.x && blob.centerPositions[currFrameIndex].x <= startingPoint.x && blob.centerPositions[currFrameIndex].y > startingPoint.y && blob.centerPositions[prevFrameIndex].y > startingPoint.y)
                    status = "No Intruder alert";
                cout << status << endl;
                blob.lastDetectStatus = blob.detectArea;

                //Detection in the inner area
                if (blob.centerPositions[prevFrameIndex].x > endingPoint.x && blob.centerPositions[currFrameIndex].x >= endingPoint.x && blob.centerPositions[currFrameIndex].y > startingPoint.y && blob.centerPositions[prevFrameIndex].y > startingPoint.y)
                {
                    status = "Detected object is in inner Area";
                    cout << status << endl;
                    blob.detectArea = "inner";
                }

                //#Detection in the outer area
                else if (blob.centerPositions[prevFrameIndex].x < startingPoint.x && blob.centerPositions[currFrameIndex].x <= startingPoint.x && blob.centerPositions[currFrameIndex].y > startingPoint.y && blob.centerPositions[prevFrameIndex].y > startingPoint.y)
                {
                    status = "Detected object is in outer Area";
                    cout << status << endl;
                    blob.detectArea = "outer";
                    //bPrealarm = true;
                }
                if (blob.lastDetectStatus == "")
                {
                    blob.lastDetectStatus = blob.detectArea;

                }


            }
            else if (fenceSide == "Horizontal")
            {

                if (blob.centerPositions[prevFrameIndex].y > startingPoint.y && blob.centerPositions[currFrameIndex].y <= startingPoint.y)
                {
                    status = "Intruder Alert!Alarm is triggered";
                    cout << status << endl;
                    blob.lastDetectStatus = blob.detectArea;
                    blnAtLeastOneBlobCrossedTheLine = true;
                    //  bAlarm = true;
                }
                //the object detected object is passing from inner area to outer area of the fence no action has to taken
                else if (blob.centerPositions[prevFrameIndex].y < startingPoint.y && blob.centerPositions[currFrameIndex].y >= startingPoint.y)
                {
                    status = "No Intruder alert";
                    cout << status << endl;
                    blob.lastDetectStatus = blob.detectArea;

                }//Detection in the inner area
                if (blob.centerPositions[prevFrameIndex].y > startingPoint.y && blob.centerPositions[currFrameIndex].y >= startingPoint.y)
                {
                    status = "Detected object is in inner Area";
                    cout << status << endl;
                    blob.detectArea = "inner";
                }

                else if (blob.centerPositions[prevFrameIndex].y < startingPoint.y && blob.centerPositions[currFrameIndex].y <= startingPoint.y)
                {
                    status = "Detected object is in outer Area";
                    cout << status << endl;

                    blob.detectArea = "outer";
                    //  bPrealarm = true;
                }


                if (blob.lastDetectStatus == "")
                {
                    blob.lastDetectStatus = blob.detectArea;

                }


            }



            }
        /*          if (blob.centerPositions[prevFrameIndex].y > intHorizontalLinePosition && blob.centerPositions[currFrameIndex].y <= intHorizontalLinePosition) {
                carCount++;
                blnAtLeastOneBlobCrossedTheLine = true;
            }*/
    }



    return blnAtLeastOneBlobCrossedTheLine;
}


void drawBlobInfoOnImage(std::vector<Blob> &blobs, cv::Mat &imgFrame2Copy) {

    for (unsigned int i = 0; i < blobs.size(); i++) {

        if (blobs[i].blnStillBeingTracked == true) {
            cv::rectangle(imgFrame2Copy, blobs[i].currentBoundingRect, SCALAR_RED, 2);

            int intFontFace = CV_FONT_HERSHEY_SIMPLEX;
            double dblFontScale = 1;
            int intFontThickness = 1; //(int)std::round(dblFontScale * 1.0);

            cv::putText(imgFrame2Copy, std::to_string(i), blobs[i].centerPositions.back(), intFontFace, dblFontScale, SCALAR_GREEN, intFontThickness);
        }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ if(c > 0 ){ ... }else{ ... }else { ... cv::putText(frame, text,Point ( ... what editor/IDE are you using? Don't get me wrong, but the effort you get is often proportional to the effort you give in. \$\endgroup\$ – user52292 Oct 3 '18 at 22:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.