カメラで撮影した映像を送信するプログラム



  • 現在、一台のパソコンの内蔵Webカメラで撮影した映像をUDPソケット通信で同じパソコンに送信するプログラムを書いているのですが、混乱しているのでアドバイス願います。

    目標:一台のパソコンでカメラで映像取得→UDPソケット通信→同じパソコンで映像を復元して表示
    コード詳細:sousinとjyusinの二つのコードを書いている。

    sousin:送信用プログラム Webカメラで撮影した映像を送信
    カメラ映像をOpenCVの関数を用いてキャプチャー。キャプチャーした映像をQByteArrayに変換。
    映像の幅w、高さh、ビット幅s(色の情報を考える。例:wが100ならsは3色分でs=100×3)
    UDpソケット通信QUdpSocketで同じパソコンに送信。

    jyusin:受信用プログラム 送信されてきた映像を受信して、映像に変換
    送信されてきた映像QByteArrayを解析する。映像の幅w、高さh、ビット幅sを取得する。
    そして、映像をchar*からQImage、QPixmapと変換して映像を取得。

    このような流れなのですが、映像をうまく取得できません。
    映像の取得に失敗する原因が分からず悩んでいます。
    コードものせるので、お力をお貸しください。

    sousin
    ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    mainwindow.h
    ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QUdpSocket>
    #include <QString>
    #include <highgui.h>
    #include <QImage>
    #include <QPixmap>
    #include <QByteArray>

    #include <QtGui>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QUdpSocket udpserver;//送信側
    QString sqwidth, sqheight, sqwidthStep;
    IplImage *img;
    QImage *qimg;
    QPixmap piximg;
    QPainter paint;
    QByteArray *ba;
    CvCapture *capture;
    QByteArray *qdata;
    QByteArray *whws;

    //IplImageからQImageへの変換
    QImage *IplImage2QImage(const IplImage *iplImg);
    //Timer object
    class QTimer *m_timer;
    

    private slots:
    void TimerHandler();
    void on_pushButton_clicked();

    protected slots:
    void sendDatagram();

    private:
    Ui::MainWindow *ui;

    };

    #endif // MAINWINDOW_H

    また、
    ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    mainwindow.cpp
    ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QLabel>
    #include <QDebug>

    //コンストラクタ
    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    connect(ui->sousin, SIGNAL(clicked()), this, SLOT(sendDatagram()));
    //カメラをキャプチャーする作業段階
    qimg = NULL;
    capture = cvCaptureFromCAM(0);
    m_timer = new QTimer();
    connect(m_timer, SIGNAL(timeout()), this, SLOT(TimerHandler()));
    m_timer->start(50);

    udpserver.connectToHost(QHostAddress::LocalHost, 10000, QUdpSocket::WriteOnly);
    

    }

    //デストラクタ
    MainWindow::~MainWindow()
    {
    delete ui;
    delete m_timer;
    cvReleaseCapture(&capture);
    }

    //この関数内でカメラ映像をウインドウに表示する
    void MainWindow::TimerHandler()
    {

        //フレームの取得
        img = cvQueryFrame(capture);
        //IPlImageをQImageに変換する
        qimg = IplImage2QImage(img);
        //QImageをPixmapに変換
        piximg = piximg.fromImage(*qimg);
        //ウインドウに描画
        ui->label->setPixmap(piximg);
    

    }

    //カメラ映像を送信する処理を表す関数
    void MainWindow::sendDatagram()
    {
    int i;
    ba = new QByteArray(img->imageData, img->imageSize);
    qDebug() << "w =" << img->width;
    qDebug() << "h =" << img->height;
    qDebug() << "ws =" << img->widthStep;

    qdata = new QByteArray();
    //プロトコルの決定 <WS>ステップ幅</WS><H>画像縦方向</H><W>画像横方向</W>画像データ(可変長)
    //QByteArrayにwidthを追加
        ba->append("<W>");
        sqwidth.setNum(img->width);
        ba->append(sqwidth);
        ba->append("</W>");
    
        //QByteArrayにheightを追加
        ba->append("<H>");
        sqheight.setNum(img->height);
        ba->append(sqheight);
        ba->append("</H>");
    
        //QByteArrayにwidthStepを追加
        ba->append("<S>");
        sqwidthStep.setNum(img->widthStep);
        ba->append(sqwidthStep);
        ba->append("</S>");
    
    //動画データを送信
    for(i=0;i<ba->size();i=i+100)
    {
        if(i > ba->size()){
            for(;i<ba->size();i++){
                udpserver.writeDatagram(ba->mid(i, 1), QHostAddress::LocalHost, 10000);
                qdata->append(ba->mid(i, 1));
            }
        }else{
            udpserver.writeDatagram(ba->mid(i, 100), QHostAddress::LocalHost, 10000);
            qdata->append(ba->mid(i, 100));
        }
    }
    qDebug() << "storage =" << qdata->toHex();
    
    ui->label_2->setText("transfer finished");
    
    delete qdata;
    delete ba;
    

    }

    // IplImage から QImage に変換するよ!
    QImage* MainWindow::IplImage2QImage(const IplImage *iplImg)
    {
    int h = iplImg->height;
    int w = iplImg->width;
    int channels = iplImg->nChannels;
    QImage *qimg = new QImage(w, h, QImage::Format_ARGB32);
    char *data = iplImg->imageData;

    for (int y = 0; y < h; y++, data += iplImg->widthStep)
    {
        for (int x = 0; x < w; x++)
        {
            char r, g, b, a = 0;
            if (channels == 1)
            {
                r = data[x * channels];
                g = data[x * channels];
                b = data[x * channels];
            }
            else if (channels == 3 || channels == 4)
            {
                b = data[x * channels];
                g = data[x * channels + 1];
                r = data[x * channels + 2];
            }
         if (channels == 4)
            {
                a = data[x * channels + 3];
                qimg->setPixel(x, y, qRgba(r, g, b, a));
            }
            else
            {
                qimg->setPixel(x, y, qRgb(r, g, b));
            }
        }
    }
    return qimg;
    delete qimg;
    

    }

    void MainWindow::on_pushButton_clicked()
    {
    ui->label_2->setText("clear");
    }

    jyusin
    ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    mainwindow.h
    ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QUdpSocket>
    #include <QString>
    #include <highgui.h>
    #include <QImage>
    #include <QPixmap>
    #include <QPainter>
    #include <QByteArray>
    #include <QtGui>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QUdpSocket udpreceiver;//受信側
    QString str;
    QString refw, refh, refws;//プロトコル用前置タグ
    QString reflw, reflh, reflws;//プロトコル用後置タグ
    QImage *qimg;
    QPixmap piximg;
    QPainter paint;
    QByteArray datagram, dest;//destは抽出した数値を一時的に格納しておく変数
    qint32 qwidth, qheight, qwidthStep;
    qint32 index_head, index_tail;
    QString sqwidth, sqheight, sqwidthStep;
    int i;
    int width_data, height_data, wstep_data;
    //IplImageからQImageへの変換
    QImage *char2QImage(char *cdata);
    QByteArray store;

    protected slots:
    void processPendingDatagram();
    void analysis();
    void showMovie();

    private slots:
    void on_clearButton_clicked();

    private:
    Ui::MainWindow *ui;

    };

    #endif // MAINWINDOW_H

    ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    mainwindow.cpp
    ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    str("connection"),
    ui(new Ui::MainWindow),
    refw("<W>"),
    refh("<H>"),
    refws("<S>"),
    reflw("</W>"),
    reflh("</H>"),
    reflws("</S>")
    {
    ui->setupUi(this);
    udpreceiver.bind(QHostAddress::LocalHost, 10000);
    connect(ui->pushButton1, SIGNAL(clicked()), this, SLOT(analysis()));
    connect(ui->pushButton2, SIGNAL(clicked()), this, SLOT(showMovie()));
    connect(&udpreceiver, SIGNAL(readyRead()), this, SLOT(processPendingDatagram()));
    datagram.clear();
    store.clear();
    width_data = 0;
    height_data = 0;
    wstep_data = 0;
    index_head = 0;
    index_tail = 0;
    }

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

    void MainWindow::processPendingDatagram()
    {
    ui->label->setText(str);
    QHostAddress sender;
    quint16 senderPort;

        do{
            datagram.resize(udpreceiver.pendingDatagramSize());
            udpreceiver.readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
            store.append(datagram);
        }while(udpreceiver.hasPendingDatagrams());
    
        qDebug() << "| storage =" << store.toHex();
        qDebug() << "| size =" << datagram.size();
        qDebug() << "| sender =" << sender;
        qDebug() << "| senderPort =" << senderPort;
    

    }

    void MainWindow::showMovie()
    {
    char cdata;
    //QByteArrayをchar
    に変換
    cdata = store.data();
    //char*型のデータをQImageに変換
    qimg = char2QImage(cdata);
    //QImageをPixmapに変換
    piximg = piximg.fromImage(*qimg);
    //ウインドウに描画
    ui->label->setPixmap(piximg);

    delete qimg;
    datagram.clear();
    store.clear();
    

    }

    // IplImage から QImage に変換するよ!
    QImage* MainWindow::char2QImage(char *cdata)
    {
    int channels = 3;
    QImage *qimg = new QImage(width_data, height_data, QImage::Format_ARGB32);
    char *data = cdata;

    for (int y = 0; y < height_data; y++, data += wstep_data)
    {
        for (int x = 0; x < width_data; x++)
        {
            char r, g, b, a = 0;
            if (channels == 1)
            {
                r = data[x * channels];
                g = data[x * channels];
                b = data[x * channels];
            }
            else if (channels == 3 || channels == 4)
            {
                b = data[x * channels];
                g = data[x * channels + 1];
                r = data[x * channels + 2];
            }
         if (channels == 4)
            {
                a = data[x * channels + 3];
                qimg->setPixel(x, y, qRgba(r, g, b, a));
            }
            else
            {
                qimg->setPixel(x, y, qRgb(r, g, b));
            }
        }
    }
    return qimg;
    

    }

    void MainWindow::on_clearButton_clicked()
    {
    ui->label->setText("clear");
    datagram.clear();
    store.clear();
    width_data = 0;
    height_data = 0;
    wstep_data = 0;
    index_head = 0;
    index_tail = 0;
    }

    void MainWindow::analysis()
    {
    height_data = 0;
    width_data = 0;
    wstep_data = 0;
    index_head = 0;
    index_tail = 0;
    //送信側定義済みプロトコルに基づいて画像データを抽出
    //widthStepの抽出
    index_head = store.indexOf(refws);
    index_tail = store.indexOf(reflws);
    for(i = index_head + 3; i < index_tail; i++)
    {
    dest.append(store[i]);
    }
    wstep_data = dest.toDouble();
    qDebug() << "<S>index_head =" << index_head;
    qDebug() << "<S>index_tail =" << index_tail;
    qDebug() << "<S>data =" << wstep_data;
    //destをクリアする
    dest.clear();

    //heightの抽出
    index_head = store.indexOf(refh);
    index_tail = store.indexOf(reflh);
    for(i = index_head + 3; i < index_tail; i++)
    {
        dest.append(store[i]);
    }
    height_data = dest.toDouble();
    qDebug() << "<H>index_head =" << index_head;
    qDebug() << "<H>index_tail =" << index_tail;
    qDebug() << "<H>data =" << height_data;
    //destをクリアする
    dest.clear();
    
    //widthの抽出
    index_head = store.indexOf(refw);
    index_tail = store.indexOf(reflw);
    for(i = index_head + 3; i < index_tail; i++)
    {
        dest.append(store[i]);
    }
    width_data = dest.toDouble();
    qDebug() << "<W>index_head =" << index_head;
    qDebug() << "<W>index_tail =" << index_tail;
    qDebug() << "<W>data =" << width_data;
    

    }


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.