0

几天来,我一直在努力尝试让循环缓冲区工作,但由于某种原因它只是不打球。我正在用 C 而不是 C++ 编写程序。

我正在尝试在一个线程中缓冲来自相机的图像,以便可以在另一个线程中读取和处理它(我知道如何使用 pthread_mutex_* 进行资源锁定)。到目前为止,我已将缓冲区图像管理到我的缓冲区中,但在检索它们时遇到了问题。这是我的循环缓冲区实现:

#define BUFFER_SIZE 100

typedef struct
{
     IplImage** queue[BUFFER_SIZE];
     IplImage** in;
     IplImage** out;
     int num_frames;
     int in_ctr;
     int out_ctr;
     int update_flag;
 } frame_buffer;

static frame_buffer frbuff;

void buff_init()
{
    frbuff.in = &frbuff.queue[0];
    frbuff.out = &frbuff.queue[0];
    frbuff.num_frames = 0;
    frbuff.in_ctr = 0;
    frbuff.out_ctr = 0;
    frbuff.update_flag = 0;
}

int buff_size()
{
    return frbuff.num_frames;
}

int buff_flag_check()
{
    return frbuff.update_flag;
}

void buff_flag_set()
{
    frbuff.update_flag = 1;
}

void buff_flag_clr()
{
    frbuff.update_flag = 0;
}

IplImage** buff_get()
{
    IplImage** nextfr;
    if(frbuff.num_frames == 0)
    {
        return NULL;
    }
    nextfr = frbuff.out++;
    if(++frbuff.out_ctr == BUFFER_SIZE)
    {
        frbuff.out = &frbuff.queue[0];
        frbuff.out_ctr = 0;
    }
    --frbuff.num_frames;
    buff_flag_clr();
    return nextfr;
}

int buff_put(IplImage* nextfr)
{
    if(++frbuff.num_frames > BUFFER_SIZE)
    {
       return 0;
    }
    frbuff.in++; 
    frbuff.in = nextfr;
    if(++frbuff.in_ctr == BUFFER_SIZE)
    {
        frbuff.in = &frbuff.queue[0];
        frbuff.in_ctr = 0;
    }
    buff_flag_set();
    return 1;
}

我可以 buff_put() 就好了,这似乎工作,因为我看到计数器增加。当我 buff_get() 时,我也得到了一些不为空的东西。当我尝试用它做任何事情时,问题就来了:

IplImage **some_image;
some_image = buff_get();
cvShowImage("some_window_somewhere",some_image);

好吧,显然它对此不满意......

OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in cvGetMat, file /home/fagg/src/OpenCV-2.3.1/modules/core/src/array.cpp, line 2482
 terminate called after throwing an instance of 'cv::Exception'
 what():  /home/fagg/src/OpenCV-2.3.1/modules/core/src/array.cpp:2482: error: (-206)  Unrecognized or unsupported array type in function cvGetMat

我也试过这个(导致分段错误):

cvShowImage("some_window_somewhere",*some_image);

我非常卡住,已经尝试了我能想到的一切。毫无疑问,它最终会变得很明显(我讨厌指针)。任何帮助将不胜感激。

4

1 回答 1

0

我将在这里做一个假设,并假设您正在尝试构建 ImpImage* 的队列。如果是这样的话,这一行:

IplImage** queue[BUFFER_SIZE];

应该读:

IplImage* queue[BUFFER_SIZE];

这些行:

IplImage** buff_get()
{
    IplImage** nextfr;
    if(frbuff.num_frames == 0)
    {
        return NULL;
    }
    nextfr = frbuff.out++;

应该读:

IplImage* buff_get()
{
    IplImage* nextfr;
    if(frbuff.num_frames == 0)
    {
        return NULL;
    }
    nextfr = *frbuff.out++;

这些行:

IplImage **some_image;
some_image = buff_get();
cvShowImage("some_window_somewhere",some_image);

应该读:

IplImage *some_image;
some_image = buff_get();
cvShowImage("some_window_somewhere",some_image);

接下来我们有一个简单的错误。这一行:

frbuff.in = nextfr;

应该读:

*frbuff.in = nextfr;

我很惊讶现代 C 编译器没有完全拒绝代码。至少它必须发出警告。如果您使用 gcc,我建议您将 -Wall -Wextra 作为您编写的所有新代码的最低要求。将您的代码转换成编译器在没有警告的情况下接受的形式可能会很痛苦,但从长远来看,您会发现不这样做会更加痛苦。

其次,您说您正在使用pthreads。如果总是从同一个线程调用 buf_get(),那么您的大部分代码都会正常,对于 buf_put() 也是如此。如果从多个线程调用 buf_get(),那么至少您的队列将被破坏,buf_put() 也是如此。所有这一切的一个例外是 frbuff.update_flag,它由 buf_get() 和 buf_put() 更改。如果 buf_get() 和 buf_put() 从不同的线程调用,您可以确定 update_flag 最终会包含错误的内容。

于 2012-03-19T08:43:27.260 回答