откройте веб-камеру с OpenCV и покажите ее с помощью QLabel — белое окно

Я работаю на 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?

Спасибо!

6

Решение

У меня нет большого опыта, но я вижу, что может пойти не так:

 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;
}
6

Другие решения

Попробуйте это в 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()));
1

Если вы хотите запустить 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;
0
По вопросам рекламы [email protected]