PDA

View Full Version : Wireless Video



khrave
1st June 2010, 21:14
I have this Qt application that currently reads video data from a webcam plugged into my laptop and outputs it in a window. I need to make it receive data wireless-ly from a flying vehicle and display the data it receives in the window.

I am using OpenCV to display the video currently and would like to be able to modify it to work over a wireless network. Thanks in advance for your help and patience!

high_flyer
2nd June 2010, 09:27
What is the question?

Qt Coder
2nd June 2010, 11:36
Hey what you used to receive camera output and show it in Qt???
pls post some code,I also need it.

squidge
2nd June 2010, 14:32
To an application, a wireless network is the same as a wired one. There is no difference.

(Assuming the wireless network is TCP/IP and not some proprietary nonsense, of course)

khrave
2nd June 2010, 18:08
@fatjuicymole
Well right now I am reading the video data directly from a webcam that is plugged in to one of my usb ports on my laptop. I need to modify the code to receive video data from a vehicle flying in the air with a camera attached to it.

@Qt Coder
Here is the website where I downloaded some code that takes webcam video and displays it in a Qt window. It was very easy for me to integrate this into my personal project and should be the same for you. Keep in mind that OpenCV must be installed completely, along with some other things probably.
http://qt-apps.org/content/show.php/Qt+Opencv+webcam+viewer?content=89995

Installation instructions for OpenCV:
http://opencv.willowgarage.com/wiki/InstallGuide_Linux

@high_flyer
Basically, how do I take the attached code, and make it work with tcp/ip wireless network. I need to receive the video from a remote location, not just my own computer.

The attached code requires OpenCV to run and it could require other things. Feel free to ask me any questions and I will help getting it running quickly. Thanks everyone for your time and patience!

squidge
2nd June 2010, 19:16
@fatjuicymole
Well right now I am reading the video data directly from a webcam that is plugged in to one of my usb ports on my laptop. I need to modify the code to receive video data from a vehicle flying in the air with a camera attached to it. And? How does the flying camera transmit its data? Wifi? Bluetooth?

khrave
2nd June 2010, 19:24
It transmits it via wifi to a computer on the ground purposed to view video data and other stats about the flying vehicle.

squidge
2nd June 2010, 20:23
So what you need to do is create a server. What type of connection does it expect?

khrave
2nd June 2010, 21:08
We're using a camera that is mounted on the flying vehicle, which is attached via usb to a gumstix overo fire board (also mounted on the flying vehicle) which will transmit various types of information, including video data, through a tcp/ip wireless-g signal to the computer on the ground. I need to be able to get the video data from the vehicle and display it. I feel like it is an easy modification to the code I posted earlier, but I need a push in the right direction. Thanks! :)

squidge
2nd June 2010, 22:18
Wireless-G is a transport medium (well, Link Layer) for transferring data over the air-ways
TCP over IP is a transport medium
Before we can go further we need to know what Application Layer the camera uses. For example, HTTP, FTP, Proprietary, etc.

khrave
2nd June 2010, 22:27
Oh, my apologies, my terminology knowledge is relatively low. We're using UDP, sending raw data through packets between the ground computer and the vehicle.

squidge
2nd June 2010, 23:22
In which case, there is a nice example for UDP in the QUdpSocket documentation in Assistant.

Qt Coder
4th June 2010, 12:23
The same way I need to use IP camera in my proje.My question is

1) How to know which application layer the camera uses?

squidge
4th June 2010, 14:06
a) Wireshark (examine communication), or
b) Experimentation, or
c) Documentation

Qt Coder
5th June 2010, 10:36
I installd Qt 4.6.2 and OpenCV2.0 on my windows machine

Qt is installed at C:\Qt\2010.02.1\Qt and openCV is installed at c:\OpenCV2.0

I downloaded the QtOpenCV example which
Opens a webcam, and displays the image in the widget.
from http://opendesktop.org/content/show.php?content=89995&PHPSESSID=kfmhtqozm


I copied opencv folder where it contains cv.h,higui.h in Qt include folder also I changed .pro file as


INCLUDEPATH += "C:\OpenCV2.0\src\cv"
INCLUDEPATH += "C:\OpenCV2.0\src\cxcore"
INCLUDEPATH += "C:\OpenCV2.0\src\cvaux"
INCLUDEPATH += "C:\OpenCV2.0\src\highgui"

LIBS += -L "C:\OpenCV2.0\lib"
LIBS += -lcv -lhighgui


when I compile example it gives me error


c:/qt/2010.02.1/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../../mingw32/bin/ld.exe: cannot find -lcv
collect2: ld returned 1 exit status

why this error occures?

squidge
5th June 2010, 20:58
Where is cv?

Qt Coder
7th June 2010, 08:25
OpenCV is installed at C:\OpenCV2.0

Qt 4.6.2 is installed at C:\Qt\2010.02.1\qt

also I have copied C:\OpenCV2.0\include\opencv folder to Qt include folder

still it gives this error
1.
c:/qt/2010.02.1/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../../mingw32/bin/ld.exe: cannot find -lcv
2.
collect2: ld returned 1 exit status

squidge
7th June 2010, 08:57
So there is a file called libcv.lib in C:\OpenCV2.0\lib ?

Qt Coder
7th June 2010, 09:09
C:\OpenCV2.0\lib\libcv200.dll.a

file is there

saa7_go
7th June 2010, 11:16
modify
LIBS += -lcv -lhighgui

to
LIBS += -lcv200.dll -lhighgui

Qt Coder
7th June 2010, 12:10
:)

linking LIB files as dll solved my problem

I changed it as

LIBS += -lcv200.dll -lhighgui200.dll

also I needed to place the dll's where my qt project EXE resides.

Thanks to all who helped me.

Qt Coder
8th June 2010, 09:53
modifying

LIBS += -lcvl -lhighguil

to

LIBS += -lcv200.dll -lhighgui200.dll

solved my problem

also I had to place

1) libcv200.dll
2) libcvaux200.dll
3) libhighgui200.dll
4) libcxcore200.dll


above dll's in release folder where project exe resides


Thanx to all who helped me


My another question is if we attached webcam to a PC in LAN,can we access and view it in other PC using Qt?

:)

hatred
8th June 2010, 18:19
hello, can i ask you something, i'm currently doing a similar program with yours, im trying to send a video feed from a mobile robot into my laptop using qt and open cv,

i also use the same source code that have tried to open the webcam in opencv using Qt,

but after compiling the QtOpenCV i got thsi eror messages:

1. collect2: ld returned 1 exit status

can u share help me to solve this error?

Qt Coder
9th June 2010, 08:00
Post error message,there must be some error message above this " 1. collect2: ld returned 1 exit status" .

tbscope
9th June 2010, 08:02
Can we access and view webcam on my PC which is attached to other PC in LAN using Qt

Of course you can. Create a little server on the pc having the webcam. Send it to all the other clients that are connected.

Qt Coder
9th June 2010, 12:31
I m able to create server and client,but my question is


1) How to send IplImage over socket?

2) How to use threads to handle more than one client requests?

squidge
9th June 2010, 13:44
You don't need to use threads to handle more than one client request. Use signals, slots and asynchronous methods instead.

You can transfer the image as binary data.

Qt Coder
10th June 2010, 07:52
I have tried



CvCapture * camera;
IplImage * image;
qint64 nWrite;

image=cvQueryFrame(camera);
nWrite = gtcpSocket->write((char*)image,sizeof(image));

But nWrite shows only 4 bytes transferred..

How to send image as binary data?

squidge
10th June 2010, 09:11
sizeof(image) is a pointer, so 4 bytes is what I'd expect it to write.

image->imageData may be more suitable (or wherever the data is stored)

khrave
10th June 2010, 18:29
hello, can i ask you something, i'm currently doing a similar program with yours, im trying to send a video feed from a mobile robot into my laptop using qt and open cv,

i also use the same source code that have tried to open the webcam in opencv using Qt,

but after compiling the QtOpenCV i got thsi eror messages:

1. collect2: ld returned 1 exit status

can u share help me to solve this error?

What I do in this situation is go into my project directory via console and run make from console. Usually, but not always, it will show some more info regarding why ld returned 1 exit status. More often than not, it is because a library wasn't found. Hope this helps!

Qt Coder
12th June 2010, 13:30
Hey I m able to send image over socket ,but at clients side I m not able to see any image

My server application code for sending image is
QImage pic("Viraat.png","PNG");

QByteArray ba;
QBuffer buffer( &ba );
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer,"PNG"); // writes image into ba in PNG format
nWrite = gtcpSocket->write((const char *)ba);

QMessageBox::critical(this, QString::number(int(nWrite)),
tr("Size of Image sent to client: %1."));

here MessageBox shows that 8 bytes transferred which is the size of file.


Now at client side I have written code as
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_6);

QByteArray ba;
QBuffer buffer( &ba );
buffer.open(QIODevice::ReadOnly);

//nRead = in.device()->read((char *)&ba,sizeof(ba));
ba = tcpSocket->read(100);


//empty image
QImage image(2048,1024,QImage::Format_Indexed8);

//load pixel data into empty image from QByteArray
image = QImage::fromData(ba,"PNG");

//load pixel data into empty image from QByteArray


QMessageBox::critical(this,tr("Data Received: %1."),QString::number(ba.length()));
image.save("d:/pic.png","PNG");
ui->label_3->setPixmap(QPixmap:: fromImage( QImage(image)));
ui->label_3->show();
tcpSocket->disconnectFromHost(); but nothing is saved at D drive and no image is set in label. but it shows it received 8 bytes of data...

how to construct Qimage from raw data and how to save the data/image received over socket to local hard drive ?

wysota
12th June 2010, 14:55
You expect the whole image data to fit into 8 bytes? Or even into 100 bytes?

Qt Coder
14th June 2010, 08:00
I dont know how much would be the image size so I have given maximum of 100 bytes data to read. what to give read size otherwise if you dont know how much size of data is going to arrive on socket?

squidge
14th June 2010, 09:02
So why not send the size of the data your sending before sending the actual image data? Then you know the size you are expecting.

Qt Coder
15th June 2010, 12:14
I m able to receive data on socket but I need to construct image from it and set it as pixmap to my label

My client side code is



QPixmap pixmap;
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_6);

QByteArray ba;
QBuffer buffer( &ba );
buffer.open(QIODevice::ReadOnly);
ba = tcpSocket->read(100);

pixmap.loadFromData(ba,"PNG");

ViewObj->ui.label->setPixmap(pixmap);


But no image is displayed also tell me some way how to save received image on local hard drive

wysota
15th June 2010, 12:30
Please, answer these questions:

How many bytes (roughly) would a BMP image with 2048x1024 size and an 8 bit colormap take?
How many bytes are sent on the socket on the transmitting side?
How many bytes should be sent on the socket assuming a maximal possible image compression available is about 1:12?
How are those three figures related to each other?
What is the size of byte array on the receiving end before calling loadFromData()?

If you don't know how to answer those questions, please look for answers in the Internet. Answers to the last two should give you a hint why an image is not displayed.

Qt Coder
15th June 2010, 13:03
Currently The image which I m sending is of
1)Image resolution - 128 by 128
2)format - "PNG"
3)size on disk - 8,192 bytes

but at server side it shows only 8 bytes transferred...

As I searched on internet 8 bit Grayscale means 1 byte per pixel

so answer to your first question is

1) 2048x1024 = 2097152 pixels which would mean 2097152 bytes
2) in my case only 8 bytes are sent on the socket on the transmitting side
3) if we consider above bmp image with the 2048*1024 resolution then 174762 bytes should be sent assuming a maximal possible image compression available is about 1:12

correct me if I m wrong

wysota
15th June 2010, 13:15
So what does it mean if 8 bytes are sent on the transmitting end if the image has volume of 8kB? Can the image be recreated on the receiving end from those 8 bytes?

Qt Coder
16th June 2010, 09:08
I m getting a runtime error in my server application

when I compile it it gives error
C:\Qt\2010.02.1\qt\examples\widgets\WebServer\debu g\QtOpenCV.exe exited with code -1073741515


it use to run fine before ,

I tried adding messegebox in main() at very first step but control dont even reaches there, if I run exe manually it gives
Runtime error !.. This application has requested the runtime to terminate it in an unusual way.

I m not able to debug it also..

How to fix this runtime error?

Qt Coder
16th June 2010, 09:57
:) Hey I got where this runtime error lies

I need to place those OpenCV dll's in my debub folder.

Now my server side code is


QImage pic("monkey_off_128x128.png","PNG");

QByteArray ba;
QBuffer buffer( &ba );
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer,"PNG"); // writes image into ba in PNG format
nWrite = gtcpSocket->write(ba.data());
QMessageBox::critical(this, QString::number(ba.length()),QString::number((int) nWrite));


The messageBox shows ba.length() to be 9437 and nWrite to be 8 only.
where as the file size is 7045 bytes and size on disk 8192 bytes ,I dont know from where it has added extra bytes.

also why it sends only 8 bytes over socket?

Qt Coder
16th June 2010, 10:59
:) Hey I m able to sendwhole image over socket to client but only half of bytes are received at client side

Now my server side code is
QBuffer buffer;
QImageWriter writer(&buffer, "png");
writer.write(pic);
QByteArray data;
QDataStream stream(&data,QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_4_6);
stream << (quint32)buffer.data().size();
data.append(buffer.data());
nWrite = gtcpSocket->write(data);

QMessageBox::critical(this, QString::number(data.length()),QString::number((in t)nWrite));
MessageBox shows image size and bytes transferred to be 9441 but only 4380 bytes are received at client side


My client side code is
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_6);
QByteArray* array = new QByteArray();
*array = tcpSocket->readAll();
QMessageBox::critical(this,tr("Bytes rcvd %1."),QString::number(array->length()));
QImage image;
image = QImage::fromData(array->data(),"png");
image.save("rcvdimage.png","png");


where the problem lies?

wysota
16th June 2010, 11:28
The messageBox shows ba.length() to be 9437 and nWrite to be 8 only.
Close the buffer before writing its contents to the socket.

where as the file size is 7045 bytes and size on disk 8192 bytes ,I dont know from where it has added extra bytes.
From the cluster size on your filesystem, most probably.

numbat
16th June 2010, 12:20
readAll reads all available data, but in your case the date may not have all arrived when you call it. Following is a little (untested) code showing you how to send and receive a length. You should be able to extend it from here.


//server
/* Assumes data is a QByteArray containing your image. */

/* First get our number into a QByteArray */
QByteArray len = QByteArray::number(data.length(), 10);

/* Pad it with spaces, so that it has a constant width. */
len = len.leftJustified(10, ' ', false);

/* Put the number at the start of our data array. */
data.prepend(len);

/* Now send our data to the socket, */
g_tcpsocket->write(data);



//client
QByteArray data;
while (data.length() < 10)
{
/* Read all available data. */
QByteArray received = tcpsocket->readAll();

/* Add received data to the end of our byte array. */
data += received;

/* Wait until the next packet of data arrives. */
tcpsocket->waitForReadyRead();
}

/* Get the first ten bytes, making up our number. */
QByteArray len = data.left(10);

/* Convert to an integer. */
int length = len.toInt();

/* Remove the first ten bytes from our data array. */
data.remove(0, 10);

/* Now repeat the loop above until you have length bytes in data. */

Qt Coder
16th June 2010, 12:31
A strange behavior at client side,If I put a messagebox just before reading data from socket then it reads all 9441 bytes.

Before reading any data from socket I m checking how many bytes the server has send
QMessageBox::critical(this,tr("Bytes available"),QString::number((int)tcpSocket->bytesAvailable()));


it shows 4380 bytes available but reads 9441 bytes if I put msgbox before start reading .

If no msgbox is there it reads only 4380 bytes why so.

Also I m not able to reconstruct the image from this 9441 bytes of data

My client side code is

QByteArray ba;
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_6);

QMessageBox::critical(this,tr("Bytes available %1."),QString::number((int)tcpSocket->bytesAvailable()));
ba = tcpSocket->readAll();
QMessageBox::critical(this,tr("Bytes rcvd %1."),QString::number(ba.length()));


QImage icon(128, 128, QImage::Format_RGB32);
QImageReader reader(ba,"png");
if(reader.canRead())
QMessageBox::critical(this,tr("Image can be read"),"");
else
QMessageBox::critical(this,tr("Error"),reader.errorString());
if (reader.read(&icon)) {

//pixmap.loadFromData(QImage());
QMessageBox::critical(this,tr("Time to set icon"),"");


ui.label->setPixmap(QPixmap::fromImage(icon));
}
Errorstring returns "File not found" and My debugging output is
QFSFileEngine::open: No file name specified
QFSFileEngine::open: No file name specified

Qt Coder
16th June 2010, 13:05
@numbat

Hey I added the code u suggested
but at client side


while (data.length() < 10)
{
/* Read all available data. */
QByteArray received = tcpSocket->readAll();

/* Add received data to the end of our byte array. */
data += received;

/* Wait until the next packet of data arrives. */
//tcpSocket->waitForReadyRead();
}

if I uncomment that tcpSocket->waitForReadyRead(); my program hangs. Now my another question is how to construct image from data I received?

squidge
16th June 2010, 14:20
Since you are using a char * and not providing a length, how does the method know how many bytes to send? Its logical to assume that it'll stop at the first null byte, which could be 8 bytes in.

Now, if only there was a method that could use your QByteArray directly.... ;-)

Qt Coder
17th June 2010, 12:17
I have wriiten a test application where I m converting the Qimage to QByteArray and converting this QByteArray to QImage again and setting as pixmap on label.

Here is the code


//Image to be converted to QByteArray , stored in debug folder
QImage pic("monkey_off_128x128.png","PNG");

//Writing to QByteArray

QBuffer b;
QImageWriter writer(&b, "png");
writer.write(pic);
QByteArray ba;
QDataStream stream(&ba,QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_4_6);
b.open(QBuffer::ReadWrite);
stream << (quint32)b.data().size();
ba.append(b.data());
b.close();



//Reading from QByteArray

QPixmap pixmap;
QImage ImagePNG;

QBuffer buf(&ba);

buf.open(QIODevice::ReadWrite);
ImagePNG.loadFromData(ba,"png");

ViewObj->ui.label->setPixmap(QPixmap::fromImage(ImagePNG));

if(ImagePNG.isNull())
QMessageBox::critical(this,"NULL IMAGE",QString::number(ba.length()));



my image size is 8192 bytes
but when I test this code but it shows 9441 bytes in QByteArray also ImagePNG.isNull returns true and no image is displayed.

Where I m going wrong?

squidge
17th June 2010, 13:03
Please define "image size"

Qt Coder
17th June 2010, 13:21
I m not getting you

The image size is 7045 Bytes and size on disk is 8192 Bytes (I got this information from file properties right clicking the image file) but my test program shows 9441 bytes in QByteArray,I dont know from where it has got these extra bytes ,may be bcoz of this image is not constructed properly....

wysota
17th June 2010, 13:47
What you are doing here doesn't make much sense. Either use QDataStream for everything or don't use it at all.


QByteArray ba;
QImage img(...);
QDataStream stream(&ba, QIODevice::WriteOnly);
stream << img;
and

QByteArray ba = ... ;
QDataStream stream(ba, QIODevice::ReadOnly);
QImage img;
stream >> img;

squidge
17th June 2010, 14:17
I m not getting you

The image size is 7045 Bytes and size on disk is 8192 Bytes (I got this information from file properties right clicking the image file) but my test program shows 9441 bytes in QByteArray,I dont know from where it has got these extra bytes ,may be bcoz of this image is not constructed properly....

PNG is a compressed file, so Image size could be the size of the file, the size of the raw data, or the size of the uncompressed data. Thats why I asked you to define it.

So if the compressed file size is 7045, then it is logical that the uncompressed file size (ie, when the file is loaded) will be larger.

Qt Coder
18th June 2010, 10:49
:) I m able to send and receive as well as display image .

My latest server side code is



IplImage *image=cvQueryFrame(camera);
CapturedImage = cvwidget->putImage(image);

cvwidget->imagelabel->setPixmap(QPixmap::fromImage(CapturedImage)); //For viewing captured image

QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
CapturedImage.save(&buffer, "PNG");
buffer.close();

QByteArray len = QByteArray::number(data.length(), 10);

/* Pad it with spaces, so that it has a constant width. */
len = len.leftJustified(10, ' ', false);

/* Put the number at the start of our data array. */
data.prepend(len);

/*send QbyteArray over socket */
nWrite = gtcpSocket->write(data);



My client side code for receiving and displaying image is



void MainWindow::readDatafromServer() //Slot conneted to readyRead() signal
{

qint64 nRead;
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_6);
QByteArray data;
while (data.length() < 10)
{
/* Read all available data. */
QByteArray received = tcpSocket->readAll();

// QMessageBox::critical(this,tr("first"),QString::number(received.length()));
/* Add received data to the end of our byte array. */
data += received;

/* Wait until the next packet of data arrives. */
// tcpSocket->waitForReadyRead();
}

/* Get the first ten bytes, making up our number. */
QByteArray len = data.left(10);

/* Remove the first ten bytes from our data array. */
data.remove(0, 10);

QString str( len);
bool ok;
int length = str.toInt(&ok,10);
// QMessageBox::critical(this,str,QString::number(len gth));
// QMessageBox::critical(this,"ABytes",QString::number((int)tcpSocket->bytesAvailable()));


while (data.length() < length)
{
/* Read all available data. */
QByteArray receivedB = tcpSocket->readAll();
// QMessageBox::critical(this,tr("second"),QString::number(receivedB.length()));


/* Add received data to the end of our byte array. */
data += receivedB;

/* Wait until the next packet of data arrives. */
//tcpSocket->waitForReadyRead();
}
QBuffer buf;
buf.setBuffer(&data);
buf.open(QIODevice::ReadOnly);
QImageReader qir;
qir.setDevice(&buf);
QImage ImagePNG;
qir.read(&ImagePNG);

ViewObj->ui.label->setPixmap(QPixmap::fromImage(ImagePNG));
}

At server captures image from webcam and writes over socket every o.1 sec,Now how to use waitForReadyRead() at client side to read this continuous data from server .I tried but it freezes the GUI,If not used client receives image only one time.

Qt Coder
18th June 2010, 13:36
I m able to get all images sent by server

I added


tcpSocket->waitForReadyRead(100) ; in client's mainwindow constructer now the constructor looks like
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
tcpSocket = new QTcpSocket(this);

ViewObj = new view(this);
ViewObj->show();

tcpSocket->waitForReadyRead(100) ;

connect(ui->BtnConnect, SIGNAL(clicked()), this, SLOT(Get_ServerPortIP()));
connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),this, SLOT(displayError(QAbstractSocket::SocketError)));
connect(tcpSocket, SIGNAL(readyRead()),SLOT(readDatafromServer()));


}

But now problem is

server sends captured image after every 0.1 sec,but at my client app if I dont put msgbox before accepting any new data my GUI freezes ,I dont know why it needs the msgbox to be clicked/some time to rest before accepting new image?


what could be alternative to this ?
should I put sleep() function before accepting new image?

squidge
18th June 2010, 14:08
You are blocking the event loop because you are using blocking calls. You should use asynchronous calls and signals/slots.

Qt Coder
19th June 2010, 08:15
Data is coming continously even if I dont use/comment tcpSocket->waitForReadyRead(100) ;
But problem is I get all images continously if I put MsgBox before accepting new data

i.e.
void MainWindow::readDatafromServer()
{
qint64 nRead;
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_6);
QByteArray data;

QMessageBox::critical(this,"WebClient","Received Data");

while (data.length() < 10)
{
.....
}
}

if I remove this QMessageBox ,nothing is displayed and my GUI is freezed,

why it needs that msgbox /some time before accepting new data?

what is asynchronous call and how to use it?