7

私は、OpenCV と Qt ライブラリ、および VS 2010 を使用して Win7 x64 で作業しています。

OpenCV でカメラを開き、Mat から QImage に変換した後、たとえば QLabel を使用して、Qt でキャプチャされたフレームを表示したいと思います。

関数 imshow("camera", image) および 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(..)、動作します (同じ画像を持つ 2 つのウィンドウが表示されます) が、OpenCV でキャプチャされたフレームを表示しますが、これは避けたいことです。

私の質問は次のとおりです。私は何か間違っていますか?? わかりません、Mat から Qimage への変換が間違っていますか??.. または、キャプチャしたフレームを Qt だけで表示することはできませんか?

ありがとうございました!

4

3 に答える 3

9

私はあまり経験がありませんが、ここで何がうまくいかないかがわかります。

 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()ループに陥ってしまうので決して実行されないことに注意してください。

イベント ループがスタックしないようにするには、QTimerx ミリ秒ごとにウィジェットを更新する 必要があります。

 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;   
}
于 2013-02-06T13:03:21.693 に答える
1

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)

タイマーを使用して、timeoutSIGNAL をupdateウィジェットの SLOT に接続できます。20 ~ 40 ミリ秒の間隔を使用します。カメラを起動するプッシュボタンを作成する場合と同様に、次のコードをそのclickedSLOT に入れます。

QTimer *timer = new QTimer;
timer->setInterval(20);
connect(timer,SIGNAL(timeout()),this,SLOT(update()));
于 2013-02-06T15:23:55.673 に答える