简体   繁体   English

OpenCV矩阵到共享内存

[英]opencv matrix into shared memory

I want to share between two linux processes a CvMat object (a matrix in the OpenCV library), for that I'm using shared memory. 我想在两个Linux进程之间共享一个CvMat对象(OpenCV库中的矩阵),因为我正在使用共享内存。 One process (server) will capture a frame (matrix) from the webcam, convert it to gray scale, share it using shared memory and show the frame on the screen. 一个进程(服务器)将从网络摄像头捕获帧(矩阵),将其转换为灰度,使用共享内存进行共享,然后在屏幕上显示该帧。 The other process (client) will read the shared frame and perform some operations. 另一个进程(客户端)将读取共享帧并执行一些操作。 See the code below. 请参阅下面的代码。

The problem seems to be that the client doesn't read the information since 'rows' and 'cols' are zero (or the server is not writing in the shared memory). 问题似乎是客户端没有读取信息,因为“行”和“列”为零(或者服务器未在共享内存中写入数据)。 Anyway I'm not getting any error message and I don't know what I'm doing wrong. 无论如何,我没有收到任何错误消息,也不知道我在做什么错。 Any idea? 任何想法?

Thank you very much! 非常感谢你!


Here is the the server's code: 这是服务器的代码:

#include <iostream>
#include <cv.h>
#include <highgui.h>
using namespace std;

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

#include "2cam.h"

int sizeofmat(CvMat *mat) {
    return mat->rows * mat->cols * CV_ELEM_SIZE(mat->type);
}

int main() {
    int shmid;
    key_t key = 5678;

    CvMat *vdisp = cvCreateMat(240, 320, CV_8U);
    const size_t vdispsize = sizeofmat(vdisp);
    CvMat *s = cvCreateMat(240, 320, CV_8U);
    CvMat stub;
    CvSize imageSize = cvSize(320, 240);

    IplImage *color = cvCreateImage(imageSize, 8, 3);
    IplImage *gray = cvCreateImage(imageSize, 8, 1);

    /* Create the segment */
    if ((shmid = shmget(key, vdispsize, IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    /* Attach the segment to our data space */
    if ((vdisp = (CvMat *)shmat(shmid, NULL, 0)) == (CvMat *)-1) {
        perror("shmat");
        exit(1);
    }

    /* Put CvMat into the memory to be read for other processes */
    s = vdisp;

    /* Create camera */
    Camera c("/dev/video0", 320, 240, 30);

    while (1) {
        /* Get one frame */
        c.Update();
        c.toIplImage(color);

        /* Convert color frame to grayscale */
        cvCvtColor(color, gray, CV_BGR2GRAY);

        /* Get matrix from the gray frame and write the matrix in shared memory*/
        s = cvGetMat(gray, &stub, 0, 0);

        /* Show frame */
        cvNamedWindow("result", CV_WINDOW_AUTOSIZE);
        cvShowImage("result", s);

        /* Wait for escape key */
        if ((cvWaitKey(10) & 255) == 27)
            break;
    }

    /* free memory */
    cvDestroyWindow("result");
    cvReleaseImage(&color);
    cvReleaseImage(&gray);
    //cvReleaseMat(&vdisp);
    //cvReleaseMat(&s);

    return 0;
}  

And here the client's code: 这是客户的代码:

#include <iostream>
#include <cv.h>
#include <highgui.h>
using namespace std;

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

int sizeofmat(CvMat *mat) {
    return mat->rows * mat->cols * CV_ELEM_SIZE(mat->type);
}

int main() {
    int shmid;
    key_t key = 5678;

    CvMat *vdisp = cvCreateMat(240, 320, CV_8U);
    const size_t vdispsize = sizeofmat(vdisp);
    CvMat *s = cvCreateMat(240, 320, CV_8U);

    /* Locate the segment */
    if ((shmid = shmget(key, vdispsize, 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    /* Now we attach the segment to our data space */
    if ((vdisp = (CvMat *)shmat(shmid, NULL, 0)) == (CvMat *) -1) {
        perror("shmat");
        exit(1);
    }

    s = vdisp;

    cout << "rows: " << s->rows << endl;
    cout << "cols: " << s->cols << endl;

    return 0;
}

Thanks to larsmans, that he pointed me in the right direction. 多亏了larsmans,他为我指明了正确的方向。 Anyway, I answered myself just in case someone need the same solution. 无论如何,我回答自己,以防万一有人需要相同的解决方案。


Here it is the server'S code: 这是服务器的代码:

#include <iostream>
#include <cv.h>
#include <highgui.h>
using namespace std;

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

#include "2cam.h"

int sizeofmat(CvMat *mat) {
    return mat->rows * mat->step;
}

int main() {
    int shmid;
    key_t key = 5678;

    uchar *vdisp;
    CvMat *s = cvCreateMat(240, 320, CV_8U);
    CvMat *tmp = cvCreateMat(240, 320, CV_8U);
    const size_t vdispsize = sizeofmat(s);
    CvMat stub;
    CvSize imageSize = cvSize(320, 240);

    IplImage *color = cvCreateImage(imageSize, 8, 3);
    IplImage *gray = cvCreateImage(imageSize, 8, 1);

    /* Create the segment */
    if ((shmid = shmget(key, vdispsize, IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    /* Attach the segment to our data space */
    if ((vdisp = (uchar *) shmat(shmid, NULL, 0)) == (uchar *) -1) {
        perror("shmat");
        exit(1);
    }

    s->data.ptr = vdisp;

    /* Create camera */
    Camera c("/dev/video0", 320, 240, 30);

    while (1) {
        /* Get one frame */
        c.Update();
        c.toIplImage(color);

        /* Convert color frame to grayscale */
        cvCvtColor(color, gray, CV_BGR2GRAY);

        /* Get matrix from the gray frame and write the matrix in shared memory*/
        tmp = cvGetMat(gray, &stub, 0, 0);

        for (int row = 0; row < tmp->rows; row++) {
            const uchar* ptr = (const uchar*) (tmp->data.ptr + row * tmp->step);
            memcpy((uchar*)(s->data.ptr + row * s->step), ptr, tmp->step);
        }

        /* Show frame */
        cvNamedWindow("result", CV_WINDOW_AUTOSIZE);
        cvShowImage("result", s);

        /* Wait for escape key */
        if ((cvWaitKey(10) & 255) == 27)
            break;
    }

    /* free memory */
    cvDestroyWindow("result");
    cvReleaseImage(&color);
    cvReleaseImage(&gray);

    return 0;
}

Here the client'S code: 这是客户的代码:

#include <iostream>
#include <cv.h>
#include <highgui.h>
using namespace std;

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>

int sizeofmat(CvMat *mat) {
    return mat->rows * mat->step;
}

int main() {
    int shmid;
    key_t key = 5678;

    uchar *vdisp;
    CvMat *s = cvCreateMat(240, 320, CV_8U);
    const size_t vdispsize = sizeofmat(s);

    /* Locate the segment */
    if ((shmid = shmget(key, vdispsize, 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    /* Now we attach the segment to our data space */
    if ((vdisp = (uchar *)shmat(shmid, NULL, 0)) == (uchar *) -1) {
        perror("shmat");
        exit(1);
    }

    s->data.ptr = vdisp;

    cvNamedWindow("result", CV_WINDOW_AUTOSIZE);
    cvShowImage("result", s);

    cvWaitKey(10000);

    cvDestroyWindow("result");

    return 0;
}

It should be like this, if you are using Boost Interprocess. 如果您使用的是Boost Interprocess,则应该像这样。

if(argv[1] = SERVER){

  struct shm_remove{
    shm_remove() {shared_memory_object::remove("SharedMemoryForCvMat"); }
    ~shm_remove(){shared_memory_object::remove("SharedMemoryForCvMat"); }
  }remover;

  shared_memory_object shm (create_only,"SharedMemoryForCvMat",read_write);
  shm.truncate(widht*height*channel);
  mapped_region region(shm, read_write);

  cv::VideoCapture cap(0);
  cv::Mat frame;

  while(everything_is_ok_for_server){
    cap >> frame;
    memcpy(region.get_address(), frame.data, width*height*channel);   
  }
}

else if(argv[1] == CLIENT){

    shared_memory_object shm (open_only, "SharedMemoryForCvMat", read_only);
    mapped_region region(shm, read_only);

    while(everything_is_ok_for_client){

        cv::Mat frame(cv::Size(width, height),
                      CV_8UC3,
                      region.get_address(),
                      cv::Mat::AUTO_STEP);
        cv::imshow("unimportant_string",frame);
        cv::waitKey(2);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM