Перейти к содержимому
Compvision.ru
AndreyPavlov

Подсчёт количества посетителей - C++

Recommended Posts

Доброго времени суток. Возникла необходимость считать количество людей заходящих в помещение и выходящих из него. Это я реализовал. Но еще необходимо реализовать подсчёт сколько людей находится еще в помещении.
Пример: вошло 15 человек, вышло 9, осталось в помещении 6 человек. 
если наглядно то надо что-то вроде этого - https://www.youtube.com/watch?v=W-gDfr_G7GA&t=1s

 

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
 
#include<iostream>
#include<conio.h>           // it may be necessary to change or remove this line if not using Windows
#include <fstream>      // file utils
#include <ctime>        // timestamp stuff
#include "Blob.h"
#define SHOW_STEPS            // un-comment or comment this line to show steps or not
#define FRAME_SCALE     1   // divide frame dimentions by this number
 
///////////////////////////////////////////////////////////////////////////////////////////////////
int main(void) {
    cv::VideoCapture capVideo;
    std::ofstream myfile; // log file
    cv::Mat imgFrame1;
    cv::Mat imgFrame2;
    cv::Mat imgFrame1L;
    cv::Mat imgFrame2L;
    std::vector<Blob> blobs;
    cv::Point crossingLine[2];
    int ShopCountL = 0;
    int ShopCountR = 0;
    capVideo.open("input1_2.MOV");
    if (capVideo.get(CV_CAP_PROP_FRAME_COUNT) < 2) {
        std::cout << "error: video file must have at least two frames";
        _getch();                   // it may be necessary to change or remove this line if not using Windows
        return(0);
    }
    capVideo.read(imgFrame1L);
    capVideo.read(imgFrame2L);
    int intVerticalLinePosition = (int)std::round((double)imgFrame1.cols * 0.50);
    crossingLine[0].y = 0;
    crossingLine[0].x = intVerticalLinePosition;
    crossingLine[1].y = imgFrame1.rows - 1;
    crossingLine[1].x = intVerticalLinePosition;
    char chCheckForEscKey = 0;
    bool blnFirstFrame = true;
    int frameCount = 2;
   
        imgFrame2Copy = imgFrame2.clone();          // get another copy of frame 2 since we changed the previous frame 2 copy in the processing above
        drawBlobInfoOnImage(blobs, imgFrame2Copy);
        int blnAtLeastOneBlobCrossedTheLine = checkIfBlobsCrossedTheLine(blobs, intVerticalLinePosition, ShopCountL, ShopCountR, myfile);
        if (blnAtLeastOneBlobCrossedTheLine == 1) {
            cv::line(imgFrame2Copy, crossingLine[0], crossingLine[1], SCALAR_GREEN, 2);
        }
        else if (blnAtLeastOneBlobCrossedTheLine == 2) {
            cv::line(imgFrame2Copy, crossingLine[0], crossingLine[1], SCALAR_YELLOW, 2);
        }
        else {
            cv::line(imgFrame2Copy, crossingLine[0], crossingLine[1], SCALAR_BLUE, 2);
        }
 
        drawShopCountOnImage(ShopCountL, ShopCountR, imgFrame2Copy);
        cv::imshow("People_Counting_Cross_Line", imgFrame2Copy);
        currentFrameBlobs.clear();
        imgFrame1 = imgFrame2.clone();           // move frame 1 up to where frame 2 is
        capVideo.read(imgFrame2);
        if ((capVideo.get(CV_CAP_PROP_POS_FRAMES) + 1) < capVideo.get(CV_CAP_PROP_FRAME_COUNT)) {
            capVideo.read(imgFrame2L);
            resize(imgFrame2L, imgFrame2, cv::Size(imgFrame2L.size().width / FRAME_SCALE, imgFrame2L.size().height / FRAME_SCALE));
        }
        else {
            time_t now = time(0);
            char* dt = strtok(ctime(&now), "\n");;
            std::cout << dt << ",EOF" << std::endl;
            return(0); // end?
        }
 
        blnFirstFrame = false;
        frameCount++;
        chCheckForEscKey = cv::waitKey(1);
    }
 
    if (chCheckForEscKey != 27) {               // if the user did not press esc (i.e. we reached the end of the video)
        cv::waitKey(0);                         // hold the windows open to allow the "end of video" message to show
    }
  return(0);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
bool checkIfBlobsCrossedTheLine(std::vector<Blob> &blobs, int &intVerticalLinePosition, int &ShopCountL, int &ShopCountR, std::ofstream &myfile) {
    bool blnAtLeastOneBlobCrossedTheLine = 0;
    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;
           
            //going left
            if (blob.centerPositions[prevFrameIndex].x > intVerticalLinePosition && blob.centerPositions[currFrameIndex].x <= intVerticalLinePosition) {
                ShopCountL++;[B][SIZE="3"]вычисление сколько вошло[/SIZE][/B]
            [B]вот тут должно быть вычисление сколько осталось еще внутри[/B]
                time_t now = time(0);
                char* dt = strtok(ctime(&now), "\n");;
                std::cout << dt << ",1,0 (Left)" << std::endl;
                myfile << dt << ",1,0" << std::endl;
                blnAtLeastOneBlobCrossedTheLine = 1;
            }
 
            // going right
            if (blob.centerPositions[prevFrameIndex].x < intVerticalLinePosition && blob.centerPositions[currFrameIndex].x >= intVerticalLinePosition) {
                ShopCountR++;[B]А вот тут сколько вышло[/B]
 
                time_t now = time(0);
                char* dt = strtok(ctime(&now), "\n");;
                std::cout << dt << ",0,1 (Right)" << std::endl;
                myfile << dt << ",0,1" << std::endl;
                blnAtLeastOneBlobCrossedTheLine = 2;
            }
        }
    }
    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 = blobs[i].dblCurrentDiagonalSize / 60.0;
            int intFontThickness = (int)std::round(dblFontScale * 1.0);
            cv::putText(imgFrame2Copy, std::to_string(i), blobs[i].centerPositions.back(), intFontFace, dblFontScale, SCALAR_GREEN, intFontThickness);
        }
    }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А в чём проблема? Сделать переменную типа int, которую менять при проходах?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Не совсем понял(

//going left
            if (blob.centerPositions[prevFrameIndex].x > intVerticalLinePosition && blob.centerPositions[currFrameIndex].x <= intVerticalLinePosition) {
                shopCountL++;
                shopCountR = shopCountL-1;
                time_t now = time(0);
                char* dt = strtok(ctime(&now), "\n");;
                std::cout << dt << ",1,0 (Left)" << std::endl;
                myfile << dt << ",1,0" << std::endl;
                blnAtLeastOneBlobCrossedTheLine = 1;
            }
            
            // going right
            if (blob.centerPositions[prevFrameIndex].x < intVerticalLinePosition && blob.centerPositions[currFrameIndex].x >= intVerticalLinePosition) {
                shopCountR++;
                shopCountL = shopCountR-1;
                time_t now = time(0);
                char* dt = strtok(ctime(&now), "\n");;
                std::cout << dt << ",0,1 (Right)" << std::endl;
                myfile << dt << ",0,1" << std::endl;
                blnAtLeastOneBlobCrossedTheLine = 2;
            }

При первом проходе туда обратно все правильно считает а потом счётчик увеличивается

если наглядно то надо что-то вроде этого - https://www.youtube.com/watch?v=W-gDfr_G7GA&t=1s
но не могу понять как он это сделал...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

1. Мне проблема кажется надуманной. Что сложного в подсчёте людей? Сделать плюс и минус?

2. Совсем непонятно, что делают строки shopCountR = shopCountL-1 и shopCountL = shopCountR-1.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

shopCountR, shopCountL - это счётчик на прохождение линии вход/выход. 

строки shopCountR = shopCountL-1 и shopCountL = shopCountR-1. я уже убрал так как сделал не подумав.

только скорее всего это надо сделать через условие что бы счётчик не был меньше нуля

а я пока не могу понять как это сделать. Не могли бы вы помочь?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×