如何在客户端-服务器模型(OpenCV C++)中通过套接字传输 cv::VideoCapture 帧?

2024-04-23

我通过套接字翻译视频,我在另一端看到视频流,但无法接收视频。我的视频文件是空的。我认为问题可能是接收端转换视频格式错误。我应该如何在服务器端对视频进行编码以及如何在客户端对视频进行解码?

我使用 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;
}

环境:OpenCV 3.3、G++5.4、Ubuntu 16.04


如果你想保存视频,你应该设置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);

这是我的结果:

代码如下:

客户端(客户端.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;
}

服务端(服务器.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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在客户端-服务器模型(OpenCV C++)中通过套接字传输 cv::VideoCapture 帧? 的相关文章

  • ServiceStack 验证并不总是触发

    因此 我尝试使用 RavenDB 和 ServiceStack 构建端到端集成测试套件 但遇到了一个非常奇怪的问题 即验证无法对某些请求运行 这真的很奇怪 我不确定我做错了什么 我正在使用 NCrunch 有时测试通过 有时失败 希望这是一
  • fgetc,检查 EOF

    在书里Linux系统编程我读过一些这样的内容 fgetc返回读取为的字符unsigned char投射到int or EOF在文件末尾或错误 使用时的一个常见错误fgetc is char c if c fgetc EOF 该代码的正确版本
  • Xamarin 中 QR 扫描后的处理对话框

    我在Xamarin应用程序中使用QR码扫描仪 当它扫描QR码时 它会执行一些操作 大约需要一分钟 而在执行操作时 我想在屏幕上显示一个加载对话框 但是 它没有显示在屏幕上 并且在应用程序的其他地方 它运行得很好 Code var expec
  • 如何吞咽……有具体原因的异常

    在这个方法中 public static void Detach try using var master new DataContext Data Source LocalDB MSSQLLocalDB Initial Catalog m
  • 使用 perf 查找线程瓶颈并优化挂机时间

    对 cpu 周期进行采样perf record如果核心利用率大致恒定 则对于寻找优化候选非常有用 但对于具有并行性不同的多个阶段的代码 计算 cpu 周期将重点强调并行阶段 而低估影响挂机时间的顺序或有限并行阶段 简而言之 天真的 perf
  • 同步和异步 API

    我正在开发一个库 它提供一些耗时的服务 我需要每个 API 有两个版本 一个用于同步函数调用 另一个用于异步 图书馆用户应决定使用哪个版本 服务结果可能对于系统继续运行 同步调用 至关重要 可能需要在不同的工作线程中完成相同的操作 因为结果
  • 再次对存储库和持久性一无所知

    这就是我要做的 我有一个通用的存储库类Repository
  • std::mutex 和 std::shared_mutex 之间的区别

    我遇到了一个std shared mutex in C 17 到底是什么std shared mutex以及它有何不同std mutex 如中所述文档 http en cppreference com w cpp thread shared
  • 如何保存具有多个缩进设置的XmlDocument?

    我需要保存一个XmlDocument以适当的缩进归档 Formatting Indented 但有些节点及其子节点必须排在一行 Formatting None 从那时起如何实现这一目标XmlTextWriter接受整个文档的设置 在 Ahm
  • 使用箭头键滚动可滚动控件

    我正在使用一个ScrollableControl在我的 C 项目中 我想知道如何将箭头键映射到垂直 水平滚动 编辑 我的图片框获得焦点 并且我设法映射滚动键 这里的问题是 当我按下箭头键时 它会滚动一次 然后失去焦点 将其交给滚动查看器旁边
  • 重复取消引用多个指针,效率较低?

    而不是写 string name first gt next gt next gt next gt name int age first gt next gt next gt next gt age 将其写为 node billy bloc
  • GoogleTest:如何跳过测试?

    使用 Google Test 1 6 Windows 7 Visual Studio C 如何关闭给定的测试 又名如何阻止测试运行 除了注释掉整个测试之外 我还能做些什么吗 The docs https github com google
  • 在库中使用 .Net Standard 1.4 并在应用程序中使用 .Net Framework 4.6.1 时,无法加载文件 System.IO.FileSystem,版本=4.0.1.0

    我有一个包含一个库和两个应用程序的解决方案 这些应用程序代表同一个程序 其中一个针对通过 UAP10 的 Windows App Store 构建 另一个针对使用 Net Framework 4 6 1 的 Microsoft Window
  • 即使使用前向声明也会出现未定义的类型错误

    我正在阅读循环引用和前向声明 我确实知道在头文件中实现并不是一个好的设计实践 然而我正在尝试并且无法理解这种行为 使用以下代码 包含前向声明 我期望它能够构建 但是我收到此错误 Error 1 error C2027 use of unde
  • List.Except 不起作用

    我尝试减去 2 个列表 如下代码所示 assignUsers已获得 3 条记录assignedUsers有 2 行 后Except方法我仍然得到 3 行 尽管我应该得到 1 条记录 因为 2 行assignedUsers类似于assignU
  • HTTP 错误 500.35 - ANCM 同一进程中的多个进程内应用程序 ASP.NET Core 3

    从今天早上开始 没有对项目代码进行任何更改 一个非常简单的 Web API 一个控制器和 3 个方法 使用 Swagger 它不再启动 我收到错误 HTTP 错误 500 35 ANCM 同一进程中有多个进程内应用程序 事件查看器报告最无用
  • 以编程方式将 Word 文件另存为图片

    我想将Word文档的第一页另存为图片 使用 C 有什么方法可以做到这一点 您可以将 Word 文档打印到 XPS 文档 在 WPF Net 3 5 应用程序中打开它 并使用 WPF 框架的文档和图像功能将第一个内部固定页面对象转换为位图 如
  • 在 C# 中同步闪烁标签

    我创建了一个BlinkingLabel类 源自Forms Label 其中有一个Forms Timer这允许我启用和禁用闪烁效果 我创建了 4 个标签BlinkingLabel类型 我的问题是 如果所有 4 个标签在不同时间闪烁 则闪烁效果
  • 在ubuntu 18.04上安装python 2.7

    有没有办法在 Ubuntu 18 04 上安装 Python 2 7 我尝试了这个命令 但它不起作用 sudo apt install python minimal 有没有办法手动安装 我尝试使用 python 2 7 作为不支持 pyth
  • SQL 注入在 winform 中有效吗?

    我正在用 C 制作一个 Windows 软件 我读过关于sql injection但我没有发现它适用于我的应用程序 SQL 注入在 winform 中有效吗 如果是的话如何预防 EDIT 我正在使用文本框来读取用户名和密码 通过使用 tex

随机推荐