简体   繁体   English

尽管有新的视频数据,OpenCV直方图也不会更新

[英]OpenCV histogram doesn't update, despite new video data

I'm trying to compute a histogram for each frame coming in from a single-channel black and white video stream. 我正在尝试计算来自单通道黑白视频流的每一帧的直方图。 Eventually, I'll be feeding back projections of these histograms to OpenCV's camshift function. 最终,我将这些直方图的投影反馈给OpenCV的camshift函数。

Here's my code: 这是我的代码:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include <iostream>
#include <vector>

using namespace std;
using namespace cv;

int main(int argc, char* argv[]) {

    Mat frame, back, fore, hist, image, v_hist;
    BackgroundSubtractorMOG2 bgs;
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    int bins = 8; 
    int histSize[] = { bins };
    float range[] = { 0, 255 }; //values will range from 0 to 256
    const float* histRange = { range };
    bool uniform = true, accumulate = true;

    VideoCapture cap(0);
    if (!cap.isOpened()) {
        cout << "Cannot open the video cam" << endl;
        return -1;
    }

    namedWindow("histogram",CV_WINDOW_AUTOSIZE);
    namedWindow("Foreground",CV_WINDOW_AUTOSIZE);

    for (;;) {
        if (!cap.read(frame)){
            cout << "No frame" << endl;
            break;
        }

        frame.copyTo(image);

        //***start mask computation***
        bgs.operator()(image, fore);
        bgs.getBackgroundImage(back);

        findContours(fore, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

        int idx = 0;
        for( ; idx >= 0; idx = hierarchy[idx][0] ){
            Scalar color( 255, 255, 255 );
            drawContours( fore, contours, idx, color, CV_FILLED, 8, hierarchy );
        }

        erode(fore, fore, Mat());
        erode(fore, fore, Mat());
        dilate(fore, fore, Mat());
        dilate(fore, fore, Mat());
        //****end mask computation****

        calcHist( &fore, 1, 0, Mat(), v_hist, 1, histSize, &histRange, uniform, accumulate);

        int hist_w = 512; int hist_h = 400;
        int bin_w = cvRound( (double) hist_w/ (*histSize) );

        Mat histImage( hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0) );

        normalize( v_hist, v_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

        //draw histogram
        for (int i = 1; i < *histSize; i++)
            line ( histImage, 
            Point(bin_w*(i-1), hist_h - cvRound(v_hist.at<float>(i-1)) ),
            Point( bin_w*(i), hist_h - cvRound(v_hist.at<float>(i)) ),
            Scalar( 255, 255, 255), 2, 8, 0  );

        if(!histImage.empty()) imshow("histogram", histImage);

        if(!fore.empty()) imshow("Foreground", fore);


        if (waitKey(30) >= 0) break;

    }
    return 0;
}

This is what the output initially looks like (bear in mind - at the outset, the foreground mask is all black): 这是输出最初的样子(请记住,一开始,前景遮罩全是黑色的): 初始蒙版和直方图

..but even after foreground extraction, the histogram remains unchanged: ..但即使在前景提取之后,直方图仍保持不变: 稍后,前景遮罩和直方图

It seems like this histogram applies to the first, all-black image only, which is why the line goes to y=0 starting at x=(length of x-axis)/8. 该直方图似乎仅适用于第一个全黑图像,这就是为什么线从x =(x轴的长度)/ 8开始到y = 0的原因。 This makes sense, because the histogram has 8 bins and all of the values in this original picture are 0. (FWIW: when there are only 2 bins, the line goes to y=0 starting at x=(length of x-axis)/2.) 这是有道理的,因为直方图有8个bin,此原始图片中的所有值均为0。(FWIW:当只有2个bin时,线从x =(x轴的长度)开始到y = 0 / 2)。

I've drawn lines and rectangles with OpenCV in the past, and haven't ever had to do much different from what I'm doing here, so I'm reasonably certain that this isn't an issue with any of the drawing functions. 我过去曾使用OpenCV绘制过线和矩形,并且与我在这里所做的没什么不同,因此我可以肯定地说,这与任何绘制功能都没有关系。 If that's the case, it seems like the histogram isn't updating as new video data comes in. 如果是这样,随着新视频数据的进入,直方图似乎没有更新。

Does anybody have an idea as to why this might be happening? 有谁知道为什么会这样吗?

While I haven't found out exactly why the drawn histogram isn't updating, I've done some testing and now feel confident that the histograms are changing between different frames. 虽然我还没有找出绘制的直方图为什么不更新的确切原因,但我已经进行了一些测试,现在充满信心,直方图会在不同帧之间变化。

Here's the code I've added to my previous program: 这是我添加到先前程序中的代码:

//new declarations
Mat last_hist;
bool first = true;

//code is the same, leading up to...
normalize( v_hist, v_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

if (!first){
    eq = std::equal( v_hist.begin<uchar>(), v_hist.end<uchar>(), last_hist.begin<uchar>() );
    if (eq)
        cout << "hists equal" << endl;
    else
        cout << "hists not equal" << endl;
}
else
    first = false;

//draw histogram
for (int i = 1; i < *histSize; i++)
//...

if(!frame.empty())imshow("Frame", frame);
v_hist.copyTo(last_hist);

if (waitKey(30) >= 0) break;
//from here to end is the same

Use of the STL equal() in the conditional statement after normalize() came from how to check whether two matrixes are identical in OpenCV . normalize()之后在条件语句中使用STL equal()来自如何检查OpenCV中两个矩阵是否相同

When I run this code, I'll see "hists not equal" printed for a few frames after the foreground mask is sufficiently disturbed. 当我运行此代码时,在前景蒙版受到充分干扰后,我会看到“历史不相等”打印了几帧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM