Quantcast
Channel: OpenCV Q&A Forum - Latest question feed
Viewing all articles
Browse latest Browse all 600

How to calculate number of people counting inside/outside in shop?

$
0
0
Hello. How to calculate how many people are in the shop a lot ? Came out 7 people left 5 people in the shop left 2 people. Could you tell me how it can be implemented? #include #include #include #include #include // it may be necessary to change or remove this line if not using Windows #include // file utils #include // 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 // global variables /////////////////////////////////////////////////////////////////////////////// const cv::Scalar SCALAR_BLACK = cv::Scalar(0.0, 0.0, 0.0); const cv::Scalar SCALAR_WHITE = cv::Scalar(255.0, 255.0, 255.0); const cv::Scalar SCALAR_YELLOW = cv::Scalar(0.0, 255.0, 255.0); const cv::Scalar SCALAR_GREEN = cv::Scalar(0.0, 200.0, 0.0); const cv::Scalar SCALAR_RED = cv::Scalar(0.0, 0.0, 255.0); const cv::Scalar SCALAR_BLUE = cv::Scalar(255.0, 0.0, 0.0); // function prototypes //////////////////////////////////////////////////////////////////////////// void matchCurrentFrameBlobsToExistingBlobs(std::vector&existingBlobs, std::vector&currentFrameBlobs); void addBlobToExistingBlobs(Blob &currentFrameBlob, std::vector&existingBlobs, int &intIndex); void addNewBlob(Blob &currentFrameBlob, std::vector&existingBlobs); double distanceBetweenPoints(cv::Point point1, cv::Point point2); void drawAndShowContours(cv::Size imageSize, std::vector> contours, std::string strImageName); void drawAndShowContours(cv::Size imageSize, std::vector blobs, std::string strImageName); bool checkIfBlobsCrossedTheLine(std::vector&blobs, int &intVerticalLinePosition, int &ShopCountL, int &ShopCountR, std::ofstream &myfile); void drawBlobInfoOnImage(std::vector&blobs, cv::Mat &imgFrame2Copy); void drawShopCountOnImage(int &ShopCountL, int &ShopCountR, cv::Mat &imgFrame2Copy); /////////////////////////////////////////////////////////////////////////////////////////////////// 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 blobs; cv::Point crossingLine[2]; int ShopCountL = 0; int ShopCountR = 0; capVideo.open("input1_2.MOV"); //capVideo.open("rtsp://192.168.1.254/sjcam.mov"); //capVideo.open(1); // log file myfile.open("/tmp/OpenCV-" + std::string() + "-" + std::to_string(time(0)) + ".txt"); std::cout << "Logging to: \"/tmp/OpenCV-" << "-" << std::to_string(time(0)) << ".txt\"" << std::endl; myfile << "\"Timestamp\",\"Left\",\"Right\"" << std::endl; if (!capVideo.isOpened()) { // if unable to open video file std::cout << "error reading video file" << std::endl << std::endl; // show error message _getch(); // it may be necessary to change or remove this line if not using Windows return(0); // and exit program } 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); resize(imgFrame1L, imgFrame1, cv::Size(imgFrame1L.size().width / FRAME_SCALE, imgFrame1L.size().height / FRAME_SCALE)); resize(imgFrame2L, imgFrame2, cv::Size(imgFrame2L.size().width / FRAME_SCALE, imgFrame2L.size().height / FRAME_SCALE)); //int intHorizontalLinePosition = (int)std::round((double)imgFrame1.rows * 0.35); 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; while (capVideo.isOpened() && chCheckForEscKey != 27) { std::vector currentFrameBlobs; cv::Mat imgFrame1Copy = imgFrame1.clone(); cv::Mat imgFrame2Copy = imgFrame2.clone(); cv::Mat imgDifference; cv::Mat imgThresh; cv::cvtColor(imgFrame1Copy, imgFrame1Copy, CV_BGR2GRAY); cv::cvtColor(imgFrame2Copy, imgFrame2Copy, CV_BGR2GRAY); cv::GaussianBlur(imgFrame1Copy, imgFrame1Copy, cv::Size(5, 5), 0); cv::GaussianBlur(imgFrame2Copy, imgFrame2Copy, cv::Size(5, 5), 0); cv::absdiff(imgFrame1Copy, imgFrame2Copy, imgDifference); cv::threshold(imgDifference, imgThresh, 30, 255.0, CV_THRESH_BINARY); //cv::imshow("imgThresh", imgThresh); cv::Mat structuringElement3x3 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); cv::Mat structuringElement5x5 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)); cv::Mat structuringElement7x7 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7)); cv::Mat structuringElement15x15 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15)); for (unsigned int i = 0; i < 2; i++) { cv::dilate(imgThresh, imgThresh, structuringElement5x5); cv::dilate(imgThresh, imgThresh, structuringElement5x5); cv::erode(imgThresh, imgThresh, structuringElement5x5); } cv::Mat imgThreshCopy = imgThresh.clone(); std::vector> contours; cv::findContours(imgThreshCopy, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); drawAndShowContours(imgThresh.size(), contours, "imgContours"); std::vector> convexHulls(contours.size()); for (unsigned int i = 0; i < contours.size(); i++) { cv::convexHull(contours[i], convexHulls[i]); } drawAndShowContours(imgThresh.size(), convexHulls, "imgConvexHulls"); for (auto &convexHull : convexHulls) { Blob possibleBlob(convexHull); if (possibleBlob.currentBoundingRect.area() > 800 && possibleBlob.dblCurrentAspectRatio > 0.2 && possibleBlob.dblCurrentAspectRatio < 4.0 && possibleBlob.currentBoundingRect.width > 40 && possibleBlob.currentBoundingRect.height > 40 && possibleBlob.dblCurrentDiagonalSize > 90.0 && (cv::contourArea(possibleBlob.currentContour) / (double)possibleBlob.currentBoundingRect.area()) > 0.50) { currentFrameBlobs.push_back(possibleBlob); } } drawAndShowContours(imgThresh.size(), currentFrameBlobs, "imgCurrentFrameBlobs"); if (blnFirstFrame == true) { for (auto &currentFrameBlob : currentFrameBlobs) { blobs.push_back(currentFrameBlob); } } else { matchCurrentFrameBlobsToExistingBlobs(blobs, currentFrameBlobs); } drawAndShowContours(imgThresh.size(), blobs, "imgBlobs"); 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); //cv::waitKey(0); // uncomment this line to go frame by frame for debugging // now we prepare for the next iteration 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 } // 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 return(0); } /////////////////////////////////////////////////////////////////////////////////////////////////// void matchCurrentFrameBlobsToExistingBlobs(std::vector&existingBlobs, std::vector&currentFrameBlobs) { for (auto &existingBlob : existingBlobs) { existingBlob.blnCurrentMatchFoundOrNewBlob = false; existingBlob.predictNextPosition(); } for (auto &currentFrameBlob : currentFrameBlobs) { int intIndexOfLeastDistance = 0; double dblLeastDistance = 100000.; 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 >= 5) { existingBlob.blnStillBeingTracked = false; } } } /////////////////////////////////////////////////////////////////////////////////////////////////// void addBlobToExistingBlobs(Blob &currentFrameBlob, std::vector&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&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> 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 blobs, std::string strImageName) { cv::Mat image(imageSize, CV_8UC3, SCALAR_BLACK); std::vector> 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&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++; 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++; 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&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); } } } /////////////////////////////////////////////////////////////////////////////////////////////////// void drawShopCountOnImage(int &ShopCountL, int &ShopCountR, cv::Mat &imgFrame2Copy) { int intFontFace = CV_FONT_HERSHEY_SIMPLEX; double dblFontScale = (imgFrame2Copy.rows * imgFrame2Copy.cols) / 200000.0; int intFontThickness = (int)std::round(dblFontScale * 1.5); cv::Size textSizeL = cv::getTextSize("Inside: " + std::to_string(ShopCountL), intFontFace, dblFontScale, intFontThickness, 0); cv::Size textSizeR = cv::getTextSize("Outside: " + std::to_string(ShopCountR), intFontFace, dblFontScale, intFontThickness, 0); cv::Point ptTextBottomLeftPositionL, ptTextBottomLeftPositionR; ptTextBottomLeftPositionL.x = imgFrame2Copy.cols - 1 - (int)((double)textSizeL.width * 1.25); ptTextBottomLeftPositionL.y = (int)((double)textSizeL.height * 1.25); ptTextBottomLeftPositionR.x = ptTextBottomLeftPositionL.x - 350; ptTextBottomLeftPositionR.y = ptTextBottomLeftPositionL.y + (textSizeL.height) * 1.25; cv::putText(imgFrame2Copy, "Inside: " + std::to_string(ShopCountL), ptTextBottomLeftPositionL, intFontFace, dblFontScale, SCALAR_GREEN, intFontThickness); cv::putText(imgFrame2Copy, "Outside: " + std::to_string(ShopCountR), ptTextBottomLeftPositionR, intFontFace, dblFontScale, SCALAR_YELLOW, intFontThickness); }

Viewing all articles
Browse latest Browse all 600

Trending Articles