Я работаю на Win7 x64 с библиотеками OpenCV и Qt и VS 2010.
Я хотел бы открыть свою камеру с помощью OpenCV и затем показать захваченные кадры с помощью Qt, например, используя QLabel, после преобразования из Mat в QImage.
Я хочу сделать это, потому что использование функций imshow («камера», изображение) и waitKey () замедляет потоковую камеру.
Это мой код:
int main () {
QApplication a(argc, argv);
QLabel myLabel;
VideoCapture cap(0);
//namedWindow(c"camera", 1);
for (;;) {
cap >> image;
//conversion from Mat to QImage
Mat dest;
cvtColor(image, dest,CV_BGR2RGB);
QImage image1= QImage((uchar*) dest.data, dest.cols, dest.rows, dest.step, QImage::Format_RGB888);
//show Qimage using QLabel
myLabel.setPixmap(QPixmap::fromImage(image1));
myLabel.show();
//imshow("camera",image);
//if (waitKey(30)>= 0) break;
}
return a.exec();
}
Веб-камера открыта правильно и работает, но я вижу белое окно, а не захваченные кадры, как вы можете видеть на этом изображении
Если я раскомментирую: namedWindow (..), imshow(..), if(waitKey(..)
, это работает (я вижу два окна с одинаковыми изображениями), но я показываю захваченные кадры с OpenCV, и это то, чего я хочу избежать.
У меня вопрос: я в чем-то не прав ?? Я не знаю, преобразование из Mat в Qimage неправильно ?? ..
Или я не могу отображать захваченные кадры только с помощью Qt?
Спасибо!
У меня нет большого опыта, но я вижу, что может пойти не так:
for (;;) {
cap >> image;
//conversion from Mat to QImage
Mat dest;
cvtColor(image, dest,CV_BGR2RGB);
QImage image1= QImage((uchar*) dest.data, dest.cols, dest.rows, dest.step, QImage::Format_RGB888);
//show Qimage using QLabel
myLabel.setPixmap(QPixmap::fromImage(image1));
myLabel.show();
//imshow("camera",image);
//if (waitKey(30)>= 0) break;
}
Вы делаете это в тупике — это заставит ваш QLabel бесконечно обновляться, поэтому вы можете ничего не увидеть. Кроме того, если раскомментировано waitKey
помогает вам, это в значительной степени означает, что вы конвертируете данные в QImage
хорошо, но что-то другое сломано.
Обратите внимание, что a.exec()
никогда не выполнится, так как вы застрянете в цикле, но я думаю, этого было достаточно для достижения концепции.
Чтобы не застревать в цикле событий, нужно создать QTimer
и каждые x миллисекунд, чтобы обновить ваш виджет:
class VideoWindow: public QWidget
{
Q_OBJECT
public:
VideoWindow(QWidget* parent = 0): QWidget(parent), cap(0)
{
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updatePicture()));
timer->start(20);
}public slots:
void updatePicture()
{
cap >> image;
//conversion from Mat to QImage
Mat dest;
cvtColor(image, dest,CV_BGR2RGB);
QImage image1 = QImage((uchar*) dest.data, dest.cols, dest.rows, dest.step, QImage::Format_RGB888);
//show Qimage using QLabel
setPixmap(QPixmap::fromImage(image1));
}
private:
QTimer * timer;
VideoCapture cap;
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
VideoWindow w;
w.show();
app.exec();
return 0;
}
Попробуйте это в paintEvent()
виджета (widget / mainwindow), который вы хотите использовать для отображения изображения.
Откройте камеру в конструкторе виджета:
VideoCapture myVideo;
myVideo.open(0);
if(!myVideo.isOpened())
cout<<"CANNOT OPEN CAMERA"<<endl; //or you can put some error message
в paintEvent()
сделай это
myVideo >> frame;
QImage image = QImage((const unsigned char*)frame.data,frame.cols,
frame.rows,frame.step,QImage::Format_RGB888);
QRectF target(0.0,0.0,image.width(),image.height());
QRectF source(0.0,0.0,image.width(),image.height());
QPainter painter(this);
painter.drawImage(target,image,source)
используя таймер, вы можете подключить timeout
СИГНАЛ update
СЛОТ виджета. используйте интервал 20-40 мс. Например, если вы нажмете кнопку, чтобы запустить камеру, введите следующий код в clicked
SLOT.
QTimer *timer = new QTimer;
timer->setInterval(20);
connect(timer,SIGNAL(timeout()),this,SLOT(update()));
Если вы хотите запустить Capture Video in Label, вы должны написать такой код в CPP:
Этот код работает очень хорошо для меня, я надеюсь, что он также поможет вам.
void <Class name Here>::on_button_clicked(){
captureVideoInLabel.open(0);
if (captureVideoInLabel.isOpened() == false)
{
qDebug() << "Camera can't open";
return;
}
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this,
SLOT(processFrameAndUpdateGUI()));
timer->start(20);
}
void <here you need to write class name>::processFrameAndUpdateGUI()
{
Mat originalImage;
captureVideoInLabel.read(originalImage);
if (originalImage.empty() == true)
{
return;
}
QImage qOriginalImage((uchar*)originalImage.data, originalImage.cols,
originalImage.rows, originalImage.step, QImage::Format_RGB888);
ui->label->setPixmap(QPixmap::fromImage(qOriginalImage));
}
в заголовке:
private slots:
void processFrameAndUpdateGUI();
void on_button_clicked();
private:
cv::VideoCapture captureVideoInLabel;