- 1.器件
1 | 上位机—笔记本 |
2 | 下位机–树莓派zero w/树莓派3B+ |
3 | 树莓派V2相机–800w像素 |
-
2.基于SOCKET的通讯
Server----作为服务器接收图片
Client----作为客户端采集图片并通过socket的网口连接传输 -
3.树莓派Linux,笔记本Windows/Linux
Server端代码-----(Linux)
1.main.cpp
#include<several_mat.h>
int main()
{
getpicture img;
if(img.socketConnect(8888)<0) //建立socket通讯,端口为8888
{
cout<<"connect error!";
return -1;
}
Mat image;
if(img.acceptfile(image)>0) //等待客户端的信号输入,接收图片
{
cout<<"accept is OK!";
}
img.socketDisconnect();
return 0;
}
2.several_mat.h
#ifndef SEVERAL_IMGS_H
#define SEVERAL_IMGS_H
#endif // SEVERAL_IMGS_H
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
using namespace std;
using namespace cv;
#define MAXLINE 1024*1024 //最大传输单张图片的大小
#define img_width 1920 //图片的分辨率
#define img_height 1080
#define img_num 30 //传输图片的张数
#define packet_num 8 //把一张图片划分成n部分传输
struct recvBuf //接收的数据
{
char buf[MAXLINE];
int flag; //来判断一张图片接收完成
};
class getpicture
{
public:
getpicture(void);
~getpicture(void);
int socketConnect(int PORT); //socket通讯
int acceptfile(Mat& image); //接收图片,每一个像素的接收
void socketDisconnect(void);//关闭服务器
private:
struct recvBuf data;
int needRecv;
int count;
int sockConn;
};
3.several_mat.cpp
#include<several_mat.h>
getpicture::getpicture(void)
{
}
getpicture::~getpicture(void)
{
}
int getpicture::socketConnect(int PORT)
{
int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);//创建套接字,初始化信息
struct sockaddr_in server_sockaddr; //指向sockaddr地址的指针,该结构含有IP和PORT
server_sockaddr.sin_family = AF_INET; //ipv4
server_sockaddr.sin_port = htons(PORT); //端口
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //ip地址
if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)//bind函数将socket关联一个本地地址
{
perror("bind");
return -1;
}
if(listen(server_sockfd,5) == -1)//listen来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。
{
perror("listen");
return -1;
}
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);
sockConn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length); //socket()、bind()、listen()之后,就会监听指定的socket地址了。
//TCP客户端依次调用socket()、connect()之后就想TCP服务器发送了一个连接请求。
//TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。
if(sockConn<0) //之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。
{
perror("connect");
return -1;
}
else
{
printf("connect successful!\n");
}
// int nRecvBuf = 1024 * 1024 * 20;
// setsockopt(sockConn, SOL_SOCKET, SO_RCVBUF, (const char*)&nRecvBuf, sizeof(int));
}
void getpicture::socketDisconnect(void)
{
close(sockConn);
}
int getpicture::acceptfile(Mat& image)
{
int returnflag = 0;
cv::Mat img(img_height, img_width, CV_8UC3, cv::Scalar(0));
needRecv = sizeof(recvBuf); //struct recvBuf int needRecv
count = 0;
memset(&data,0,sizeof(data));
for (int p=0;p<img_num;p++)
{
for (int i = 0; i < packet_num; i++) //一张图片划分为n个区域来传递,一个像素一个像素的传递
{
int pos = 0;
int len0 = 0;
while (pos < needRecv) //接收缓冲区