OpenCV2马拉松第1圈——纵观全局

前话

我会结合计算机视觉算法与应用,冈萨雷斯图像处理,以及CVPR,ICCV等论文深入原理,不仅会用OpenCV,还要懂原理。

Version1和Version2的主要差别

OpenCV2和OpenCV1的一个主要差别就是1是C的版本,2是C++的版本


简要介绍


OpenCV有很多的模块

  • core,定义了许多数据结构和基本的函数
  • imgproc,顾名思义就是处理图片的模块,包括线性和非线性滤波器,图形几何变换,颜色空间变换,直方图
  • video,包括运动估计,背景消除,物体跟踪
  • calib3d,摄像机标定,姿态估计,3D重建
  • features2D,用于特征的检测
  • objdetect,可方便实现人脸识别,眼睛,人,车也可以,已经训练过了
  • highgui,很方便的图像捕获接口
  • gpu,跟GPU加速有关
  • 等等
一些要了解的常识
OpenCV所有的东西都在cv这个namespace下面
所在,我们在调用的时候可以这样
#include "opencv2/core/core.hpp"
...
cv::Mat H = cv::findHomography(points1, points2, CV_RANSAC, 5);

或者
#include "opencv2/core/core.hpp"
using namespace cv;
...
Mat H = findHomography(points1, points2, CV_RANSAC, 5 );

当你的命名空间有std,cv等等大于1个的时候,就有可能导致冲突,比如log函数,这时候就必须要指定了
Mat a(100, 100, CV_32F);
randu(a, Scalar::all(1), Scalar::all(std::rand()));
cv::log(a, a);
a /= std::log(2.);

自动内存管理
在使用version1的时候,我们都要free(image)
在version2里面,所有的类都有解析函数,不需要你手动去管理了
// 创建了1000*1000,每个像素点是64位浮点数
Mat A(1000, 1000, CV_64F);

// B和A共享像素数据,这个操作是立即的,不需要复制像素点
Mat B = A;
// 跟上面一样,只是共享了row3
Mat C = B.row(3);
// 现在是独立的复制了
Mat D = B.clone();
// 把B的第5行复制给C, 其实就是把A的第5行复制给A的第3行
B.row(5).copyTo(C);
// A共享了D的数据;
A = D;

// C仍然指向修改后的A的数据
B.release();

// 这时候,A原来的数据就消失了
C = C.clone();

当你创建属于自己的数据结构,但是又没有自动内存管理怎么办?
OpenCV有自己的智能指针
Ptr<T> ptr = new T(...);

OpenCV大多数时候会自动为输出矩阵分配内存
#include "cv.h"
#include "highgui.h"

using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0);
    if(!cap.isOpened()) return -1;

    Mat frame, edges;
    namedWindow("edges",1);
    for(;;)
    {
        cap >> frame;
        cvtColor(frame, edges, CV_BGR2GRAY);
        GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
        Canny(edges, edges, 0, 30, 3);
        imshow("edges", edges);
        if(waitKey(30) >= 0) break;
    }
    return 0;
}
cap >> frame,>> 自动为 frame分配内存,包括type,size和量化位数(bit-depth)
edges也会自动分配

防止溢出
大多数图像处理都是8位,16位的数字
I.at<uchar>(y, x) = saturate_cast<uchar>(r);
OpenCV提供了防止溢出的功能
,就像这样

减少模版的使用
我们知道,模版的实现要写在头文件中(这是编译链接所决定的),如果大量使用模版,不仅编译速度慢,代码也会很难看,因为一个算法就可能要上千行。
所以OpenCV固定了像素的一些类型
  • 8-bit unsigned integer (uchar)
  • 8-bit signed integer (schar)
  • 16-bit unsigned integer (ushort)
  • 16-bit signed integer (short)
  • 32-bit signed integer (int)
  • 32-bit floating-point number (float)
  • 64-bit floating-point number (double)
enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };

多通道通过如下方式指定
  • CV_8UC1 ... CV_64FC4 constants (for a number of channels from 1 to 4)
  • CV_8UC(n) ... CV_64FC(n) or CV_MAKETYPE(CV_8U, n) ... CV_MAKETYPE(CV_64F, n) macros when the number of channels is more than 4 or unknown at the compilation time.
注意:CV_32FC1  ==  CV_32F CV_32FC2  ==  CV_32FC(2)  ==  CV_MAKETYPE(CV_32F,  2)
Examples:
Mat mtx(3, 3, CV_32F); // make a 3x3 floating-point matrix
Mat cmtx(10, 1, CV_64FC2); // make a 10x1 2-channel floating-point
                           // matrix (10-element complex vector)
Mat img(Size(1920, 1080), CV_8UC3); // make a 3-channel (color) image
                                    // of 1920 columns and 1080 rows.
Mat grayscale(image.size(), CV_MAKETYPE(image.depth(), 1)); // make a 1-channel image of
                                                            // the same size and same
                                                            // channel type as img

OpenCV的函数只能处理上面这些类型的矩阵图片,算法越复杂,能处理的矩阵类型就越少
  • 人脸检测只能处理8bit灰度图和彩色图片
  • 大多数机器学习算法只能应用于浮点矩阵
  • 简单的函数,比如矩阵相加,cv::add,适用所有类型
  • 颜色空间转换适用8-bit unsigned, 16-bit unsigned, and 32-bit floating-point types
InputArray and OutputArray
在参数类型是这些时,你可以用Matstd::vector<>Matx<>Vec<> or Scalar来替代,InputArray是只读的
当你不想传参数时,使用cv::noArray()

错误处理
try
{
    ... // call OpenCV
}
catch( cv::Exception& e )
{
    const char* err_msg = e.what();
    std::cout << "exception caught: " << err_msg << std::endl;
}

放心大胆使用多线程
前提当然是你自己不要很2,写出死锁或者竞争的代码

你可能感兴趣的:(opencv2)