树莓派centos 第二十章:作视频服务器编程,(C++、socket、opencv)

8 篇文章 1 订阅
8 篇文章 0 订阅

这个项程序是用c++写的,运行过程,服务端读取摄像头数据,并建立socker server, 作为视频服务器,本机再运行client.pp读取服务端的视步图像,server.cpp, 与client.cpp,可以同时在两台机使用。

先看看效果图。

1. 每一步,装好摄像头硬件,

2. 建立两个文件,

server.cpp 是服务端程序

client.cpp 是客户端程序

 3. 编写服务端代码( server.cpp)

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <vector>

using namespace std; 
using namespace cv;

int main(int argc, char** argv)
{
    int    listenfd, connfd;
    struct sockaddr_in     servaddr;
    char    buff[4096];
    int     n;
    int sendbytes;
    int connectstatus =0;


    while(1)
    {
        if( connectstatus== 0)
        {
            if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
            {
                printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
                exit(0);
            }
            memset(&servaddr, 0, sizeof(servaddr));
            servaddr.sin_family = AF_INET;
            servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
            servaddr.sin_port = htons(8001);

            int opt = 1;
            /* set port reuse */
            if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const void *)&opt,sizeof(opt)))
            {
                perror("setsockopt");
                return -1;
            }

            if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)
            {
                printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
                exit(0);
            }

            if( listen(listenfd, 10) == -1)
            {
                printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
                exit(0);
            }
        }

        /* ---main task process--- */
        Mat frame;
        VideoCapture cap;
        vector<unsigned char> inImage;  
        /* open camera */
        cap.open(0);
        if (!cap.isOpened()) 
        {
            cerr << "ERROR! Unable to open camera\n";
            return -1;
        }

        printf("open camera success\n");
        printf("======waiting for client's apple request======\n");

        if((connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1)
        {
            printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
            exit(0);
        }
        {
            printf("accept socket success!!\n");
        }
    
        char cok[1]={0x55};
        char cokstart[1]={0};
        char j = 0;
        int sizelen=0;
        int sizejpg=0;
    
        for (;;)
        {


            if(waitKey(5)>=0)
                break;

            if (cok[0]==0x55)
            {


                cap.read(frame);

                if (frame.empty()) 
                {
                    cerr << "ERROR! blank frame grabbed\n";
                    break;
                }

                cok[0]=0;
                imencode(".jpg",frame,inImage);  

                int datalen=inImage.size()+1;
            
                unsigned char *msgImage=new unsigned char[datalen]; 
                memset(msgImage, 0 ,datalen);

                unsigned char msgLen[4];
                msgLen[0]=datalen >> 24;
                msgLen[1]=datalen >> 16;
                msgLen[2]=datalen >> 8;
                msgLen[3]=datalen;

                sizelen=send(connfd,msgLen,4,0);

                for(int i=0;i<datalen;i++)  
                {  
                    msgImage[i]=inImage[i];  
                } 

                recv(connfd,cokstart,1,0);

                if(cokstart[0] == 0x33)
                {
                    vector<char>vec;
                    Mat img_decode;

                    cokstart[0]=0x0;

                    for(int i=0;i<datalen;i++)
                    {
                        vec.push_back(msgImage[i]);
                    }

                    img_decode =imdecode(vec,CV_LOAD_IMAGE_COLOR);
                    printf("send image data length:%d\n",datalen);
                    sizejpg=send(connfd, msgImage, datalen, 0);

                }

               // usleep(10);
                recv(connfd, cok, 1, 0);
            }

        }
        close(listenfd);
    }
    return 0;
}

4. 编写客户端代码(client.cpp)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include<vector>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio.hpp>
#include <unistd.h>
#include <iostream>

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
    int    sockfd, n;
    char    recvline[4096], sendline[4096];
    struct sockaddr_in    servaddr;
    
    int ntry =0;

    #if 0
    if( argc != 2)
    {
        printf("usage: ./client <ipaddress>\n");
        exit(0);

    }
    #endif

    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
    printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
    exit(0);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(8008);

    if( inet_pton(AF_INET, "10.8.0.88", &servaddr.sin_addr) <= 0)
    {
        printf("inet_pton error for %s\n",argv[1]);
        exit(0);
    }

    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
    {
    printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    #define BUF_SIZE 254280
    char buffer[ BUF_SIZE ];
    
    Mat img_decode; 
    //string filename="";   
    int size = 0;
    int mylen = 0;
    int j= 0;
    char cokstart[ 1 ]={0x33};
    
    int nTry =0;

    while(1)
    {

        memset( buffer, 0, BUF_SIZE );
        vector<char> vec;

        size = recv(sockfd,buffer,4,0);

        unsigned char a0 = buffer[0];
        int b0 = (int)a0;

        int mylen0 =  b0* (int)0x1000000;

        unsigned char a1 = buffer[1];
        int b1 = (int)a1;
        int mylen1 =  a1* (int)0x10000;

        unsigned char a2 = buffer[2];
        int b2 = (int)a2;
        int mylen2 =  a2* (int)0x100;

        unsigned char a3 = buffer[3];
        int b3 = (int)a3;
        int mylen3 =  b3;

        

        mylen = mylen0 + mylen1 + mylen2 + mylen3;


        printf("receive data length: %d\n",mylen);

        if (mylen>0)
        {
            /*received length then send ack signal cokstart.*/  
            send(sockfd, cokstart, 1, 0);      
        }
        /* receive one frame of jpg data */
        if(mylen>100)
        {
            while(mylen) 
            {
                memset( buffer, 0, BUF_SIZE );
                size=recv(sockfd,buffer,mylen,0);

                for(int i = 0 ; i < size ; i++)  
                {  
                    vec.push_back(buffer[i]);
                }
                mylen = mylen-size;  
            }

            /* decode jpg data */
            img_decode = imdecode(vec, CV_LOAD_IMAGE_COLOR); 
            /* release vector then ready to receive next frame */
            vec.clear();
            //cout << "vector capacity:"<<vec.capacity()<<endl;
            vector<char>(vec).swap(vec);
            //cout << "vector capacity afterswap:"<<vec.capacity()<<endl;
        
            /* display the jpg in windows */
            namedWindow("pic",WINDOW_AUTOSIZE);

            if(  !img_decode.empty())
            {
                imshow("pic",img_decode);     
                /* save to file -- this function is optional */
                //j++;
                //filename = "pic"+int2string(j)+".jpg";
                //imwrite(filename,img_decode);   
            }
        
            /* reflash display window in every 33ms */
            cvWaitKey(33);

            /* send ack signal cok to tell that I'm ready to handler next frame */
            char cok[ 1 ]={0x55};

            send(sockfd, cok, 1, 0);
            usleep(1000);
        }

        nTry++;

    }
    exit(0);

}

 5. 编译服务端后台程序

g++ server.cpp -o ser1 `pkg-config opencv --cflags` `pkg-config opencv --libs`

6. 编译客户端程序

g++ client.cpp -o cli1 `pkg-config opencv --cflags` `pkg-config opencv --libs`

7. 运行服务器程序 

./ser1

8. 运行客户端程序

./cli1

测试效果一切正常,

小结:通过这个程序,可以了解 报像头的图像转换为字符串,并通过socket发送数据,客服端则接收数据后重新转换为图像,不过,这个过程,可能会有延时,大约一秒左右。

并且刷率很低。

源代码下载路径:

https://download.csdn.net/download/meekiki/21454087

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

树莓派centos

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值