tcp+opencv 视频传输

来源:互联网 发布:bugclose 源码下载 编辑:程序博客网 时间:2024/05/21 06:57

环境:

Server: Ubuntu 14.04 LTS + OpenCV2.4.10 

Client:: Ubuntu 14.04 LTS + OpenCV2.4.10 


我采用的仍是TCP协议的通信,linux上的实现和Windows大同小异

Linux中opencv的编译安装可以参考 http://blog.csdn.net/pengz0807/article/details/49915573

TCP协议通信的一般步骤我再重新说一下:

客户端:

       1、创建一个socket,用函数socket(); 
  2、设置socket属性,用函数setsockopt();* 可选 
  3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
  4、设置要连接的对方的IP地址和端口等属性; 
  5、连接服务器,用函数connect(); 
  6、收发数据,用函数send()和recv(),或者read()和write(); 
  7、关闭网络连接;

服务器端:

       1、创建一个socket,用函数socket(); 
  2、设置socket属性,用函数setsockopt(); * 可选 
  3、绑定IP地址、端口等信息到socket上,用函数bind(); 
  4、开启监听,用函数listen(); 
  5、接收客户端上来的连接,用函数accept(); 
  6、收发数据,用函数send()和recv(),或者read()和write(); 
  7、关闭网络连接; 
  8、关闭监听; 


我把图像的发送和接收分别封装在了两个类中:

采集与发送:


SocketMatTransmissionClient.h

[cpp] view plain copy
  1. /*M/////////////////////////////////////////////////////////////////////////////////////// 
  2. // 
  3. //  基于OpenCV和Socket的图像传输(发送) 
  4.  
  5. //M*/  
  6.   
  7. #ifndef __SOCKETMATTRANSMISSIONCLIENT_H__  
  8. #define __SOCKETMATTRANSMISSIONCLIENT_H__  
  9.   
  10. #include "opencv2/opencv.hpp"  
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13. #include <string.h>  
  14. #include <errno.h>  
  15. #include <unistd.h>  
  16. #include <sys/types.h>  
  17. #include <sys/socket.h>  
  18. #include <netinet/in.h>  
  19. #include <arpa/inet.h>  
  20.   
  21. using namespace cv;  
  22.   
  23. //待传输图像默认大小为 640*480,可修改  
  24. #define IMG_WIDTH 640   // 需传输图像的宽  
  25. #define IMG_HEIGHT 480  // 需传输图像的高  
  26. #define PACKAGE_NUM 2  
  27. //默认格式为CV_8UC3  
  28. #define BUFFER_SIZE IMG_WIDTH*IMG_HEIGHT*3/PACKAGE_NUM  
  29.   
  30. struct sentbuf  
  31. {  
  32.     char buf[BUFFER_SIZE];  
  33.     int flag;  
  34. };  
  35.   
  36. class SocketMatTransmissionClient  
  37. {  
  38. public:  
  39.     SocketMatTransmissionClient(void);  
  40.     ~SocketMatTransmissionClient(void);  
  41.   
  42. private:  
  43.     int sockClient;  
  44.     struct sentbuf data;  
  45.   
  46. public:  
  47.   
  48.     // 打开socket连接  
  49.     // params : IP      服务器的ip地址  
  50.     //          PORT    传输端口  
  51.     // return : -1      连接失败  
  52.     //          1       连接成功  
  53.     int socketConnect(const char* IP, int PORT);  
  54.   
  55.   
  56.     // 传输图像  
  57.     // params : image 待传输图像  
  58.     // return : -1      传输失败  
  59.     //          1       传输成功  
  60.     int transmit(cv::Mat image);  
  61.   
  62.   
  63.     // 断开socket连接  
  64.     void socketDisconnect(void);  
  65. };  
  66.   
  67. #endif  


SocketMatTransmissionClient.cpp
[cpp] view plain copy
  1. /*M/////////////////////////////////////////////////////////////////////////////////////// 
  2. // 
  3. //  基于OpenCV和Socket的图像传输(发送) 
  4. //M*/  
  5.   
  6.   
  7. #include "SocketMatTransmissionClient.h"  
  8.   
  9. SocketMatTransmissionClient::SocketMatTransmissionClient(void)  
  10. {  
  11. }  
  12.   
  13.   
  14. SocketMatTransmissionClient::~SocketMatTransmissionClient(void)  
  15. {  
  16. }  
  17.   
  18.   
  19. int SocketMatTransmissionClient::socketConnect(const char* IP, int PORT)  
  20. {  
  21.     struct sockaddr_in    servaddr;  
  22.   
  23.     if ((sockClient = socket(AF_INET, SOCK_STREAM, 0)) < 0)   
  24.     {  
  25.         printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);  
  26.         return -1;  
  27.     }  
  28.   
  29.     memset(&servaddr, 0, sizeof(servaddr));  
  30.     servaddr.sin_family = AF_INET;  
  31.     servaddr.sin_port = htons(PORT);  
  32.     if (inet_pton(AF_INET, IP, &servaddr.sin_addr) <= 0)   
  33.     {  
  34.         printf("inet_pton error for %s\n", IP);  
  35.         return -1;  
  36.     }  
  37.   
  38.     if (connect(sockClient, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)   
  39.     {  
  40.         printf("connect error: %s(errno: %d)\n", strerror(errno), errno);  
  41.         return -1;  
  42.     }  
  43.     else   
  44.     {  
  45.         printf("connect successful!\n");  
  46.     }  
  47. }  
  48.   
  49.   
  50. void SocketMatTransmissionClient::socketDisconnect(void)  
  51. {  
  52.     close(sockClient);  
  53. }  
  54.   
  55. int SocketMatTransmissionClient::transmit(cv::Mat image)  
  56. {  
  57.     if (image.empty())  
  58.     {  
  59.         printf("empty image\n\n");  
  60.         return -1;  
  61.     }  
  62.   
  63.     if(image.cols != IMG_WIDTH || image.rows != IMG_HEIGHT || image.type() != CV_8UC3)  
  64.     {  
  65.         printf("the image must satisfy : cols == IMG_WIDTH(%d)  rows == IMG_HEIGHT(%d) type == CV_8UC3\n\n", IMG_WIDTH, IMG_HEIGHT);  
  66.         return -1;  
  67.     }  
  68.   
  69.     for(int k = 0; k < PACKAGE_NUM; k++)   
  70.     {  
  71.         int num1 = IMG_HEIGHT / PACKAGE_NUM * k;  
  72.         for (int i = 0; i < IMG_HEIGHT / PACKAGE_NUM; i++)  
  73.         {  
  74.             int num2 = i * IMG_WIDTH * 3;  
  75.             uchar* ucdata = image.ptr<uchar>(i + num1);  
  76.             for (int j = 0; j < IMG_WIDTH * 3; j++)  
  77.             {  
  78.                 data.buf[num2 + j] = ucdata[j];  
  79.             }  
  80.         }  
  81.   
  82.         if(k == PACKAGE_NUM - 1)  
  83.             data.flag = 2;  
  84.         else  
  85.             data.flag = 1;  
  86.   
  87.         if (send(sockClient, (char *)(&data), sizeof(data), 0) < 0)  
  88.         {  
  89.             printf("send image error: %s(errno: %d)\n", strerror(errno), errno);  
  90.             return -1;  
  91.         }  
  92.     }  
  93. }  


接收与显示:

SocketMatTransmissionServer.h

[cpp] view plain copy
  1. /*M/////////////////////////////////////////////////////////////////////////////////////// 
  2. // 
  3. //  基于OpenCV和Socket的图像传输(接收) 
  4. //M*/  
  5.   
  6. #ifndef __SOCKETMATTRANSMISSIONSEVER_H__  
  7. #define __SOCKETMATTRANSMISSIONSEVER_H__  
  8.   
  9. #include "opencv2/opencv.hpp"  
  10. #include <stdio.h>  
  11. #include <stdlib.h>  
  12. #include <string.h>  
  13. #include <errno.h>  
  14. #include <unistd.h>  
  15. #include <sys/shm.h>  
  16. #include <sys/types.h>  
  17. #include <sys/socket.h>  
  18. #include <netinet/in.h>  
  19. #include <arpa/inet.h>  
  20.   
  21. using namespace cv;  
  22.   
  23. #define PACKAGE_NUM 2  
  24.   
  25. #define IMG_WIDTH 640  
  26. #define IMG_HEIGHT 480  
  27.   
  28. #define BLOCKSIZE IMG_WIDTH*IMG_HEIGHT*3/PACKAGE_NUM  
  29.   
  30. struct recvBuf  
  31. {  
  32.     char buf[BLOCKSIZE];  
  33.     int flag;  
  34. };  
  35.   
  36.   
  37. class SocketMatTransmissionServer  
  38. {  
  39. public:  
  40.     SocketMatTransmissionServer(void);  
  41.     ~SocketMatTransmissionServer(void);  
  42.     int sockConn;  
  43. private:  
  44.     struct recvBuf data;  
  45.   
  46.     int needRecv;  
  47.     int count;  
  48.   
  49. public:  
  50.   
  51.     // 打开socket连接  
  52.     // params : PORT    传输端口  
  53.     // return : -1      连接失败  
  54.     //          1       连接成功  
  55.     int socketConnect(int PORT);  
  56.   
  57.   
  58.     // 传输图像  
  59.     // params : image   待接收图像  
  60.     //      image   待接收图像  
  61.     // return : -1      接收失败  
  62.     //          1       接收成功  
  63.     int receive(cv::Mat& image);  
  64.   
  65.   
  66.     // 断开socket连接  
  67.     void socketDisconnect(void);  
  68. };  
  69.   
  70. #endif  

SocketMatTransmissionServer.cpp

[cpp] view plain copy
  1. /*M/////////////////////////////////////////////////////////////////////////////////////// 
  2. // 
  3. //  基于OpenCV和Socket的图像传输(接收) 
  4. //   
  5. //M*/  
  6.   
  7.   
  8. #include "SocketMatTransmissionServer.h"  
  9.   
  10. SocketMatTransmissionServer::SocketMatTransmissionServer(void)  
  11. {  
  12. }  
  13.   
  14.   
  15. SocketMatTransmissionServer::~SocketMatTransmissionServer(void)  
  16. {  
  17. }  
  18.   
  19.   
  20. int SocketMatTransmissionServer::socketConnect(int PORT)  
  21. {  
  22.     int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);  
  23.   
  24.     struct sockaddr_in server_sockaddr;  
  25.     server_sockaddr.sin_family = AF_INET;  
  26.     server_sockaddr.sin_port = htons(PORT);  
  27.     server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);  
  28.   
  29.     if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)  
  30.     {  
  31.         perror("bind");  
  32.         return -1;  
  33.     }  
  34.   
  35.     if(listen(server_sockfd,5) == -1)  
  36.     {  
  37.         perror("listen");  
  38.         return -1;  
  39.     }  
  40.   
  41.     struct sockaddr_in client_addr;  
  42.     socklen_t length = sizeof(client_addr);  
  43.   
  44.     sockConn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length);  
  45.     if(sockConn<0)  
  46.     {  
  47.         perror("connect");  
  48.         return -1;  
  49.     }  
  50.     else  
  51.     {  
  52.         printf("connect successful!\n");  
  53.         return 1;  
  54.     }  
  55.       
  56.     close(server_sockfd);  
  57. }  
  58.   
  59.   
  60. void SocketMatTransmissionServer::socketDisconnect(void)  
  61. {  
  62.     close(sockConn);  
  63. }  
  64.   
  65. int SocketMatTransmissionServer::receive(cv::Mat& image)  
  66. {  
  67.     int returnflag = 0;  
  68.     cv::Mat img(IMG_HEIGHT, IMG_WIDTH, CV_8UC3, cv::Scalar(0));  
  69.     needRecv = sizeof(recvBuf);  
  70.     count = 0;  
  71.     memset(&data,0,sizeof(data));  
  72.   
  73.     for (int i = 0; i < PACKAGE_NUM; i++)  
  74.     {  
  75.         int pos = 0;  
  76.         int len0 = 0;  
  77.   
  78.         while (pos < needRecv)  
  79.         {  
  80.             len0 = recv(sockConn, (char*)(&data) + pos, needRecv - pos, 0);  
  81.             if (len0 < 0)  
  82.             {  
  83.                 printf("Server Recieve Data Failed!\n");  
  84.                 break;  
  85.             }  
  86.             pos += len0;  
  87.         }  
  88.   
  89.         count = count + data.flag;  
  90.   
  91.         int num1 = IMG_HEIGHT / PACKAGE_NUM * i;  
  92.         for (int j = 0; j < IMG_HEIGHT / PACKAGE_NUM; j++)  
  93.         {  
  94.             int num2 = j * IMG_WIDTH * 3;  
  95.             uchar* ucdata = img.ptr<uchar>(j + num1);  
  96.             for (int k = 0; k < IMG_WIDTH * 3; k++)  
  97.             {  
  98.                 ucdata[k] = data.buf[num2 + k];  
  99.             }  
  100.         }  
  101.   
  102.         if (data.flag == 2)  
  103.         {  
  104.             if (count == PACKAGE_NUM + 1)  
  105.             {  
  106.                 image = img;  
  107.                 returnflag = 1;  
  108.                 count = 0;  
  109.             }  
  110.             else  
  111.             {  
  112.                 count = 0;  
  113.                 i = 0;  
  114.             }  
  115.         }  
  116.     }  
  117.     if(returnflag == 1)  
  118.         return 1;  
  119.     else  
  120.         return -1;  
  121. }  


示例代码:

图像的采集与发送:

SocketClientMat.cpp

[cpp] view plain copy
  1. #include "SocketMatTransmissionClient.h"  
  2.   
  3. int main()  
  4. {  
  5.     SocketMatTransmissionClient socketMat;  
  6.     if (socketMat.socketConnect("127.0.0.1", 6666) < 0)  
  7.     {  
  8.         return 0;  
  9.     }  
  10.       
  11.     cv::VideoCapture capture(0);  
  12.     cv::Mat image;  
  13.   
  14.     while (1)  
  15.     {  
  16.         if (!capture.isOpened())  
  17.             return 0;  
  18.   
  19.         capture >> image;  
  20.   
  21.         if (image.empty())  
  22.             return 0;  
  23.   
  24.         socketMat.transmit(image);  
  25.     }  
  26.   
  27.     socketMat.socketDisconnect();  
  28.     return 0;  
  29. }  

接收与显示:

SocketServerMat.cpp

[cpp] view plain copy
  1. #include "SocketMatTransmissionServer.h"  
  2.   
  3. int main()  
  4. {  
  5.     SocketMatTransmissionServer socketMat;  
  6.     if (socketMat.socketConnect(6666) < 0)  
  7.     {  
  8.         return 0;  
  9.     }  
  10.   
  11.     cv::Mat image;  
  12.     while (1)  
  13.     {  
  14.         if(socketMat.receive(image) > 0)  
  15.         {  
  16.             cv::imshow("",image);  
  17.             cv::waitKey(30);  
  18.         }  
  19.     }  
  20.   
  21.     socketMat.socketDisconnect();  
  22.     return 0;  


原创粉丝点击