2016-06-20 8 views
0

Ich habe einen bestimmten Teil einer Qt-Anwendung, die einfach ein Foto von einer Kamera nehmen und einen QR-Code mit der qzxing-Bibliothek dekodieren soll. Allerdings kann ich für das LEBEN von mir das blöde Foto nicht aus dem blöden Puffer holen! Ich weiß, dass die Decodierung gut funktioniert, denn wenn ich das Foto in einer Datei speichern und es dann sofort als QImage neu lade, funktioniert alles (außer natürlich, dass das Programm nicht blockiert, bis das Bild vollständig gespeichert ist, also es versuche ein Halbbild zu dekodieren, dann beim zweiten Versuch das erste Bild zu dekodieren ... AUGH)!Qt und C++ - hat jemals ein Mensch ein Programm erstellt, das erfolgreich Pufferinformationen von einer Kamera liest?

Es gibt viele Leute da draußen, die diese Frage stellen, aber niemand scheint eine KOMPLETTE Antwort zu haben. Ich habe die letzten sechs Stunden geforscht und raten und testen lassen und ich bin dabei, mir die Haare auszuziehen. Die Qt-Dokumentation für QCameraImageCapture existiert, spricht aber nicht davon, den Puffer zu übergeben oder überhaupt QImage zu übertragen. Es gibt ein paar Antworten auf SO, die ein paar Vermutungen haben, das Bild in ein QImage zu werfen, und ein paar mehr, die darüber reden, den Puffer zu finden, aber niemand hat eine vollständige Antwort - es ist alles Stückwerk. Die Dokumentation zu Qt-Beispielen ist noch nicht vollständig, und ihr Beispielprojekt (im ganzen Netz gibt es nicht viele Links) diskutiert nicht, WAS es tut.

Hier ist ein Beispiel für einige Test-Code, der läuft und kompiliert mit einem Hauptfenster.ui mit einer Schaltfläche namens "pushButton" und einem vertikalen Layout namens "verticalLayout." Was mache ich so falsch?

main.cpp

#include "mainwindow.h" 
#include <QApplication> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MainWindow w; 
    w.show(); 

    return a.exec(); 
} 

mainwindow.h

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QMainWindow> 
#include <QImage> 
#include <QCamera> 
#include <QCameraInfo> 
#include <QCameraViewfinder> 
#include <QCameraImageCapture> 
#include <qzxing/QZXing.h> 

namespace Ui { 
class MainWindow; 
} 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

private slots: 
    void cameraReceiver(int f,QVideoFrame u); 
    void on_pushButton_clicked(); 

private: 
    Ui::MainWindow *ui; 
    QCameraViewfinder *viewfinder; 
    QCamera    *invCam; 
    QCameraImageCapture *rawImage; 
    QZXing    *decoder; 
}; 

#endif // MAINWINDOW_H 

mainwindow.cpp

#include "mainwindow.h" 
#include "ui_mainwindow.h" 

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

    //build camera 
    QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); 
    foreach (const QCameraInfo &cameraInfo, cameras) { 
     if (cameraInfo.deviceName() == "/dev/video0") 
      invCam = new QCamera(cameraInfo); 

    } 

    //build decoder 
    decoder = new QZXing; 
    decoder->setDecoder(QZXing::DecoderFormat_QR_CODE); 

    //build viewfinder and link to camera 
    viewfinder = new QCameraViewfinder(this); 
    viewfinder->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); 
    ui->verticalLayout->addWidget(viewfinder); 
    invCam->setViewfinder(viewfinder); 

    //build image buffer, set camera mode to capture 
    rawImage = new QCameraImageCapture(invCam); 
    invCam->setCaptureMode(QCamera::CaptureStillImage); 
    invCam->start(); 
    viewfinder->show(); 

    connect(rawImage,SIGNAL(imageAvailable(int,QVideoFrame)),this,SLOT(cameraReceiver(int,QVideoFrame))); 
} 

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

void MainWindow::cameraReceiver(int f,QVideoFrame u) { 

    QImage currentImage(u.bits(), u.width(), u.height(), u.bytesPerLine(), QVideoFrame::imageFormatFromPixelFormat(u.pixelFormat())); 
    QString output = decoder->decodeImage(currentImage); 
    qDebug() << output; 

} 

void MainWindow::on_pushButton_clicked() 
{ 
    rawImage->setCaptureDestination(QCameraImageCapture::CaptureToBuffer); 
    rawImage->capture(); 
} 

EDIT: Derzeit auf ein Linux-Umgebung, Kamera ist eingebettet. Der Sucher zeigt nur gut, und wie ich schon sagte, ich kann Bild zu Datei kein Problem - die Kamera funktioniert gut

EDIT 2: sobald ich auf SO posten finde ich die Flippin Antwort :. Der Aufruf "connect" sollte das Signal "imageCaptured" verwenden: connect (rawImage, SIGNAL (imageCaptured (int, QImage)), dieses, SLOT (cameraReceiver (int, QImage)));

Dann hat der Puffer ein QImage sitzen direkt darin.

void MainWindow::cameraReceiver(int f,QImage u) { 

    QString output = decoder->decodeImage(u); 
    qDebug() << output; 

} 
+0

Wie ist die Kamera mit dem Computer verbunden? –

+0

Welche Plattform verwenden Sie, eingebettet? Windows? Linux? Andere? –

+0

Welche Art von Kamera (Marke und Modell)? Gibt es bestimmte Befehle, die an die Kamera gesendet werden müssen? –

Antwort

1

Ich sah Sie für sich selbst eine Lösung gefunden, aber ich Fall, dass jemand mit ihm stecken wird, ist hier ein wichtiger Hinweis, wenn jemand verwenden muss QVideoFrame:

Das Problem ist die falsche Verwendung von QVideoFrame Die Rahmen zugeordnet werden, bevor Sie darauf zugreifen können:

void MainWindow::cameraReceiver(int f,QVideoFrame u) { 
    if (u.isValid()) { 
     if(u.map(QAbstractVideoBuffer::ReadOnly)) {//map the frame 
      uchar * data = new uchar[u.mappedBytes()];//copy the buffer for QImage 
      memcpy(data, u.bits(), u.mappedBytes()); 
      QImage image(data, 
         u.width(), 
         u.height(), 
         u.bytesPerLine(), 
         QVideoFrame::imageFormatFromPixelFormat(u.pixelFormat()), 
         simpleCleanupHandler,//handles the buffer cleanup 
         data);//required for the cleanup 
      u.unmap();//unmap the frame 

      QString output = decoder->decodeImage(currentImage); 
      qDebug() << output; 
     } 
    } 
} 

Da QImage den Puffer nicht kopieren, Sie haben es zu tun auf eigene Faust. Der SimpleImageCleanupHandler sieht wie folgt aus:

static void simpleCleanupHandler(void *info) 
{ 
    delete[] (uchar*)info; 
}