C++ opencv小试3

           由于本人从事的是图像算法开发,视频语义分析方面的工作,向广大图形处理爱好者推广OpenCV是我们非常高兴的一件事情,希望能抛砖引玉吧。首先,按照教程配置好OpenCV,linux或者window都可。在具体介绍之前,本人希望大家在学习时,尽量写标准的代码,这样不易出未知错,因为未知错误是无穷尽的。不用标准的写法,看起来好像是对的,可能某一天运行就出错了,有经历的人应该能理解我这句话。程序也是先跑出正确的结果(用比较慢,但符合人们思维的东西,代码,访问变量形式等等)->进行程序的后期优化(优化运行的速度),循序渐进。我的OpenCV会讲的很详细,大家并不需要教材!

         OpenCV用#include <opencv2/opencv.hpp>,这里面已经包含了基本要用的全部头文件,包含这一个就可以了。对于库的话,用到哪个包含哪个,在前期的开发阶段,全部包含也可。Opencv可以显示的无符号字符与浮点图(要求在0-1)之间。最后在保存的时候会全部转化为无符号字符(后在细谈);

        打开失败这个判断必须得有。彩色图是BGR的,我们先用灰度的图来作一些测试,这里定义了Mat对象后 用了函数进行了初始化;

怎么去访问呢?遍历的访问用Mat_<uchar> _img =img 这样来的话 改变_img也既改变了img ,有趣的是,若这里不是uchar 则对于灰度图它并没有改变原来的,只是可以访问而已。所以我们还是得先来看看Mat这个东西。

       Mat 的初始化必须用CV_16UC1这种opencv的标准类型,Mat img(2,2,CV_16UC1, Scalar(0,1,2))--------Scalar没关系 如果一维的话自取第一个 后面的可以不写,默认为零,第一个也不写的话 全部为0,还是希望写一下;但是Mat_却只能用C++的类型 所以有以下的对照表

     CV_8UC1  --------- unsigned char -------uchar

     CV_8SC1 -------char 、、、几乎不用

     CV_16UC1------------ unsigned short int

     CV_16SC1------------short  int

     CV_32SC1------------int

     CV_32FC1----------float

     CV_64FC1 -------double

只有这七中  没有其他的。只能类型对应了 Mat_  对象 就代表了Mat对象,更改会生效,否则不生效。当时 Mat_对于Mat值的读取是完全生效的,Mat_=Mat;赋值会成功。这可以认为它们指向了不同的地方,完成了数据的拷贝; 类型相同,则指向了相同的一块地方,Mat_与Mat之间不能引用,比较神奇,但就是这样的。定以后再用create方法初始化也可,但这样会以固定的值来初始化。img.create(2,2,CV_16UC1);各种初始化后才能用(i,j)坐标访问方法。

对于多维度的情形。

      读取时候就要用Vec技术了,它内部已经定义好了。

       Vec2b ----------------2维的 unsigned char

       Vec2s-----------------short int

       Vec2w----------------unsigned short int

       Vec2i---------------int

       Vec2f--------------float

       Vec2d--------------double

     常见的6种对应关系。

Mat_如此强大是不是Mat没用了呢?显然不是的,很多函数只是支持Mat,用Mat_会出现很多的错误,但Mat_与Mat可以相互赋值(用对方来构造自己),使它们指向同一块地方。Mat与Mat_ ,Mat与Mat ,Mat_与Mat_  它们之间的转化还是需要说明的。

Mat与Mat:

        Mat img;
    img.create(2,2,CV_16SC1);
    Mat f;
    f.create(3,3,CV_8SC3);
    img=f;
    cout<<img<<endl<<f<<endl;它们之间的转化 相等  无视类型设定的大小,可以任意等于,使得指针指向同一块地方。若利用Mat_指向它们的地方,改变值,那么指向那里得到的值都将改变。

Mat与Mat_之间的转化;

(1)有Mat-》Mat_,这个前面已经有说明,Mat初始化后有了类型,Mat_要规定好类型,然后去指向Mat说指向的地方,如果类型相同 (这里指type,是CV_8UC3这种形式的,_mat也是的type输出 也必须是这种类型,这在if判断上很有用,输出则没有太多的意义。)若我们要将一个越界MAT转化为不越界的Mat(类型转化了) 可以用_mat,因为mat=_mat后,他的类型是由_mat决定的,这种转化最好还有_mat=_mat的过程。首先用一个类型不相同的_mat指向mat空间(防止改变原来 比原来的大一点比较好),然后对于_mat的每个元素用,saturate_cast<uchar>(feng(i,j)[k]);防止越界,阀值阶段。最好在定义一个_img为对应类型,转化过去,最后在定义一个mat直接等于,但这样存在了3个空间,我们可以用大括号将过程中的空间成为块,出块自动删除。C++中的块非常好用,内层替代外层,外层访问不到内层。这样就可以产生符合类型条件的mat。有些时候,mat的类型变化是很有用的。#include <string>
#include <opencv2\opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
    Mat f;
    Mat_<Vec3b> _img;
    f.create(3,3,CV_16UC3);
    {
        Mat_<Vec3i> feng=f;
        cout<<fe<<endl;
        int i,j,k;
        for (i=0;i<fe.rows;i++)
            for(j=0;j<fe.cols;j++)
                for (k=0;k<3;k++)
                {
                    fe(i,j)[k]=saturate_cast<uchar>(fe(i,j)[k]);
                }
        _img=fe;
    }
    int i(10);
    cout<<_img<<endl;
    if (_img.type()==CV_8UC3)
    {
        cout<<"xxxx"<<endl;
    }
}

Mat_与Mat_的转化:

由mat_的声明类型所决定,mat_必须有声明类型。有mat_或者mat去初始化自己;

有些时候还会涉及到mat的通道转化,3通道转化为1通道。这种转化不能够随便去等于,合理的方法是用逐值复制的方法。声明一个一维的矩阵,然后逐值复制这样子是合理的 ,opencv的内部应该也是这样实现的。

     这些天有点忙,写的比较乱!







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV小项目 这是一个个人在使用OpenCV过程中写的一些小项目,以及一些非常有用的OpenCV代码,有些代码是对某论文中的部分实现。 注意:代码是在Xcode里写的,如果要在win下测试,遇到问题自己修改。 opencv-rootsift-py 用python和OpenCV写的一个rootsift实现,其中RootSIFT部分的代码参照Implementing RootSIFT in Python and OpenCV这篇文章所写,通过这个你可以了解Three things everyone should know to improve object retrieval这篇文章中RootSIFT是怎么实现的。 sift(asift)-match-with-ransac-cpp 用C++OpenCV写的一个图像匹配实现,里面包含了采用1NN匹配可视化、1NN匹配后经RANSAC剔除错配点可视化、1NN/2NN<0.8匹配可视化、1NN/2NN<0.8经 RANSAC剔除错配点可视化四个过程,其中1NN/2NN<0.8匹配过程是Lowe的Raw feature match,具体可以阅读Lowe的Distinctive image features from scale-invariant keypoints这篇文章。这个对图像检索重排非常有用。另外里面还有用OpenCV写的ASIFT,这部分来源于OPENCV ASIFT C++ IMPLEMENTATION,ASIFT还可以到官网页面下载,ASIFT提取的关键点 比SIFT要多得多,速度非常慢,不推荐在对要求实时性的应用中使用。 更多详细的分析可以阅读博文SIFT(ASIFT) Matching with RANSAC。 有用链接 OpenCV3.0文档 // 测试sparse unsigned int centersNum = 10; vector descrNums; descrNums.push_back(8); descrNums.push_back(12); //unsigned int T[] = {1, 2, 1, 3, 2, 5, 4, 3, 10, 5; 4, 2, 6, 5, 2, 5, 4, 6, 2, 4}; unsigned int T[] = {1, 2, 1, 3, 2, 5, 4, 3, 10, 5, 4, 2, 6, 5, 2, 5, 4, 6, 2, 4}; sp_mat Hist(descrNums.size(), centersNum); static long int count = 0; for (int i = 0; i < descrNums.size(); i++){ unsigned int* desrcElementsTmp = new unsigned int[descrNums[i]]; memcpy(desrcElementsTmp, T + count, descrNums[i] * sizeof(T[0])); //cout << desrcElementsTmp[0] << '\t' << desrcElementsTmp[1] << '\t' << desrcElementsTmp[2] << '\t' << desrcElementsTmp[3] << '\t' << desrcElementsTmp[4] << '\t' <<endl; //cout << desrcElementsTmp[5] << '\t' << desrcElementsTmp[6] << '\t' << desrcElementsTmp[7] << '\t' << desrcElementsTmp[8] << '\t' << desrcElementsTmp[9] << '\t' << desrcElementsTmp[10] << '\t' <<endl; //cout << endl; sp_mat X(1, centersNum); X.zeros(); for (int j = 0; j < descrNums[i]; j++){ X(0, desrcElementsTmp[j]-1) += 1; } X.print("X:"); X = X/norm(X, 2); Hist.row(i) = X; count = count + descrNums[i]; delete desrcElementsTmp; } //Hist.print("Hist:");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值