Как получить гистограмму реального видео в реальном времени с помощью OpenCV? - PullRequest
0 голосов
/ 05 марта 2019

Я пытаюсь получить гистограмму в реальном времени из видеопотока с моей веб-камеры.Но я застрял в точке, где захватывается только первый кадр видео, и отображается его эквивалентная гистограмма.Также я использую OpenCV2 в Qt Creator.Вот код:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

 /// Capture video
VideoCapture cap(0);
 if( cap.isOpened() == false )
   { exit(0); }

 while(true)
 {
    Mat frame;
    bool bSuccess = cap.read(frame);
    if (bSuccess == false)
      {
        ui->label->setText("Video camera is disconnected");
        exit(0);
      }

    /// Separate the image in 3 places ( B, G and R )
    vector<Mat> bgr_planes;
    split(frame, bgr_planes );

    /// Establish the number of bins
     int histSize = 256;

    /// Set the ranges ( for B,G,R) )
    float range[] = { 0, 256 } ;
    const float* histRange = { range };

     bool uniform = true; bool accumulate = false;

     Mat b_hist, g_hist, r_hist;

     /// Compute the histograms:
     calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
     calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
     calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );

    // Draw the histograms for B, G and R
    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 the result to [ 0, histImage.rows ]
    normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

     /// Draw for each channel
    for( int i = 1; i < histSize; i++ )
    {
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
                      Scalar( 255, 0, 0), 2, 8, 0  );
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
                      Scalar( 0, 255, 0), 2, 8, 0  );
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
                      Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
                      Scalar( 0, 0, 255), 2, 8, 0  );
    }

    /// Display
    namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE );
    imshow("calcHist Demo", histImage );
    namedWindow("Video Capture", CV_WINDOW_AUTOSIZE );
    imshow("Video Capture", frame );

    waitKey(0);

    exit(0);

 }

   }

 MainWindow::~MainWindow()
{
     delete ui;
}

This image показывает вывод моего кода.Кто-нибудь может подсказать мне, как мне поступить с этим кодом, чтобы получить гистограмму в реальном времени?

Ответы [ 2 ]

0 голосов
/ 05 марта 2019

У вас есть waitKey(0) и exit(0) в вашем while(true) цикле.Не глядя на источник waitKey, я могу сделать следующее предположение: вы получаете гистограмму один раз, затем нажимаете кнопку, затем она выходит.

Я подозреваю, что если вы возьмете waitKey иexit звонки из вашей программы, вы получите то, что вы хотите.

0 голосов
/ 05 марта 2019

В конце цикла захвата вы используете waitKey(0), что является функцией OpenCV, которая ожидает нажатия клавиши.Целочисленный параметр указывает, как долго (в миллисекундах) функция ожидает нажатия клавиши.Значение 0 означает ожидание, пока не произойдет нажатие клавиши.Вот почему ваша программа останавливается после первого кадра.Вам нужно нажать любую клавишу, чтобы увидеть следующий кадр (после удаления также exit(0), который завершает программу).

Если вы хотите увидеть видеопоток, вы можете использовать меньшее значение, например, 10 дляожидание только 10 мс с учетом частоты кадров до 100 кадров в секунду.

Также следует удалить функцию exit, поскольку эта функция завершит вашу программу после того, как функция waitKey будет завершена в ожидании нажатия клавиши.

В качестве примечания: функция waitKey также возвращает число, указывающее, какая клавиша была нажата.Вы можете использовать это для запуска различных вариантов поведения вашей программы, например, для завершения вашей программы.

...