1 | 上位机—笔记本 |
2 | 下位机–树莓派zero w/树莓派3B+ |
3 | 树莓派V2相机–800w像素 |
2.基于SOCKET的通信
Server----做为服务器接收图片
Client----做为客户端采集图片并经过socket的网口链接传输ios
3.树莓派Linux,笔记本Windows/Linuxweb
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.hsocket
#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.cppide
#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) //接收缓冲区中的数据可能大于buf,因此须要调用几回recv函数把接收缓冲区中的数据彻底copy { len0 = recv(sockConn, (char*)(&data) + pos, needRecv - pos, 0);//3.needRecv>2buf 分屡次传 每次传pos的数据量 if (len0 < 0)//3 { printf("Server Recieve Data Failed!\n"); break; } pos += len0;// } count = count + data.flag;//1+1+1+1+1+1+1+.....2 int num1 = img_height / packet_num * i; //划分为每一行像素 for (int j = 0; j < img_height / packet_num; j++) { int num2 = j * img_width * 3; uchar* ucdata = img.ptr<uchar>(j + num1); for (int k = 0; k < img_width * 3; k++) { ucdata[k] = data.buf[num2 + k]; //划分为每一个像素 } } if (data.flag == 2) //一张图片的最后一块区域 data.flag=2 { if (count == packet_num + 1)//表示一张图片是传输完整的 { image = img; string str="/home/yqz/图片/"+to_string(p+1)+".jpg"; imwrite(str,img); returnflag++; count = 0;// one picture over,begin next } else { count = 0; //if (count != PACKAGE_NUM + 1) restart transmit i = 0; } } } } if(returnflag == img_num) return 1; else return -1; }
Server端代码-----(Windows)svg
1.main.cpp函数
#include"several_mat.h" int main() { getpicture img; if (img.socketConnect(8888) < 0) { cout << "connect error!"; return -1; } Mat image; if (img.acceptfile(image) > 0) { cout << "accept is OK!"; } img.socketDisconnect(); system("pause"); return 0; }
2.several_mat.hspa
#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 <sys/types.h> #include <iostream> #include <WinSock2.h> #pragma comment(lib,"Ws2_32.lib ") using namespace std; using namespace cv; #define MAXLINE 1024*1024 #define img_width 1920 #define img_height 1080 #define img_num 20 #define packet_num 8 struct recvBuf { char buf[MAXLINE]; int flag; }; class getpicture { public: getpicture(void); ~getpicture(void); int socketConnect(int PORT); int acceptfile(Mat& image); void socketDisconnect(void); private: struct recvBuf data; int needRecv; int count; SOCKET sockConn; };
3.several_mat.cpp.net
#include"several_mat.h" getpicture::getpicture(void) { } getpicture::~getpicture(void) { } int getpicture::socketConnect(int PORT) { //初始化WSA WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; if (::WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)//初始化供进程调用的Winsock相关的dll { cout << "WSAStartup error" << endl; //WSACleanup()释放Ws2_32.dl的l函数 return 0; } SOCKET server_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//socket函数将建立指定传输服务的socket if (server_sockfd == INVALID_SOCKET) { int er = WSAGetLastError(); return 0; } u_long mode = 0; ioctlsocket(server_sockfd, FIONBIO, &mode); sockaddr_in server_sockaddr; //指定一个未绑定的socket server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(PORT); server_sockaddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.2"); //server_sockaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); if (::bind(server_sockfd, (const SOCKADDR*)&server_sockaddr, sizeof(SOCKADDR)) == SOCKET_ERROR)//bind函数将socket关联一个本地地址 { perror("bind"); return -1; } if (listen(server_sockfd, 5) == SOCKET_ERROR) { perror("listen"); return -1; } printf("Listening To Client...\n"); sockaddr_in client_addr; int length = sizeof(client_addr); sockConn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length); if (sockConn < 0) { 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) { closesocket(sockConn); WSACleanup(); } 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++) { int pos = 0; int len0 = 0; while (pos < needRecv) { len0 = recv(sockConn, (char*)(&data) + pos, needRecv - pos, 0);//3needRecv>2buf fen duoci chuan meicichuan pos if (len0 < 0)//3 { printf("Server Recieve Data Failed!\n"); break; } pos += len0;// } count = count + data.flag;//1+1+1+1+1+1+1+.....2 int num1 = img_height / packet_num * i; for (int j = 0; j < img_height / packet_num; j++) { int num2 = j * img_width * 3; uchar* ucdata = img.ptr<uchar>(j + num1); for (int k = 0; k < img_width * 3; k++) { ucdata[k] = data.buf[num2 + k]; } } if (data.flag == 2) //final area data.flag=2 { if (count == packet_num + 1) { image = img; string str = "d:\\" + to_string(p + 1) + ".jpg"; imwrite(str, img); returnflag++; count = 0;// one picture over,begin next } else { count = 0; //if (count != PACKAGE_NUM + 1) restart transmit i = 0; } } } } if (returnflag == img_num) return 1; else return -1; }
Client-----(树莓派采集图片)
边拍变传
1.main.cpp
#include <severalimg.h> int main() { severalimg img; if(img.connectsocket("192.168.1.2",8888)<0) { cout<<"connect error!"; return -1; } if(img.getandtransmit()>0) { cout<<"transmit is right!"; } img.socketDisconnect(); return 0; }
2.severalimg.h
/////////////////////////////////////////////////////////////////////////////severalimg.h #ifndef SEVERALIMG_H #define SEVERALIMG_H #endif // SEVERALIMG_H #include<iostream> #include<opencv2/opencv.hpp> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> using namespace std; using namespace cv; #define img_width 1920 #define img_height 1080 #define img_exposure -20 #define img_fps 30 #define MAXLINE 1024*1024 #define delay 1000 //1s=1000ms #define img_num 20 #define packet_num 8 struct sentbuf { char buf[MAXLINE]; int flag; }; class severalimg { public: severalimg(void); ~severalimg(void); int connectsocket(const char* IP,int PORT); // int transmit(vector<Mat>img); // vector<Mat> getimg(); int getandtransmit(); void socketDisconnect(); private: struct sentbuf data; int sockClient; }; ///////////////////////////////////////////////////////////////////////////severalimg.cpp #include<severalimg.h> severalimg::severalimg(void) { } severalimg::~severalimg(void) { } int severalimg::getandtransmit() { VideoCapture capture(0); Mat img; int imgimg_num=0; capture.set(CV_CAP_PROP_FRAME_WIDTH,img_width); capture.set(CV_CAP_PROP_FRAME_HEIGHT,img_height); capture.set(CV_CAP_PROP_FPS,img_fps); capture.set(CV_CAP_PROP_EXPOSURE, img_exposure); if(!capture.isOpened()) { cout<<"The camera can not open!"<<endl; //return -1; } while(1) { for(int i=0;i<img_num;i++) { Mat image; capture>>image; img=image; String img_name="/home/pi/imgimg/"+to_string(i+1)+".jpg"; imwrite(img_name,image); for(int k = 0; k < packet_num; k++)//##划分每块区域 { int num1 = img_height / packet_num * k;//720/8 *(0-7) 每块区域的第一个元素 for (int i = 0; i < img_height/ packet_num; i++) //##划分每块区域的每一行 { int num2 = i * img_width * 3; uchar* ucdata = img.ptr<uchar>(i + num1);//第一行第一个元素,第二行第一个元素 for (int j = 0; j < img_width * 3; j++)//##划分每块区域每一行的每个元素 { data.buf[num2 + j] = ucdata[j];//每一行的元素每一个元素相对应 } } if(k == packet_num - 1) { //最后一块区域data.flag为2,反之为1 data.flag = 2; } else { data.flag = 1; } //发送8次数据 if (send(sockClient, (char *)(&data), sizeof(data), 0) < 0) { printf("send image error: %s(errno: %d)\n", strerror(errno), errno); return -1; } } waitKey(delay); imgimg_num++; } capture.release(); break; } if(img_num==imgimg_num) return 1; else return -1; } int severalimg::connectsocket(const char* IP, int PORT)//dingyi socket { struct sockaddr_in servaddr; if ((sockClient = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("create socket error: %s(errno: %d)\n", strerror(errno), errno); return -1; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); if (inet_pton(AF_INET, IP, &servaddr.sin_addr) <= 0) { printf("inet_pton error for %s\n", IP); return -1; } if (connect(sockClient, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { printf("connect error: %s(errno: %d)\n", strerror(errno), errno); return -1; } else { //int nsendbuf=1024*1024; //setsockopt(sockClient,SOL_SOCKET,SO_SNDBUF,(const char*)&nsendbuf,sizeof(int)); printf("connect successful!\n"); return 1; } } //int severalimg::transmit(vector<Mat>picture) //{ // if(picture.empty()) // { // cout<<"empty picture"; // return -1; // } // Mat img1; // for(int l=0;l<img_num;l++) // { // img1=picture[l]; // for(int k = 0; k < packet_num; k++)//##划分每块区域 // { // int num1 = img_height / packet_num * k;//720/8 *(0-7) 每块区域的第一个元素 // for (int i = 0; i < img_height/ packet_num; i++) //##划分每块区域的每一行 // { // int num2 = i * img_width * 3; // uchar* ucdata = img1.ptr<uchar>(i + num1);//第一行第一个元素,第二行第一个元素 // for (int j = 0; j < img_width * 3; j++)//##划分每块区域每一行的每个元素 // { // data.buf[num2 + j] = ucdata[j];//每一行的元素每一个元素相对应 // } // } // if(k == packet_num - 1) // { //最后一块区域data.flag为2,反之为1 // data.flag = 2; // } // else // { // data.flag = 1; // } //发送8次数据 // if (send(sockClient, (char *)(&data), sizeof(data), 0) < 0) // { // printf("send image error: %s(errno: %d)\n", strerror(errno), errno); // return -1; // } // } // } //} void severalimg::socketDisconnect() { close(sockClient); }
3.severalimg.cpp
//也能够自行修改为,把所有照片拍摄完之后再传输 #include<severalimg.h> severalimg::severalimg(void) { } severalimg::~severalimg(void) { } int severalimg::getandtransmit() { VideoCapture capture(0); Mat img; int imgimg_num; capture.set(CV_CAP_PROP_FRAME_WIDTH,img_width); capture.set(CV_CAP_PROP_FRAME_HEIGHT,img_height); capture.set(CV_CAP_PROP_FPS,img_fps); capture.set(CV_CAP_PROP_EXPOSURE, img_exposure); if(!capture.isOpened()) { cout<<"The camera can not open!"<<endl; //return -1; } while(1) { for(int i=0;i<img_num;i++) { Mat image; capture>>image; img=image; String img_name="/home/pi/imgimg/"+to_string(i+1)+".jpg"; imwrite(img_name,image); for(int k = 0; k < packet_num; k++)//##划分每块区域 { int num1 = img_height / packet_num * k;//720/8 *(0-7) 每块区域的第一个元素 for (int i = 0; i < img_height/ packet_num; i++) //##划分每块区域的每一行 { int num2 = i * img_width * 3; uchar* ucdata = img.ptr<uchar>(i + num1);//第一行第一个元素,第二行第一个元素 for (int j = 0; j < img_width * 3; j++)//##划分每块区域每一行的每个元素 { data.buf[num2 + j] = ucdata[j];//每一行的元素每一个元素相对应 } } if(k == packet_num - 1) { //最后一块区域data.flag为2,反之为1 data.flag = 2; } else { data.flag = 1; } //发送8次数据 if (send(sockClient, (char *)(&data), sizeof(data), 0) < 0) { printf("send image error: %s(errno: %d)\n", strerror(errno), errno); return -1; } } waitKey(delay); imgimg_num++; } capture.release(); break; } if(img_num==imgimg_num) return 1; else return -1; } int severalimg::connectsocket(const char* IP, int PORT)//dingyi socket { struct sockaddr_in servaddr; if ((sockClient = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("create socket error: %s(errno: %d)\n", strerror(errno), errno); return -1; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); if (inet_pton(AF_INET, IP, &servaddr.sin_addr) <= 0) { printf("inet_pton error for %s\n", IP); return -1; } if (connect(sockClient, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { printf("connect error: %s(errno: %d)\n", strerror(errno), errno); return -1; } else { //int nsendbuf=1024*1024; //setsockopt(sockClient,SOL_SOCKET,SO_SNDBUF,(const char*)&nsendbuf,sizeof(int)); printf("connect successful!\n"); return 1; } } //int severalimg::transmit(vector<Mat>picture) //{ // if(picture.empty()) // { // cout<<"empty picture"; // return -1; // } // Mat img1; // for(int l=0;l<img_num;l++) // { // img1=picture[l]; // for(int k = 0; k < packet_num; k++)//##划分每块区域 // { // int num1 = img_height / packet_num * k;//720/8 *(0-7) 每块区域的第一个元素 // for (int i = 0; i < img_height/ packet_num; i++) //##划分每块区域的每一行 // { // int num2 = i * img_width * 3; // uchar* ucdata = img1.ptr<uchar>(i + num1);//第一行第一个元素,第二行第一个元素 // for (int j = 0; j < img_width * 3; j++)//##划分每块区域每一行的每个元素 // { // data.buf[num2 + j] = ucdata[j];//每一行的元素每一个元素相对应 // } // } // if(k == packet_num - 1) // { //最后一块区域data.flag为2,反之为1 // data.flag = 2; // } // else // { // data.flag = 1; // } //发送8次数据 // if (send(sockClient, (char *)(&data), sizeof(data), 0) < 0) // { // printf("send image error: %s(errno: %d)\n", strerror(errno), errno); // return -1; // } // } // } //} void severalimg::socketDisconnect() { close(sockClient); }
参考博客:
https://blog.csdn.net/pengz0807/article/details/52204475