How to transfer cv::VideoCapture frames through so

2020-03-31 08:11发布

I translate video through socket and I see video stream in other side but I cant receive video. My video file is empty. I am thinking the problem can be wrong convert video format on the receive side. How I should encode video on the server side and how I should decode video in the client side?

I use Linux Ubuntu Mate, OpenCV 2.4.13.

Server:

#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fstream>
#include <cstring>
#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <iomanip>
#include <pthread.h>
#include <SerialStream.h>
#include <unistd.h>
#include <ctime>
#include <iomanip>
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/core/types_c.h>
#include <vector>
#include <arpa/inet.h>
#include <unistd.h>

using namespace std;
using namespace cv;

char answer[] = "Y";
int main()
{
int sock, listener;
struct sockaddr_in addr;
char buf[1024];
int bytes_read;


if( (listener = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
    perror("socket() failed");
    exit(1);
}

addr.sin_family = AF_INET;
addr.sin_port = htons(3425);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
    perror("bind");
    exit(2);
}

listen(listener, 1);
ofstream of("readFile.txt");
vector<int> param;
param.push_back(CV_IMWRITE_JPEG_QUALITY);


Mat frame = Mat::zeros(480, 640, CV_8UC3);
Mat receive;
int imgSize = frame.total()*frame.elemSize();

if(! frame.isContinuous() ){
    frame = frame.clone();
}

namedWindow("CV Video Client", 1);

uchar *iptr = frame.data;

int key;

uchar sockData[imgSize];
int count_of_receive_frame = 0;
int num_of_recv_bytes;
VideoWriter outputVideo;
Size S = Size((int) 480,(int) 640);
outputVideo.open("receive.avi", CV_FOURCC('X','V','I','D'), 30, S, true);
int i = 0;

char name_of_photo[20];
while(1)
{
    sock = accept(listener, NULL, NULL);
    if(sock < 0)
    {
        perror("accept");
        exit(3);
    }

    while(key != 'q'){



        if( num_of_recv_bytes = recv(sock, iptr, imgSize, MSG_WAITALL) == -1 ){
            cerr << "recv failed, received bytes = " << num_of_recv_bytes << endl;
        }

        imshow("CV Video Client", frame);

        outputVideo.write(frame);


        if (key = waitKey(10) >= 0) break;


    }
    outputVideo.release();
    close(sock);
    break;
}


return 0;
}

Client:

#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fstream>
#include <cstring>
#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <iomanip>
#include <pthread.h>
#include <unistd.h>
#include <ctime>
#include <iomanip>
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/core/types_c.h>
#include <vector>
#include <arpa/inet.h>
#include <unistd.h>



using namespace std;
using namespace cv;

size_t get_file_size( const char * filename );
void file_to_buf( char *buf, size_t _len, std::string filename );
void take_photo(char *name);

char answer[] = "N";

char message[] = "Hello there!\n";
int count_send_img = 0;
int main()
{


 string filename = "img.jpg";

    int sock;
    struct sockaddr_in addr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425); // или любой другой порт...
    addr.sin_addr.s_addr = /*net_addr*/htonl(/*"192.168.1.71"*/INADDR_LOOPBACK);
    if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("connect");
        exit(2);
    }

 int bbytee;
    cout << "before open the cam" << endl;

 VideoCapture cap(0);

    if(!cap.isOpened()){
      cout<< "Could not open the camera" <<  endl;
    }
    cout << "cam opened" << endl;

    Mat frame, frameGray;

    frame = Mat::zeros(480, 640, CV_8UC3);

    if(! frame.isContinuous() ){
        frame = frame.clone();
    }

    int imgSize = frame.total()*frame.elemSize();



 while(1){ 



  cap >> frame;



        cvtColor(frame, frameGray, CV_BGR2GRAY);

  if( (bbytee = send(sock, frameGray.data, imgSize, 0)) < 0 ){
            cerr<< "bytes = " << bbytee << endl;
            break;
  }


 }
    close(sock);

    return 0;
}

2条回答
Juvenile、少年°
2楼-- · 2020-03-31 08:48

Uh,I am also a newbie about opencv. But i can do this in opencv and Gstreamer. There are lots of solutions i'm not sure the FFmpeg can do it, you can try.

Here is the Gstremer documetion.Hope it will help you.And you can also search some project in github. This project help me but it is not my project, hope it will help you.

查看更多
别忘想泡老子
3楼-- · 2020-03-31 08:49

Env: OpenCV 3.3, G++5.4, Ubuntu 16.04


If you want to save the video, you should set CV_FOURCE to MJPG

VideoWriter outputVideo;
Size S = Size((int) 640,(int) 480);
outputVideo.open("receive.avi", CV_FOURCC('M','J','P','G'), 30, S, true);

This is my result:

enter image description here

Code as follow:

客户端(Client.cpp):

//!2017.12.19 19:19:01 CST
//!2017.12.19 22:19:38 CST
//!2017.12.19 22:39:37 CST
// 客户端
// 使用 OpenCV 读取视频(并处理),然后使用 SOCKET 上传到服务器。

#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    int sock;
    struct sockaddr_in addr;

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0){
        perror("socket");
        exit(1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425);
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0){
        perror("connect");
        exit(2);
    }

    int bbytee;
    cout << "before open the cam" << endl;

    VideoCapture cap(0);

    if(!cap.isOpened()) {
        cout<< "Could not open the camera" <<  endl;
        close(sock);
        return -1;
    }

    Mat frame;
    frame = Mat::zeros(480, 640, CV_8UC3);
    int imgSize = frame.cols*frame.rows*3;

    int cnt=0;
    //Mat frame;
    while(1) {
        cap >> frame;
        if(frame.empty()) {
            cerr<<"[client] VideoCapture(0) error!"<<endl;
        }

        cout<< ++cnt << ":"<< frame.isContinuous()<<"," <<frame.size()<<endl;;

        if( (bbytee = send(sock, frame.data, imgSize, 0)) < 0 ) {
            cerr<< "bytes = " << bbytee << endl;
            break;
        }

        cv::imshow("client", frame);
        if(cv::waitKey(100) == 'q') {
            break;
        }
    }
    close(sock);
    return 0;
}

服务端(Server.cpp):

//!2017.12.19 19:19:01 CST
//!2017.12.19 22:19:38 CST
//!2017.12.19 22:39:37 CST
// 服务器
// 监听客户端请求,读取视频流(并处理),保存。
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    int sock, listener;
    struct sockaddr_in addr;

    if( (listener = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("[server] socket() failed");
        exit(1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("[server] binding faild!");
        exit(2);
    }

    listen(listener, 1);


    int num_of_recv_bytes;
    VideoWriter outputVideo;
    Size S = Size((int) 640,(int) 480);
    outputVideo.open("receive.avi", CV_FOURCC('M','J','P','G'), 30, S, true);

    int imgSize = 480*640*3;
    Mat frame = Mat::zeros(480, 640, CV_8UC3);
    uchar *iptr = frame.data;
    int key;

    int cnt=0;
    while(1){
        cout << ++cnt<<endl;
        sock = accept(listener, NULL, NULL);
        if(sock < 0){
            perror("[server] accept() faild!");
            exit(3);
        }

        while(key != 'q') {
            if( num_of_recv_bytes = recv(sock, iptr, imgSize, MSG_WAITALL) == -1 ) {
                cerr << "recv failed, received bytes = " << num_of_recv_bytes << endl;
            }

            outputVideo<< frame;
            imshow("server", frame);
            if (key = waitKey(100) >= 0) break;
        }
        outputVideo.release();
        close(sock);
        break;
    }
    return 0;
}
查看更多
登录 后发表回答