关于STL的vector与OpenCV的Mat初始化问题记录

问题情形:

        需要记录不同的两个Opencv的Mat矩阵,由于数量是动态确定的(且很可能>4个),所以想通过构建cv::Mat的容器来保存结果。同时,每个Mat必须初始化为0矩阵且分配内存。

错误使用:

std::vector<cv::Mat> featureMats(numOfFeatures, cv::Mat::zeros(10, 10, CV_32FC1));

//这里是想给featureMats分配numOfFeatures个10×10的0矩阵

for (int i = 0; i < img_h; ++i)
        {
            for (int j = 0; j < img_w; ++j)
            {

                ......//一些计算

                for (int typeID = 0; typeID < numOfFeatures; ++typeID)
                {

                        ....//一些计算

                        float tmpVal= getFeatureNum(typeID );

                        featureMats[typeID].at<float>(i, j) = tmpVal;

                }

            }

        }

出现的问题:

        上述代码执行完,无论怎么处理,得到的numOfFeatures个矩阵的结果都是一摸一样(实际上应该是不一样的!!)debug过程中,查看了每一次最内部循环中 tmpVal的计算值是不同的,从这里开始发现问题不对劲。

debug过程:

        首先断点打在float tmpVal= getFeatureNum(typeID );这一句,然后查看每次计算的tmpVal的值,发现内部循环中每次计算的tmpVal是没问题的,所以问题要么出在赋值,要么出在多线程。

        接下来,把多线程关掉,再用上述方法debug,排除了多线程的问题。最后,在所有循环结束后查看featureMats中每一个Mat的值,发现这里就已经全部一模一样了,那就是赋值的问题了。OK,把每次typeID对应的循环中,赋值完的所有Mat的值打印一下,发现第二次给第二个Mat赋值的时候,前一个Mat中的值也被改变了!!!所以初步估计是std::vector<cv::Mat> featureMats(numOfFeatures, cv::Mat::zeros(10, 10, CV_32FC1));这里初始化的时候,内部其实是类似于OpenCV的浅拷贝的形式,所有Mat共用了一块内存!所有修改第二个Mat时第一个也会变。

        为进一步验证,提前创建好了不同的几个Mat并初始化:

        cv::Mat featureMat0 = cv::Mat::zeros(10, 10, CV_32FC1));

        cv::Mat featureMat1 = cv::Mat::zeros(10, 10, CV_32FC1));

        cv::Mat featureMat2 = cv::Mat::zeros(10, 10, CV_32FC1));

        最内部for循环改成:

        featureMat0 .at<float>(i, j) = getFeatureNum(0);

        featureMat1 .at<float>(i, j) = getFeatureNum(1);

        featureMat2 .at<float>(i, j) = getFeatureNum(2);

        最后处理完输出发现featureMat0、featureMat1、featureMat2之间是不同的!确定了问题所在,就是STL的vector初始化时把第一个元素“拷贝”给后续的元素,这里的“拷贝”对于OpenCV的Mat而言,是“浅拷贝”!

解决方案:

        只要把featureMats中每个Mat都分配内存实现”深拷贝“即可,方法就很多了!下面是一种方案:

        std::vector<cv::Mat> featureMats(numOfFeatures);
        for (int i = 0; i < numOfFeatures; ++i)
        {
            cv::Mat tmp = cv::Mat::zeros(10, 10, CV_32FC1);
            tmp.copyTo(featureMats[i]);
        }

遇上OpenCV的Mat,一定要注意”浅拷贝“和”深拷贝“的问题,虽然早就”领教“过这个问题了,但是这次又坑在这里了,MD...记录一下,以后再翻着看看...

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值