1

我想在来自 postgresql 数据库的 c++ opencv 中加载图像。图像,jpg 扩展名,作为二进制数据(bytea 类型)存储在基础中,我可以通过 libpqxx 访问它。

问题是我不知道如何将数据转换为 cv::Mat 实例。对于常规图像,我可以使用 imread('myImage.jpg', ...),但在这种情况下,我什至无法在 Mat 的数据属性中加载数据库图像,因为它是 jpeg 而不是 bmp。

任何想法 ?是否有一些我可以使用的 opencv 方法可以直接理解二进制数据并将其转换为适当的结构?imdecode() 函数似乎用于位图数据。

编辑:Berak,使用向量 imdecode 函数返回空矩阵会发生什么“如果缓冲区太短或包含无效数据,则返回空矩阵/图像。” 这是代码:

pqxx::result r=bdd::requete("SELECT image FROM lrad.img WHERE id=3",1);//returns the bytea image in r[0]["image"]
const char* buffer=r[0]["image"].c_str();    
vector<uchar>::size_type size = strlen((const char*)buffer);
vector<uchar> jpgbytes(buffer, buffer+size);
Mat img = imdecode(jpgbytes, CV_LOAD_IMAGE_COLOR); 
//jpgbytes.size()=1416562 img.size()=[0 x 0]

我错过了什么?

4

2 回答 2

4

仍然,使用imdecode。它可以处理 png、jpg、bmp、ppm、webp、jp2、exr,但不能处理 gif。

vector<uchar> jpgbytes; // from your db
Mat img = imdecode(jpgbytes);

(你应该对 bmp 或任何其他支持的格式做同样的事情,不要弄乱 Mat 的原始数据指针!)

于 2014-10-07T07:42:57.690 回答
1

好的,我有将 bytea 数据转换为 cv::Mat 的过程,这是代码。

inline int dec(uchar x){ //convert uchar to int
    if (x>='0'&&x<='9') return (x-'0');
    else if (x>='a'&&x<='f') return (x-'a'+10);
    else if (x>='A'&&x<='F') return (x-'A'+10);
    return 0;
}
cv::Mat bytea2Mat(const pqxx::result::field& f){
    const char* buffer=f.c_str();  
    vector<uchar>::size_type size = strlen((const char*)buffer);
    vector<uchar> jpgbytes(size/2-1); 

    for (size_t i=0; i!=size/2-1;i++) { 
        jpgbytes[i]=(dec(buffer[2*(i+1)])<<4)+dec(buffer[2*(i+1)+1]);
    }
    cout <<size/2<<";"<<jpgbytes.size()<<endl;
    return imdecode(jpgbytes, CV_LOAD_IMAGE_COLOR);
}

对于原始输入字符串“a b0”的六进制形式,bytea 输出被加密为看起来像“\x41204230”的 char*。(根据数据输入,\x 可能不存在)要获取原始数据,您必须从两个 char 计算原始输入,('4','1'= 0x41=65)。向量是 char* 大小的一半。

于 2014-10-08T14:28:06.593 回答