【问题标题】:C++ OpenCV create Mat from SIGNED char array (not unsigned)C++ OpenCV 从 SIGNED char 数组(非无符号)创建 Mat
【发布时间】:2014-11-14 00:21:31
【问题描述】:

我正在尝试使用存储在 SQLite 数据库中的数据重新创建 Mat 对象。我打开一个图像,获取它的描述符(使用 Surf),然后将数据存储在 SQLite DB 中。之后,我尝试从数据库中读取该数据并使用该数据重新创建相同的 Mat 对象。

这是我的桌子:

create table images(
    id INTEGER,
    descriptors BLOB
);

这是获取描述符并将它们存储在数据库部分:

Mat image;
vector<KeyPoint> keypoints;
image = imread(nameImage,0);  
SurfFeatureDetector surf(500);
surf.detect(image, keypoints);
SurfDescriptorExtractor surfDesc;
Mat descriptors, descriptors;
surfDesc.compute(image, keypoints, descriptors);
string command = "insert into images values(" << id << ",'" << descriptors << "');";
sqlite3_exec(db, command, callback, (void*)data, &errMsg);

这就是我从数据库中获取数据的方式:

string command = "select id, descriptors from images;";
sqlite3_exec(db, command, callback, (void*)data, &errMsg);

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
    int id = atoi(argv[0]);
    /*argv[1] contains the matrix data and it is untouched, the fun begins */
    /*when I try to put that data into a Mat object: */
    Mat currentDescriptors;
    currentDescriptors = Mat(h,w,CV_16S,argv[1]);
    /*after this, the Mat data gets borked /*
    return 0;
}

问题是,这些数据(基本上是一个数组,char*,它是 sqlite 方法返回的数据)由带符号的值组成(我已经使用 DB 客户端检查了 DB 中的值和值从读取数据库获得的 char 数组,它们是正确的)。但是,在创建 Mat 对象时,这些值似乎转换为无符号数字,因此 Mat 值是错误的。

以下是我打算做什么以及我在每一步检查存储值的摘要:

  1. 获取图像描述符 - 确定
  2. 将它们存储在数据库中 - 好的
  3. 从数据库中读取它们 - 好的
  4. 用它们创建一个 Mat 并查看 Mat 的值 - 错误

我正在使用的 Mat 构造函数如下:

TempMat = cv::Mat(height, width, CV_32F, buffer);

我正在使用 CV_32F,因为这是我在获取描述符后检查它时得到的类型(我得到类型 5,我发现它是 CV_32F)。

我尝试更改垫子类型并将值手动插入到垫子对象中,但似乎没有任何效果(或者我不知道如何使其工作)。有没有办法用签名数据构造一个 Mat 对象?

【问题讨论】:

  • 你怎么知道它正在转换为无符号数字?您需要显示创建buffer 的代码和验证负载的代码。
  • 我们将打印结果并进行比较。我真的不知道构造函数中发生了什么,但它显然适用于无符号字符,并且我在打印转换后看到的只是正数(之前有正数和负数),所以我认为这是正在发生的事情。我将使用一些代码 sn-ps 编辑帖子。
  • currentDescriptors = Mat(h,w,CV_16S,argv[1]); // 肯定是错误的格式。 CV_8U (ORB) 或 CV_32F (SURF)。你在存储 BLOB 对象吗?显示您的 createtable 语句。
  • CV_8U 和 CV_32F 都试过了,还是不行。添加了 createtable 语句

标签: c++ opencv char signed mat


【解决方案1】:

嗯,问题解决了。看起来这是解决两个不同问题的问题:

首先,由于某种原因,直接使用 CV_32F 类型(我用于 SURF 识别的类型)创建矩阵会以错误的顺序创建它。我不知道为什么,我已经搜索了几个来源,我开始相信这是一个错误。我什至尝试了简单的示例(创建一个 2x2 矩阵并手动添加值),但它不起作用(值最终没有出现在我告诉他们去的地方)。这是通过使用 CV_64F 类型创建矩阵,然后将其转换为 CV_32F 来解决的:

Mat m = Mat(h,w,CV_64F);
fillValues(...);
m.convertTo(m,CV_32F);

另一个问题是我提供给矩阵构造函数的数据格式错误。在解决了第一个问题后,数字似乎没有被正确读取(它们最终到达了必须的地方,但它们被改变了),所以我尝试了不同的方法。将 char 数组转换为双精度向量并手动插入值是我想出的,它可以工作:

vector<double> fvalues;
int position = 0;
for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
        if(position!=fvalues.size()){
            currentDescriptors.at<double>(i,j)=fvalues.at(position);
            position++;
        } else {
            break;
        }
    }
}

在包含这两个修复后,问题得到解决 - 重新创建的矩阵与最初创建的矩阵相同(并存储在 SQLite 数据库中)。

【讨论】:

    猜你喜欢
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-04
    • 1970-01-01
    • 2017-08-28
    • 2019-04-28
    相关资源
    最近更新 更多