#c #opencv #qt5 #ubuntu-16.04 #histogram
#c #opencv #qt5 #ubuntu-16.04 #гистограмма
Вопрос:
Я пытаюсь получить гистограмму в реальном времени из видеопотока с моей веб-камеры. Но я застрял в точке, где захвачен только первый кадр видео и показана эквивалентная ему гистограмма. Кроме того, я использую 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( amp;bgr_planes[0], 1, 0, Mat(), b_hist, 1, amp;histSize, amp;histRange, uniform, accumulate );
calcHist( amp;bgr_planes[1], 1, 0, Mat(), g_hist, 1, amp;histSize, amp;histRange, uniform, accumulate );
calcHist( amp;bgr_planes[2], 1, 0, Mat(), r_hist, 1, amp;histSize, amp;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;
}
показывает выходные данные моего кода. Кто-нибудь может подсказать мне, как мне следует работать с этим кодом, чтобы получить гистограмму в реальном времени?
Ответ №1:
В конце цикла захвата вы используете waitKey(0)
функцию OpenCV, которая ожидает нажатия клавиши. Параметр integer указывает, как долго (в миллисекундах) функция ожидает нажатия клавиши. Значение 0 означает, что нужно дождаться нажатия клавиши. Вот почему ваша программа останавливается после первого кадра. Вам нужно будет нажать любую клавишу, чтобы просмотреть следующий кадр (также после удаления, exit(0)
которое завершает работу программы).
Если вы хотите просмотреть видеопоток, вы можете использовать меньшее значение, например, 10 для ожидания всего 10 мс, что позволяет использовать частоту кадров до 100 кадров в секунду.
Также вам следует удалить exit
функцию, поскольку эта функция завершит работу вашей программы после завершения работы waitKey
функции в ожидании нажатия клавиши.
В качестве дополнительного примечания: waitKey
функция также возвращает число, указывающее, какая клавиша была нажата. Вы могли бы использовать это для запуска различных режимов работы вашей программы, например, для завершения вашей программы.
Ответ №2:
В вашем waitKey(0)
цикле есть exit(0)
и while(true)
. Не заглядывая в источник waitKey
, я могу сделать следующее предположение: Вы получаете гистограмму один раз, затем нажимаете кнопку, после чего она завершается.
Я подозреваю, что если вы уберете из своей программы вызовы waitKey
и exit
, вы получите то, что хотите.