linux摄像头数据网络传输,Linux下基于OpenCV的摄像头数据采集与传输

最近一段时间在搞摄像头的采集和传输。采集通过OpenCV自带的函数库,不用自己编写V4L2,省去了很多事情。主要工作就是在视频的传输了。主要思路是:将采集的一帧视频图像压缩成jpg格式的图片,这样进行过压缩的数据量大大减少。然后通过socket的UDP传输协议将图片通过网络传送到客户端。我之前用的TCP传的,总是有部分数据丢失重传,导致现实界面偶尔出现闪动,出现的错误提示:Corrupt JPEG data: premature end of data segment 本以为网络足够好,可有用下TCP,看来还是没设计好,就转用的UDP协议传输,问题就解决了。

在linux下QT环境中进行的程序编写,服务器端用的是linux C socket编写的,客户端是QT封装的QUdpSocket类编写的,成功实现了传输。但是将客户端放在window下就没有数据传输,客户端一直不能readyread(),一直没有找到原因,看来还要继续寻找了。

服务器端代码:

widget.h

#ifndef WIDGET_H

#define WIDGET_H

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define PORTNUMBER 4444

#define MAX_SIZE 1024;

namespace Ui {

class Widget;

}

class Widget : public QWidget

{

Q_OBJECT

public:

explicit Widget(QWidget *parent = 0);

~Widget();

int init_socket();

private:

Ui::Widget *ui;

cv::VideoCapture capture; //摄像头

cv::Mat frame; //帧图像

QTimer *timer; //定时器

QImage img; //QT 图像

int sockfd;

struct sockaddr_in server_addr;

private slots:

void slot_timer();

};

#endif

widget.c

#include "widget.h"

#include "ui_widget.h"

#include

Widget::Widget(QWidget *parent) :

QWidget(parent),

ui(new Ui::Widget)

{

ui->setupUi(this);

timer = new QTimer(this);

connect(timer, SIGNAL(timeout()), this, SLOT(slot_timer()));

timer->start(33); //启动定时器,设置帧率

capture = cv::VideoCapture(1); //打开摄像头,这里使用了固定的摄像头,随机的话为-1

sockfd = init_socket(); //初始化套接字

}

Widget::~Widget()

{

delete ui;

delete timer;

capture.release();

}

int Widget::init_socket()

{

int sockfd;

if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )

{

perror("Socket error");

exit(1);

}

bzero(&server_addr, sizeof(server_addr));

server_addr.sin_family = AF_INET;

server_addr.sin_port = htons(PORTNUMBER);

//server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

server_addr.sin_addr.s_addr = inet_addr("192.168.1.115"); //主机IP

return sockfd;

}

void Widget::slot_timer()

{

capture>>frame; //将摄像头的每一帧放入frame

if(frame.empty())

{

printf("frame is empty\n");

return;

}

/*将opencv采集的BGR格式的图像转化成QT下的RGB格式的图像*/

cv::cvtColor(frame, frame, CV_BGR2RGB);

img = QImage((unsigned const char*)frame.data, frame.cols, frame.rows, QImage::Format_RGB888 );

img.save("test.jpg", "JPEG");

QFile file("test.jpg");

if(!file.open(QIODevice::ReadOnly))

{

perror("File open error");

return;

}

QByteArray buffer = file.readAll();

file.flush(); //好像这里没起作用

if(sendto(sockfd, buffer.data(),buffer.size(), 0, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr_in)) < 0)

{

printf("send fail %d\n", buffer.size());

perror("sendto error");

}

file.close();

}

客户端程序:

widget.h

#ifndef WIDGET_H

#define WIDGET_H

#include

#include

#include

namespace Ui {

class Widget;

}

class Widget : public QWidget

{

Q_OBJECT

public:

explicit Widget(QWidget *parent = 0);

~Widget();

private:

Ui::Widget *ui;

QImage img;

QUdpSocket* receiver;

private slots:

void processPendingDatagram();

};

#endif // WIDGET_H

widget.c

#include "widget.h"

#include "ui_widget.h"

#include

#include

#define PORTNUMBER 4444

Widget::Widget(QWidget *parent) :

QWidget(parent),

ui(new Ui::Widget)

{

ui->setupUi(this);

receiver = new QUdpSocket(this);

bool result = receiver->bind(PORTNUMBER, QUdpSocket::ShareAddress);

if(result)

{

printf("bind right\n");

}

else

{

printf("Bind error");

}

connect(receiver, SIGNAL(readyRead()), this, SLOT(processPendingDatagram()));

}

void Widget::processPendingDatagram()

{

qint64 num = receiver->pendingDatagramSize();

//printf("receive size = %ld\n", num);

QByteArray buffer;

buffer.resize(num);

receiver->readDatagram((char*)buffer.data(), num); //将接收到的数据放入buffer中

QFile file("test.jpg");

if(!file.open(QIODevice::WriteOnly))

{

printf("file open error\n");

return;

}

file.write(buffer); //将数据写到硬盘,保存成JPG格式图片

file.flush();

file.close();

img = QImage("test.jpg");

ui->label->setPixmap(QPixmap::fromImage(img)); // 在label中显示图片

ui->label->resize(ui->label->pixmap()->size());

}

Widget::~Widget()

{

delete ui;

}

0818b9ca8b590ca3270a3433284dd417.png

如果有客户端在Window下的QT实现的还请大神指教。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值