liunx下使用管道传输cv::Mat图像数据 c++

4 篇文章 0 订阅
3 篇文章 0 订阅
本文介绍如何使用C++实现一个程序,通过管道机制,主进程将图片数据逐次发送给子进程,子进程接收并解码展示,用于演示进程间高效数据交换。特别关注图像编码和解码操作,以及如何在接收端计数显示接收到的数据次数。
摘要由CSDN通过智能技术生成

代码只供参考,在实际的使用场景中,进程之间可以传送不同的图片数据,比如一个进程负责读取相机传过来的数据,(网络相机可能会有很大的延迟,所以另开进程读取数据)另一个进程负责把图片输入到神经网络模型中去。

//
// Created by xia on 2022/1/5.
//

#include "unistd.h"
#include "cstdlib"
#include "cstdio"
#include "cstring"
#include "sys/wait.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#define BUF_SIZE 1024

void errorExit(const char* msg)
{
    perror(msg);
    exit(-1);
}

int main(int argc,char* argv[])
{
    int pfd[2];
    uchar buf[BUF_SIZE];
    ssize_t numRead;

    if(argc != 2 || strcmp(argv[1],"--help") == 0)
        errorExit("usage error");
    cv::Mat image = cv::imread(argv[1],1);
    if(image.empty())
        errorExit("image path is error!");
    std::vector<uchar> encoded_img;
    cv::imencode(".png",image,encoded_img);
    printf("encoded image size is: %ld\n",encoded_img.size());
    printf("original image size is %ld\n",image.step * image.rows);
    if(pipe(pfd) == -1)
    {
        perror("pipe");
        return -1;
    }
    std::vector<uchar> receive_img;
    receive_img.resize(encoded_img.size());
    int i=0;
    switch (fork()) {
        case -1:
            perror("fork");
            exit(-1);
        case 0:
            if(close(pfd[1]) == -1)
                errorExit("close fd");
            for(;;)
            {
                ssize_t current_read = 0;
                auto it = receive_img.begin();
                for(;;)
                {
                    numRead = read(pfd[0],&receive_img[current_read],
                                   std::min<size_t>(encoded_img.size()-current_read,BUF_SIZE));
                    if(numRead == -1)
                        errorExit("read error");
                    if(numRead == 0)
                        break;
                    current_read += numRead;
                    it = receive_img.begin() + current_read;
                    if(current_read == encoded_img.size())
                    {
                        printf("data %d received!\n",i);
                        cv::Mat image_receive = cv::imdecode(receive_img,1);
                        cv::putText(image_receive, std::to_string(i),cv::Point(50,50),
                                    cv::FONT_HERSHEY_SIMPLEX,2.0,cv::Scalar(255,0,0));
                        cv::imshow("image_received",image_receive);
                        cv::waitKey(30);
                        break;
                    }
                }
                i++;
                if(numRead == 0)
                    break;
            }
            if(close(pfd[0]) == -1)
                _exit(-1);
            _exit(EXIT_SUCCESS);
        default:
            break;
    }
    if(close(pfd[0]) == -1)
        errorExit("close pfd 0");
    for(int j=0;j<100;j++)
    {
        size_t hasSend = 0;
        ssize_t currentSend;
        for(;;)
        {
            currentSend = write(pfd[1],&encoded_img[hasSend],
                                std::min<size_t>(encoded_img.size()-hasSend,BUF_SIZE));
            if(currentSend == -1)
                errorExit("send error");
            if(currentSend == 0)
                break;
            hasSend += currentSend;
        }
        printf("send data %d\n",j);
    }
    close(pfd[1]);
    wait(nullptr);
    exit(EXIT_SUCCESS);
}

写的有点乱,命令行参数需要一个图片路径,然后主进程通过管道将这个图片输送给自进程100次,为了区别子进程是接受了100次数据,会在显示的图片上显示接受的次数,1,2,3,4到99这样的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值