2010-10-11 82 views
0

我想在兩個linux進程之間共享一個CvMat對象(OpenCV庫中的一個矩陣),爲此我使用共享內存。一個進程(服務器)將從網絡攝像頭捕獲一幀(矩陣),將其轉換爲灰度,使用共享內存共享並在屏幕上顯示幀。另一個進程(客戶端)將讀取共享幀並執行一些操作。請參閱下面的代碼。opencv矩陣到共享內存

問題似乎是由於'rows'和'cols'爲零(或者服務器沒有寫入共享內存),客戶端沒有讀取信息。無論如何,我沒有收到任何錯誤信息,我不知道我做錯了什麼。任何想法?

非常感謝!


這裏是服務器的代碼:

#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; 
} 

在這裏,客戶端的代碼:

#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; 
} 
+0

難道你不能使用線程嗎? – karlphillip 2010-10-11 13:15:20

+0

yeap!沒問題,但它是一個個人項目,所以我決定使用共享內存來了解它是如何工作的。感謝您的建議。 – 2010-10-11 13:18:26

+0

如果你想要它的功能和速度,只需使用gstreamer的'shmsrc'和'shmsink'(OpenCV示例:https://github.com/tik0/mat2gstreamer) – Tik0 2016-09-03 12:38:12

回答

1

由於larsmans,他向我指出了正確的方向。無論如何,我回答自己以防萬一有人需要相同的解決方案。


這是服務器的代碼:

#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; 
} 

在這裏,客戶端的代碼:

#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; 
} 
+0

好的,但是在發送3通道圖像(不是灰色圖像),你怎麼做到這一點? – user1098761 2017-01-31 05:49:07

0

它應該是這樣的,如果你正在使用升壓進程間。

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); 
    } 
}