

こんばんは、現在、Qtでプログラミング中の学生です。  
今、パソコンのWebカメラで撮影した映像をサーバー側プログラムとクライアント側プログラムで  
やり取りするコードを書いているのですが、まったくうまくいきません。  
クライアントに送信はできるのですが、クライアント側で映像を再構築するとなぜか映像が切れ切れ（テレビの調子が悪い時のあの感じです。）になります。  
そこで、UDP送信でカメラ映像をサーバ・クライアント側でやり取りするプログラムのヒントをいただけないでしょうか？

私の方法を簡単に書いておきます。問題点を指摘していただくだけでも構いません。  
「サーバ側」  
Webカメラで動画撮影→OpenCVの関数でキャプチャー→QByteArrayに変換→QByteArrayのメンバ関数appendで画像の縦、横情報をつける→UDPのwriteDatagramでクライアントに送信  
「クライアント側」  
UDPのreadDatagramで情報取得→QByteArrayのメンバ関数indexOfで画像の縦、横の情報を探して取得（送る前にタグつけてるので、それを探させます）→QByteArrayのdata()関数でデータ型をcharに変更→ネットから拾ってきた関数(1)を使ってcharをQImageのデータ型に→QImageをQPixmapに→QPixmapをラベルに張り付ける

関数(1)

[code]

     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 += width_data * channels)
    {
        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;
    
    
    }
    
[/code]


CC BY-SA 3.0
2015-06-10T18:18:47.490
11236
2015-08-17T06:59:17.370
2015-06-10T22:06:04.890
3639
10093
question
opencv qt
Webカメラで撮影した映像をサーバからクライアントに送りたい


640*480*24bitカラーだと1フレーム7Mbpt超になりますので。目標のフレームレートが書かれていませんが、動画として成立するには最低15fpsぐらいでしょう。それだと100Mbpsを超えることになります。

スループットが十分にないのであればデータ量を減らすしかありません。どうやって減らすかは回線速度との見合いです。100Mbpsはでないけど10Mbpsなら、というぐらいなら1フレームごとにJPEG圧縮でもいけるかもしれません。もっと細い回線では動画としてエンコードする必要があります。

スループットが十分にあるはずなのに問題が起きるのであれば、送信側の送出間隔が短すぎて送信側のバッファがあふれているか受信側の処理が追いつかずにやはりバッファがあふれているということもあります。


CC BY-SA 3.0
2015-06-12T03:05:28.437
11272
2015-06-12T03:05:28.437
5793
11236
answer


「サーバ側送信用の関数」  
//カメラ映像を送信する処理を表す関数  
void MainWindow::sendDatagram()  
{  
int i;  
//画像データ→QByteArray  
ba = new QByteArray(img->imageData, img->imageSize);  
qDebug() << "w =" << img->width;  
qDebug() << "h =" << img->height;  
qDebug() << "ws =" << img->widthStep;

[code]

    //プロトコルの決定　画像データ(可変長)<W>画像横方向</W><H>画像縦方向</H>
    //QByteArrayにwidthを追加
        ba->append("<WSTART>");
        sqwidth.setNum(img->width);
        ba->append(sqwidth);
        ba->append("</WEND>");
    
        //QByteArrayにheightを追加
        ba->append("<HSTART>");
        sqheight.setNum(img->height);
        ba->append(sqheight);
        ba->append("</HEND>");
    
        //動画データの圧縮
        QByteArray comp = qCompress(*ba, 5);
    
    //動画データを送信
    for(i=0;i<comp.size();i=i+100){
        if(i<comp.size())
            //100こずつデータを送信
            udpserver.writeDatagram(comp.mid(i, 100), QHostAddress::LocalHost, 10000);
        else if(i>=comp.size()){
            i=i-100;
            //1つずつデータを送信
            for(;i==comp.size();i++)
            udpserver.writeDatagram(comp.mid(i, 1), QHostAddress::LocalHost, 10000);
        }
    
[/code]

}

[code]

    //送信完了した旨の表示
    ui->label_2->setText("transfer finished");
    
    //QByteArrayの破棄
    delete ba;
    
[/code]

}


CC BY-SA 3.0
2015-06-18T05:55:25.107
11465
2015-06-18T05:55:25.107
10093
11236
answer