openCV内部源代码C++语法解析

因为看OpenCV源代码时候,发现自己很是吃力,所以做出如下总结,与大家分享。
接下来我给大家展示一小部分源代码:···(一定要往后看哦)···


接下来主要对标记0/1/2/3几处进行详细说明
语法解析:
0:类模板 + public继承
1typedef typename 作用
2:构造函数,参数初始化列表
3:()重载

//子类
0:  template<class Op, class VecOp> struct MorphRowFilter : public BaseRowFilter
{
1:  typedef typename Op::rtype T;

2:  MorphRowFilter( int _ksize, int _anchor ) : vecOp(_ksize, _anchor)
    {
        ksize = _ksize;
        anchor = _anchor;
    }
3:  void operator()(const uchar* src, uchar* dst, int width, int cn)
    {
        int i, j, k, _ksize = ksize*cn;
        const T* S = (const T*)src;
        Op op;
        T* D = (T*)dst;

        if( _ksize == cn )
        {
            for( i = 0; i < width*cn; i++ )
                D[i] = S[i];
            return;
        }

        int i0 = vecOp(src, dst, width, cn);   

        width *= cn;

        for( k = 0; k < cn; k++, S++, D++ )
        {
            for( i = i0; i <= width - cn*2; i += cn*2 )
            {
                const T* s = S + i;
                T m = s[cn];
                for( j = cn*2; j < _ksize; j += cn )
                    m = op(m, s[j]);
                D[i] = op(m, s[0]);
                D[i+cn] = op(m, s[j]);
            }

            for( ; i < width; i += cn )
            {
                const T* s = S + i;
                T m = s[0];
                for( j = cn; j < _ksize; j += cn )
                    m = op(m, s[j]);
                D[i] = m;
            }
        }
    }

    VecOp vecOp;
};

//父类(基类)
class CV_EXPORTS BaseColumnFilter
{
public:
//! the default constructor
BaseColumnFilter();
//! the destructor
virtual ~BaseColumnFilter();
//! the filtering operator. Must be overrided in the derived classes. The vertical border interpolation is done outside of the class.
virtual void operator()(const uchar** src, uchar* dst, int dststep,
                        int dstcount, int width) = 0;
//! resets the internal buffers, if any
virtual void reset();
int ksize, anchor;
};

0 :

   template<class Op, class VecOp> struct MorphRowFilter : public BaseRowFilter

类模板 + public继承

解释:Op与VecOp只是抽象的名字, 定义了MorphRowFilter的模板类,并且共有继承了BaseRowFilter

用简单案例来说明 类模板:

//copyright @ hanshanbuleng
#include <iostream>
using namespace std;

//对于类的声明来说,我们会遇到两个或多个类,其功能是相同的,仅仅是数据类型不相同
//如以下,int float 类
//int 类型
class compare_int
{
public:
    compare_int(int a, int b)   //定义构造函数
    {
        x_ = a;
        y_ = b;
    }

    int max()                   //利用三目运算符 求最大值
    {
        return (x_ > y_) ? x_ : y_;
    }

    int min()                   //利用三目运算符 求最小值
    {
        return (x_ < y_) ? x_ : y_;
    }
private:
    int x_;
    int y_;
};

//float 类型
class compare_float
{
public:
    compare_float(float a, float b)   //定义构造函数
    {
        x_ = a;
        y_ = b;
    }

    int max()                   //利用三目运算符 求最大值
    {
        return (x_ > y_) ? x_ : y_;
    }

    int min()                   //利用三目运算符 求最小值
    {
        return (x_ < y_) ? x_ : y_;
    }
private:
    float x_;
    float y_;
};

//类模板   
template <class numtype>            //template <class numtype>            
class compare                       //struct compare        在此处 class与struct可以替换               
{
public:
    compare(numtype a, numtype b)   //定义构造函数
    {
        x_ = a;
        y_ = b;
    }

    int max()                       //利用三目运算符 求最大值
    {
        return (x_ > y_) ? x_ : y_;
    }

    int min()                       //利用三目运算符 求最小值
    {
        return (x_ < y_) ? x_ : y_;
    }
private:
    numtype x_;
    numtype y_;
};

int main()
{
    int flag = 0;   //0正确 -1错误
    int value0;

    float value1;

    compare <int> hanshanbuleng0(10, 20);   //用类模板的方式进行初始化
    value0 = hanshanbuleng0.max();
    printf("value0:%d \n", value0);

    compare <float> hanshanbuleng1(10.0, 20.0);   //用类模板的方式进行初始化
    value1 = hanshanbuleng1.max();
    printf("value0:%f \n", value1);

    return flag;
}

1:

typedef typename Op::rtype T;   

typedef typename 作用
语法让人看着费解 但是当我们知道其含义和用法,就很好理解了
将以上内容进行缩写:

template<class Op, class VecOp> 
{
public:
    typedef typename Op::rtype T;   //与其等价typedef typename <Op>::rtype T

//...
};

我们删去不懂的 typename Op::

template<class Op, class VecOp> 
class MorphRowFilter 
{
public:
    typedef rtype T;   

//...
};

这样就看得很清晰了,MorphRowFilter::T是MorphRowFilter的嵌套类型定义,其实际等价于 rtype类型,也就是表明:
使用中声明 MorphRowFilter ::T INT; <==> rtype INT;

为什么使用typename关键字???
模板类型在实例化之前,编译器并不知道MorphRowFilter<Op>::T 是什么东西,事实上一共有三种可能:
静态数据成员 
静态成员函数 
嵌套类型

那么此时typename的作用就在此时体现出来了————定义就不再模棱两可。
typedef typename Op::rtype T;   //与其等价typedef typename <Op>::rtype T
语句的真是面目是: 
typedef创建了存在类型的别名,而typename告诉编译器MorphRowFilter<Op>::rtype 是一个类型而不是一个成员。

2:

    MorphRowFilter( int _ksize, int _anchor ) : vecOp(_ksize, _anchor)

构造函数,参数初始化列表 ===》本程序中是 用参数初始化表 对数据成员初始化
用vecOp(_ksize, _anchor) 对数据成员VecOp vecOp 初始化
我们要想知道VecOp具体是什么类型,那么我们需要知道是谁调用了

template<class Op, class VecOp> struct MorphRowFilter : public BaseRowFilter
调用源码截取:
if( depth == CV_64F )
return Ptr<BaseRowFilter>(new MorphRowFilter< MinOp<double>, ErodeRowVec64f >(ksize, anchor));
==》 Op 对应 double, VecOp 对应 ErodeRowVec64f
引申:
通过显示调用父类的构造函数对父类数据成员进行初始化
使用初始化列表有两个原因: 
原因1.必须这样做: 
《C++ Primer》中提到在以下三种情况下需要使用初始化成员列表:
一、需要初始化的数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化); 
二、需要初始化const修饰的类成员; 
三、需要初始化引用成员数据

原因2.效率要求这样做: 
类对象的构造顺序显示,进入构造函数体后,进行的是计算,是对成员变量的赋值操作,
显然,赋值和初始化是不同的,这样就体现出了效率差异,如果不用成员初始化类表,
那么类对自己的类成员分别进行的是一次隐式的默认构造函数的调用,和一次赋值操作符的调用,
如果是类对象,这样做效率就得不到保障。

3:

 void operator()(const uchar* src, uchar* dst, int width, int cn)

()重载
运算符重载使得指定的运算符不仅实现原来有的功能,而且实现在函数中指定的新功能。

一般格式如下:
函数类型 operator 运算符名称 (形参表)
{
对运算符的重载处理
}


参考资料:
https://blog.csdn.net/zx3517288/article/details/48806785
https://blog.csdn.net/jinzhichaoshuiping/article/details/51672586

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV是一个开源的计算机视觉库,可以用于实现人脸识别功能。以下是一个示例的人脸识别源代码(用C语言实现): ```c #include <opencv2/opencv.hpp> #include <opencv2/face.hpp> using namespace cv; using namespace cv::face; int main() { // 创建人脸识别器 Ptr<LBPHFaceRecognizer> model = LBPHFaceRecognizer::create(); // 准备训练数据 std::vector<Mat> images; std::vector<int> labels; // 输入样本图片和对应的标签 images.push_back(imread("person1.jpg", 0)); labels.push_back(1); images.push_back(imread("person2.jpg", 0)); labels.push_back(2); // 训练人脸识别模型 model->train(images, labels); // 加载待识别的测试图片 Mat testImage = imread("test.jpg", 0); // 进行人脸识别 int predictedLabel = -1; double predictedConfidence = 0.0; model->predict(testImage, predictedLabel, predictedConfidence); // 输出识别结果 if (predictedLabel != -1) { std::cout << "Predicted label: " << predictedLabel << std::endl; std::cout << "Confidence: " << predictedConfidence << std::endl; } else { std::cout << "No face detected in the test image." << std::endl; } return 0; } ``` 上述代码首先创建了一个LBPHFaceRecognizer的对象,接着加载训练样本图片和对应的标签,并通过train函数对模型进行训练。然后,代码加载待识别的测试图片,调用predict函数进行人脸识别,并输出识别结果。如果成功识别出人脸,代码将打印出预测的标签和置信度。如果无法在测试图片中检测到人脸,则输出未检测到人脸的提示信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值