将CV :: MAT实例存储在C 中的堆上

Store cv::Mat instance on Heap in C++

本文关键字:存储 CV MAT 实例      更新时间:2023-10-16

这不是仅相关的openCV,而是一般的C 问题。

我想在方法中加载图像并使用指针将其存储在堆上。

这是我当前正在使用的方法的代码:

int load_offline_image(std::string src, unsigned char* buffer, int* width, int* height, int* len) {
    if (offline_image) {
        delete offline_image;
    }
    offline_image = new cv::Mat(cv::imread(src, cv::IMREAD_GRAYSCALE));
    if (offline_image->data == 0){
        return ERROR;
    }
    int numRow = offline_image->rows;
    int numCol = offline_image->cols;
    *len = numCol*numRow*offline_image->elemSize1();
    *width = offline_image->size().width;
    *height = offline_image->size().height;
    buffer = offline_image->data;
    return OK;
}

方法内部一切正常。但是,当我尝试从外部访问buffer变量时,它是Null。我敢肯定,问题与指针offline_image指向cv::Mat实例的事实有关,该实例仅存在于堆栈上,并且在执行load_offline_image完成后,该实例的地址丢失了。

btw: offline_image是一个全局变量。

在C 中实现此操作的正确方法是什么,因此我为cv::Mat实例分配堆空间?

您可能想要的是这样的东西:

int load_offline_image(std::string src, unsigned char** buffer, int* width, int* height, int* len) {
    ...
    *buffer = offline_image->data;
    ....
}

这个原因是 - 您想更改buffer指向的地址。使用unsigned char* buffer更改地址,但更改仅限于调用方法。您需要一个unsigned char**才能更改以超越方法。

另外,我建议您考虑步幅宽度 - 这可能与图像宽度不同。您可以查询offline_image.isContinuous()来弄清楚这一点。

另一个注意事项,这不是使用cv::Mat的合适方法。同样,尚不清楚谁是责任是要清除buffer指向的内存。这是一种更清洁的方法:

int main() {
    // Calling application
    buffer = new unsigned char[width*height*dims];
    ...
    load_offline_image(..., buffer, width, height, ...);
    ...
    delete[] buffer;
}
int load_offline_image(...) {
    Mat offline_image;
    // use imread
    // Copy the buffer over
    memcpy(buffer, offline_image->data, ...);
    // Since we're using the Mat structure, the Mat will be deallocated automatically
}

这将两个函数分开,让他们分别管理记忆。