opencv3.4+contribute编译及官方自带sampl

作者: 和蔼的zhxing | 来源:发表于2018-01-08 13:01 被阅读421次

    环境:win10专业版+opencv3.4+contrib+VS2015

    圣诞前夕,opencv悄悄发布了3.4版本,和3并没有很大的区别,听说是优化了DNN,这个还没用过,正好换了电脑,新电脑上还没来得及配置opencv,昨天下午闲了,我是没想到一下子能编译成功的,因为之前用到sift的时候试了几次都不行,今天却是出奇的顺利,除了有一个小地方自己粗心填错路径之外,其他的都很顺利,因为没想到能配置成功,也就没有截图,我待会稍微重新截一次来写。

    准备工作

    1. 首先去官网上下载opencv主库zip文件,也可直接去github上下载,推荐这样,直接下载最新版本的opencv主库和contrib,链接
      下载下来的是源代码,需要编译才能使用,把两个zip文件解压,建议新建opencv/source文件夹,都解压到这个文件夹里。
    2. 下载cmake,去官网下载就可以了,我这里网有问题,官网的下不来,我另外下载的3.8版本。

    cmake编译

    cmake的界面长这个样子。

    cmake

    source code填写opencv主库的路径,路径下是有cmakelist文件的。
    下面一个路径填写编译结果放的地方,这个自己设置就行了,建议opencv文件夹下新建一个build文件夹,放在这里面就可以了。
    然后点击第一次configure,这个稍微时间长点,中间还要下载一点东西,都是自动完成的,保证联网。
    完了之后上面会有一篇红色,不用担心,找到OPENCV_EXTRA_MODULES_PATH,然后把\opencv_contrib-master\modules 的路径填进去,可以进行第二次configure,configure done提示出现后,就基本完成一半的工作了。

    然后点击generate,提示完成之后大功告成一半。 done

    生成库文件

    然后打开build文件夹,打开这个工程文件:

    opencv
    allbuild
    debug
    这里分别选择debug和release,我是64位生成的,然后ALL_BUILD左键分别生成,这个时间也比较久,机器好的话就比较快。出现 成功xx个,失败0个就OK了。这个时候主要的任务已经完成了。会在build的install文件下生成链接库,就可以直接用了。剩下的过程就很简单了。

    VS一次性配置OpenCV

    1. 环境变量配置
      我的电脑--属性--高级系统设置--环境变量:
      path
      点开path:
      opencv_bin
      这里的路径只是一个演示(我写这个的时候用的是笔记本,笔记本配置的opencv不是自己编译来的那个)这里应该填的是:\opencv\build\install\x64\vc14\bin,这个build文件夹就是刚才新建的存放编译文件的那个。
      然后一路“确定”退出环境变量设置。
    2. 配置项目环境。
      2.1 打开VS,新建c++空项目。


      c++空项目

      确定即可。
      2.2:打开属性列表
      视图--其他窗口--属性管理器,然后可以在右边(随设置不同而不同)看到属性管理器,长这样:


      属性管理器
      需要配置的是这两个红色的(其实是一个东西)。
      2.3:配置。
      双击打开:
      目录

    ① 包含目录:

    \opencv\build\install\include 
    \opencv\build\install\include\opencv 
    \opencv\build\install\include\opencv2
    

    ② 库目录:
    \opencv\new_build\install\x64\vc14\lib
    ③ 附加依赖项
    链接器--输入:

    附加依赖项
    然后把lib里面所有的都添加进去,我配置的openc3.4还没有找到网上有人写,所以都是自己一个一个敲上去的:
    opencv_aruco340.lib
    opencv_bgsegm340.lib
    opencv_bioinspired340.lib
    opencv_calib3d340.lib
    opencv_ccalib340.lib
    opencv_core340.lib
    opencv_datasets340.lib
    opencv_dnn340.lib
    opencv_dpm340.lib
    opencv_face340.lib
    opencv_features2d340.lib
    opencv_flann340.lib
    opencv_fuzzy340.lib
    opencv_highgui340.lib
    opencv_img_hash340.lib
    opencv_imgcodecs340.lib
    opencv_imgproc340.lib
    opencv_line_descriptor340.lib
    opencv_ml340.lib
    opencv_objdetect340.lib
    opencv_optflow340.lib
    opencv_phase_unwrapping340.lib
    opencv_photo340.lib
    opencv_plot340.lib
    opencv_reg340.lib
    opencv_rgbd340.lib
    opencv_saliency340.lib
    opencv_shape340.lib
    opencv_stereo340.lib
    opencv_stitching340.lib
    opencv_structured_light340.lib
    opencv_superres340.lib
    opencv_surface_matching340.lib
    opencv_text340.lib
    opencv_tracking340.lib
    opencv_video340.lib
    opencv_videoio340.lib
    opencv_videostab340.lib
    opencv_xfeatures2d340.lib
    opencv_ximgproc340.lib
    opencv_xobjdetect340.lib
    opencv_xphoto340.lib
    

    有说添加完环境变量后要重启一下电脑,我没有重启也可以,至此就大功告成了。接下来就是激动人心的测试阶段了。

    测试

    随便在网上找了一段sift的代码来测试,sift是在contrib里的,所以都可以测试一下。
    代码:

    /***************************************************************************
    *检测候选特征点周围一圈的像素值,如果候选点周围领域内有足够多的像素点与该候选点的灰度值差别够大,则认为该候选点为一个特征点。
    *如果测试了候选点周围每隔90度角的4个点,应该至少有3个和候选点的灰度值差足够大,否则则不用再计算其他点,直接认为该候选点不是特征点。候选点周围的圆的选取半径是一个很重要的参数,
    *http://www.tuicool.com/articles/NzE77nB
    *http://blog.sina.com.cn/s/blog_a98e39a201017pgn.html
    *http://www.xuebuyuan.com/582341.html
    *http://blog.csdn.net/poem_qianmo/article/details/33320997
    ***************************************************************************/
    
    #include <iostream>  
    #include<opencv2\opencv.hpp>  
    #include"opencv2/xfeatures2d.hpp"  
    
    using namespace cv;
    using namespace std;
    using namespace cv::xfeatures2d;
    using namespace cv::ml;
    
    int main()
    {
        Mat a = imread("1.jpg", 0);    //读取灰度图像  
        Mat b = imread("2.jpg", 0);
    
        Ptr<SURF> surf;                   //创建方式和opencv2中的不一样  
                                          //  Ptr<SIFT> sift;  
        surf = SURF::create(800);       //阈值  
    
        BFMatcher matcher;                //匹配器  
        Mat c, d;
        vector<KeyPoint> key1, key2;
        vector<DMatch> matches;
    
        //结果为一个Mat矩阵,它的行数与特征点向量中元素个数是一致的。每行都是一个N维描述子的向量  
        surf->detectAndCompute(a, Mat(), key1, c);      //检测关键点和匹配描述子  
        surf->detectAndCompute(b, Mat(), key2, d);
    
        matcher.match(c, d, matches);         // 匹配,得到匹配向量  
    
        sort(matches.begin(), matches.end());  // 匹配点排序  
        vector< DMatch > good_matches;            // 匹配两幅图像的描述子  
        int ptsPairs = min(50, (int)(matches.size() * 0.15));
        cout << ptsPairs << endl;
        for (int i = 0; i < ptsPairs; i++)       // 将匹配较好的特征点存入good_matches中  
        {
            good_matches.push_back(matches[i]);
        }
        Mat outimg;
        drawMatches(                               // 绘制匹配点  
            a,                                    // 原图像1  
            key1,                                 // 原图像1的特征点  
            b,                                    // 原图像2  
            key2,                                 // 原图像2的特征点  
            good_matches,                         // 原图像1的特征点匹配原图像2的特征点[matches[i]]  
            outimg,                               // 输出图像具体由flags决定  
            Scalar::all(-1),                    // 匹配的颜色(特征点和连线),若matchColor==Scalar::all(-1),颜色随机  
            Scalar::all(-1),                    // 单个点的颜色,即未配对的特征点,若matchColor==Scalar::all(-1),颜色随机  
            vector<char>(),                       // Mask决定哪些点将被画出,若为空,则画出所有匹配点  
            DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);  //Fdefined by DrawMatchesFlags  
    
        imshow("匹配图", outimg);
        waitKey();
    
        vector<Point2f> obj;
        vector<Point2f> scene;
    
        for (size_t i = 0; i < good_matches.size(); i++)
        {
            ////good_matches[i].queryIdx保存着第一张图片匹配点的序号,keypoints_1[good_matches[i].queryIdx].pt.x 为该序号对应的点的x坐标  
            obj.push_back(key1[good_matches[i].queryIdx].pt);
            scene.push_back(key2[good_matches[i].trainIdx].pt);
        }
    
        vector<Point2f> scene_corners(4);
        vector<Point2f> obj_corners(4);
        obj_corners[0] = Point(0, 0);
        obj_corners[1] = Point(a.cols, 0);
        obj_corners[2] = Point(a.cols, a.rows);
        obj_corners[3] = Point(0, a.rows);
    
        Mat H = findHomography(              // 在两个平面之间寻找单映射变换矩阵  
            obj,                            // 在原平面上点的坐标  
            scene,                          // 在目标平面上点的坐标  
            RANSAC);                        // 用于计算单映射矩阵的方法  
    
        perspectiveTransform(                // 向量组的透视变换  
            obj_corners,                    // 输入两通道或三通道的浮点数组,每一个元素是一个2D/3D 的矢量转换  
            scene_corners,                  // 输出和src同样的size和type  
            H);                             // 3x3 或者4x4浮点转换矩阵  
    
    
                                            // 绘制  
        line(outimg, scene_corners[0] + Point2f((float)a.cols, 0), scene_corners[1] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);
        line(outimg, scene_corners[1] + Point2f((float)a.cols, 0), scene_corners[2] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);
        line(outimg, scene_corners[2] + Point2f((float)a.cols, 0), scene_corners[3] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);
        line(outimg, scene_corners[3] + Point2f((float)a.cols, 0), scene_corners[0] + Point2f((float)a.cols, 0), Scalar(0, 255, 0), 2, LINE_AA);
        imshow("匹配图", outimg);
        waitKey(0);
    }
    

    结果:


    sift匹配结果

    如果没有报错且成功出现结果,那么就好好享受opencv的魔力吧,编译之后opencv的所有源码都是可见的,用到什么函数的时候不懂只要在函数名上右键跳转,就可以抵达源代码欣赏(被虐)了。

    samples编译

    opencv自带了很多例程,编译出来大概近两百个,基本都是主库里的。下面说如何编译这些自带的samples,当然不编译的话也可以用,就是得手动地把cpp文件或者cpp的内容拷贝到自己新建的解决方案(项目里)。这些例程在:
    source/opencv/samples里。给的是一些cpp源文件,可以直接复制到自己的项目里,不过这样太麻烦了,编译生成独立的项目会更易于学习。

    1. 编译samples
      首先打开cmake,source code填入sample所在的路径,这个路径下也是有cmakelist文件的。


      samples

      然后就可以点击第一次configure了,这个第一遍一般会报错,错误的原因是有一个文件路径找不到:


      opencv_dir 把这个路径改成上面编译的那个build文件夹的路径重新configure就可以了。
      然后点generate就可以了:
      done

      看到这里就说明成功生成了,这个图是我在笔记本上编译samples,用的还是3.3,不过编译过程是完全一样的。

    2. 生成解决方案。
      2.1 打开解决方案。
      camke的使命就完成了,现在在刚才生成目录下打开sample工程文件:


      samples

      2.2 打开之后可以直接生成解决方案了。
      打开之后找到ALL_BUILD,右键生成,然后就是等待了:opencv3.3里是有164个例程,3.4多十个左右。


      done
      这样就是成功了,可以愉快的学习了。
      solution
      这个解决方案里有164个例程,打开都是可以看的,可以看到上面的几个是几种深度学习的实现,但是好像opencv还不能实现训练,只能去下载别人训练好的参数来跑(我也没试过,听说的)。
      下面是一些常用的功能,要学习哪一个,把那个设置为启动项目(右键-设置为启动项目),就可以debug或release了。我发现这样的话图片的路径还是要自己手动设置的,但是已经不算麻烦了,具体看代码吧。

      找了个不需要设置图片路径的kmease来测试:


      kmease
      完美。

    summary

    至此opencv opencv_contrib samples的编译和配置就完成了,昨天出奇的顺利,基本没有遇到什么障碍,可能是因为自己都配置过几次有些坑踩掉了,中间还是参考了一些博客,不过已经不记得了是哪些了,也比较乱,这里一并感谢了。最近有一段时间没有看opencv了,这样完了之后希望可以把opencv拾起来看一看,官方给的这些例程看一看跑一跑。

    相关文章

      网友评论

        本文标题:opencv3.4+contribute编译及官方自带sampl

        本文链接:https://www.haomeiwen.com/subject/wkemnxtx.html