仰起头让泪水倒回去

仰起头让泪水倒回去

0个粉丝

1

问答

0

专栏

0

资料

仰起头让泪水倒回去  发布于  2020-11-30 12:08:51
采纳率 0%
1个问答
1505

大佬们,有人研究利用opencv进行视频车流统计的吗

 
大佬们,有人研究利用opencv进行视频车流统计的吗
我来回答
回答1个
时间排序
认可量排序

1

0个粉丝

1

问答

16

专栏

6

资料

1 2020-12-02 18:01:53
认可0

ifndef MY_BLOB

define MY_BLOB

include

include

include

///
class Blob {
public:
// member variables ///
std::vector currentContour;

cv::Rect currentBoundingRect;

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

double dblCurrentDiagonalSize;
double dblCurrentAspectRatio;

bool blnCurrentMatchFoundOrNewBlob;

bool blnStillBeingTracked;

int intNumOfConsecutiveFramesWithoutAMatch;

cv::Point predictedNextPosition;

// function prototypes 
Blob(std::vector<cv::Point> _contour);
void predictNextPosition(void);

};

endif // MY_BLOB

// Blob.cpp

include “Blob.h”

///
Blob::Blob(std::vector _contour) {

currentContour = _contour;

currentBoundingRect = cv::boundingRect(currentContour);

cv::Point currentCenter;

currentCenter.x = (currentBoundingRect.x + currentBoundingRect.x + currentBoundingRect.width) / 2;
currentCenter.y = (currentBoundingRect.y + currentBoundingRect.y + currentBoundingRect.height) / 2;

centerPositions.push_back(currentCenter);

dblCurrentDiagonalSize = sqrt(pow(currentBoundingRect.width, 2) + pow(currentBoundingRect.height, 2));

dblCurrentAspectRatio = (float)currentBoundingRect.width / (float)currentBoundingRect.height;

blnStillBeingTracked = true;
blnCurrentMatchFoundOrNewBlob = true;

intNumOfConsecutiveFramesWithoutAMatch = 0;

}

///
void Blob::predictNextPosition(void) {

int numPositions = (int)centerPositions.size();

if (numPositions == 1) {

    predictedNextPosition.x = centerPositions.back().x;
    predictedNextPosition.y = centerPositions.back().y;

}
else if (numPositions == 2) {

    int deltaX = centerPositions[1].x - centerPositions[0].x;
    int deltaY = centerPositions[1].y - centerPositions[0].y;

    predictedNextPosition.x = centerPositions.back().x + deltaX;
    predictedNextPosition.y = centerPositions.back().y + deltaY;

}
else if (numPositions == 3) {

    int sumOfXChanges = ((centerPositions[2].x - centerPositions[1].x) * 2) +
        ((centerPositions[1].x - centerPositions[0].x) * 1);

    int deltaX = (int)std::round((float)sumOfXChanges / 3.0);

    int sumOfYChanges = ((centerPositions[2].y - centerPositions[1].y) * 2) +
        ((centerPositions[1].y - centerPositions[0].y) * 1);

    int deltaY = (int)std::round((float)sumOfYChanges / 3.0);

    predictedNextPosition.x = centerPositions.back().x + deltaX;
    predictedNextPosition.y = centerPositions.back().y + deltaY;

}
else if (numPositions == 4) {

    int sumOfXChanges = ((centerPositions[3].x - centerPositions[2].x) * 3) +
        ((centerPositions[2].x - centerPositions[1].x) * 2) +
        ((centerPositions[1].x - centerPositions[0].x) * 1);

    int deltaX = (int)std::round((float)sumOfXChanges / 6.0);

    int sumOfYChanges = ((centerPositions[3].y - centerPositions[2].y) * 3) +
        ((centerPositions[2].y - centerPositions[1].y) * 2) +
        ((centerPositions[1].y - centerPositions[0].y) * 1);

    int deltaY = (int)std::round((float)sumOfYChanges / 6.0);

    predictedNextPosition.x = centerPositions.back().x + deltaX;
    predictedNextPosition.y = centerPositions.back().y + deltaY;

}
else if (numPositions >= 5) {

    int sumOfXChanges = ((centerPositions[numPositions - 1].x - centerPositions[numPositions - 2].x) * 4) +
        ((centerPositions[numPositions - 2].x - centerPositions[numPositions - 3].x) * 3) +
        ((centerPositions[numPositions - 3].x - centerPositions[numPositions - 4].x) * 2) +
        ((centerPositions[numPositions - 4].x - centerPositions[numPositions - 5].x) * 1);

    int deltaX = (int)std::round((float)sumOfXChanges / 10.0);

    int sumOfYChanges = ((centerPositions[numPositions - 1].y - centerPositions[numPositions - 2].y) * 4) +
        ((centerPositions[numPositions - 2].y - centerPositions[numPositions - 3].y) * 3) +
        ((centerPositions[numPositions - 3].y - centerPositions[numPositions - 4].y) * 2) +
        ((centerPositions[numPositions - 4].y - centerPositions[numPositions - 5].y) * 1);

    int deltaY = (int)std::round((float)sumOfYChanges / 10.0);

    predictedNextPosition.x = centerPositions.back().x + deltaX;
    predictedNextPosition.y = centerPositions.back().y + deltaY;

}
else {
    // should never get here
}

}

// main.cpp

include

include

include

include

include // it may be necessary to change or remove this line if not using Windows

include “Blob.h”

define SHOW_STEPS // un-comment or comment this line to show steps or not

// 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);

// 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 &intHorizontalLinePosition, int &carCount);
void drawBlobInfoOnImage(std::vector &blobs, cv::Mat &imgFrame2Copy);
void drawCarCountOnImage(int &carCount, cv::Mat &imgFrame2Copy);

///
int main(void)
{

cv::VideoCapture capVideo;

cv::Mat imgFrame1;
cv::Mat imgFrame2;

std::vector<Blob> blobs;

cv::Point crossingLine[2];

int carCount = 0;

capVideo.open("CarsDrivingUnderBridge.mp4");

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(imgFrame1);
capVideo.read(imgFrame2);

int intHorizontalLinePosition = (int)std::round((double)imgFrame1.rows * 0.35);

crossingLine[0].x = 0;
crossingLine[0].y = intHorizontalLinePosition;

crossingLine[1].x = imgFrame1.cols - 1;
crossingLine[1].y = intHorizontalLinePosition;

char chCheckForEscKey = 0;

bool blnFirstFrame = true;

int frameCount = 2;

while (capVideo.isOpened() && chCheckForEscKey != 27) 
{

    std::vector<Blob> 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<std::vector<cv::Point> > contours;

    cv::findContours(imgThreshCopy, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

    drawAndShowContours(imgThresh.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(imgThresh.size(), convexHulls, "imgConvexHulls");

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

        if (possibleBlob.currentBoundingRect.area() > 400 &&
            possibleBlob.dblCurrentAspectRatio > 0.2 &&
            possibleBlob.dblCurrentAspectRatio < 4.0 &&
            possibleBlob.currentBoundingRect.width > 30 &&
            possibleBlob.currentBoundingRect.height > 30 &&
            possibleBlob.dblCurrentDiagonalSize > 60.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);

    bool blnAtLeastOneBlobCrossedTheLine = checkIfBlobsCrossedTheLine(blobs, intHorizontalLinePosition, carCount);

    if (blnAtLeastOneBlobCrossedTheLine == true)
    {
        cv::line(imgFrame2Copy, crossingLine[0], crossingLine[1], SCALAR_GREEN, 2);
    }
    else 
    {
        cv::line(imgFrame2Copy, crossingLine[0], crossingLine[1], SCALAR_RED, 2);
    }

    drawCarCountOnImage(carCount, imgFrame2Copy);

    cv::imshow("imgFrame2Copy", 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

    if ((capVideo.get(CV_CAP_PROP_POS_FRAMES) + 1) < capVideo.get(CV_CAP_PROP_FRAME_COUNT)) 
    {
        capVideo.read(imgFrame2);
    }
    else 
    {
        std::cout << "end of video\n";
        break;
    }

    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.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 >= 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<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 &blobs, int &intHorizontalLinePosition, int &carCount) {
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 (blob.centerPositions[prevFrameIndex].y > intHorizontalLinePosition && blob.centerPositions[currFrameIndex].y <= intHorizontalLinePosition) {
            carCount++;
            blnAtLeastOneBlobCrossedTheLine = true;
        }
    }

}

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 drawCarCountOnImage(int &carCount, cv::Mat &imgFrame2Copy) {

int intFontFace = CV_FONT_HERSHEY_SIMPLEX;
double dblFontScale = (imgFrame2Copy.rows * imgFrame2Copy.cols) / 300000.0;
int intFontThickness = (int)std::round(dblFontScale * 1.5);

cv::Size textSize = cv::getTextSize(std::to_string(carCount), intFontFace, dblFontScale, intFontThickness, 0);

cv::Point ptTextBottomLeftPosition;

ptTextBottomLeftPosition.x = imgFrame2Copy.cols - 1 - (int)((double)textSize.width * 1.25);
ptTextBottomLeftPosition.y = (int)((double)textSize.height * 1.25);

cv::putText(imgFrame2Copy, std::to_string(carCount), ptTextBottomLeftPosition, intFontFace, dblFontScale, SCALAR_GREEN, intFontThickness);

}

或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区