カメラで撮影した映像を送信するプログラム
-
現在、一台のパソコンの内蔵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_OBJECTpublic:
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_OBJECTpublic:
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;
}