目录

一、前言

二、温故知新——Rect_

1、定义与成员变量

2、构造函数

3、常用方法

三、Scalar_

1、定义

1.构造函数

2.基本操作

3.使用时的数据类型

2、常用方法

1.加法及加赋值运算

2.减法及减赋值运算

3.乘法及乘赋值运算

4.除法及除赋值运算

5.等于与不等于

6.负号

3、代码实战——构建纯色图像

说在后面的话


一、前言

上一篇文章,我们讲了OpenCV中的一个基础结构,Rect_结构,再加上之前讲的两个结构,我们已经讲过三个基本架构啦!

我们也看到了我们讲的结构没有涉及到颜色,而在计算机视觉中,颜色是非常重要的一部分,所以我们今天要讲的Scala_类,就是讲解颜色的,这也是我们要讲的最后一个基础结构了。

其实我们知道,还有很多基础结构,但其他的其实并不常用。有的可能是用于某个特定的领域,比如用于三维空间的点的Point3_,用于特征检测的KeyPoint等,如果我们在后面用到了,我们再进行详细说明吧!

二、温故知新——Rect_

1、定义与成员变量

上一节课,我们讲到了Rect_,大家还记得,我们说的,该怎么理解这个结构吗?

对,就是下面这个:

一个明确位置且横平竖直的矩形。

怎么理解这句话呢?

什么是明确位置,就是需要一个定位点;

什么是横平竖直,就是只通过长和宽就能唯一确定一个矩形。

所以,我们需要四个成员变量:

表示横纵坐标位置的两个成员变量:x,y

表示长宽的两个成员变量:height,width

    _Tp x; //!< x coordinate of the top-left corner_Tp y; //!< y coordinate of the top-left corner_Tp width; //!< width of the rectangle_Tp height; //!< height of the rectangle

2、构造函数

所以构造过程无非就是给这四个变量赋值,我们有如下几种方式:

第一种方式是使用一个点的坐标和长宽。

(1)对于这种方式,我们既可以给四个参数:横坐标、纵坐标、长、宽:

(2)也可以使用我们昨天提到的两个类型:Point_和Size_。

第二种方式是使用两个对角线顶点。

第三种方式是使用另外的矩形为该矩形赋值。

    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);Rect_(const Rect_& r);Rect_(Rect_&& r) CV_NOEXCEPT;

3、常用方法

常用方法内容比较多,主要有如下几个方面:

1.定位点的移位操作;

2.矩形尺寸变化操作;

3.求公共矩阵操作;

4.求最小包围矩阵操作;

5.获取矩形基本信息(定位点、长宽、尺寸、面积、左上角与右下角坐标)操作;

6.判断矩阵是否相同操作;

7.计算点是否在矩形内操作;

8.赋值操作;

还有很多常用操作,因为内容比较多,就不再在这里说明啦!大家可以打开上一篇博客去详细查看哦:

Rect_类常用方法

三、Scalar_

接下来就让我们走进最后一个最常用的基本结构Scalar_吧!如果你没有接触过色彩相关内容,那可能对这些内容不太清楚,首先,我们先来看一下三原色:

三原色指色彩中不能再分解的三种基本颜色,我们通常说的三原色,是色彩三原色以及光学三原色

三原色主要有如下两种类型:

1.颜料三原色(CMYK):品红、黄、青(天蓝)。色彩三原色可以混合出所有颜料的颜色,同时相加为黑色,黑白灰属于无色系。

2.光学三原色(RGB):红、绿、蓝(靛蓝)。光学三原色混合后,组成显示屏显示颜色,三原色同时相加为白色,白色属于无色系(黑白灰)中的一种。

在我们计算机视觉中用到的颜色是光学颜色,所有,我们这里要用到的像素都是基于光学三原色的。接下来让我们从定义走近它——Scalar_。

1、定义

首先让我们看一下定义介绍:

/** @brief Template class for a 4-element vector derived from Vec.Being derived from Vec\<_Tp, 4\> , Scalar\_ and Scalar can be used just as typical 4-element
vectors. In addition, they can be converted to/from CvScalar . The type Scalar is widely used in
OpenCV to pass pixel values.
*/

这里面说,Scalar其实是一个从Vec派生得到的四元向量的模板类,在OpenCV中广泛用于传递像素值。

我们接着看一下定义:

template<typename _Tp> class Scalar_ : public Vec<_Tp, 4>
{
public://! default constructorScalar_();Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);Scalar_(_Tp v0);Scalar_(const Scalar_& s);Scalar_(Scalar_&& s) CV_NOEXCEPT;Scalar_& operator=(const Scalar_& s);Scalar_& operator=(Scalar_&& s) CV_NOEXCEPT;template<typename _Tp2, int cn>Scalar_(const Vec<_Tp2, cn>& v);//! returns a scalar with all elements set to v0static Scalar_<_Tp> all(_Tp v0);//! conversion to another data typetemplate<typename T2> operator Scalar_<T2>() const;//! per-element productScalar_<_Tp> mul(const Scalar_<_Tp>& a, double scale=1 ) const;//! returns (v0, -v1, -v2, -v3)Scalar_<_Tp> conj() const;//! returns true iff v1 == v2 == v3 == 0bool isReal() const;
};typedef Scalar_<double> Scalar;template<typename _Tp> class DataType< Scalar_<_Tp> >
{
public:typedef Scalar_<_Tp>                               value_type;typedef Scalar_<typename DataType<_Tp>::work_type> work_type;typedef _Tp                                        channel_type;enum { generic_type = 0,channels     = 4,fmt          = traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED,depth        = DataType<channel_type>::depth,type         = CV_MAKETYPE(depth, channels)
#endif};typedef Vec<channel_type, channels> vec_type;
};namespace traits {
template<typename _Tp>
struct Depth< Scalar_<_Tp> > { enum { value = Depth<_Tp>::value }; };
template<typename _Tp>
struct Type< Scalar_<_Tp> > { enum { value = CV_MAKETYPE(Depth<_Tp>::value, 4) }; };
} // namespace

这里面最基本的定义主要包括如下三部分:

1.构造函数

几个构造函数,用于生成Scalar对象:

    //! default constructorScalar_();Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);Scalar_(_Tp v0);Scalar_(const Scalar_& s);Scalar_(Scalar_&& s) CV_NOEXCEPT;

第一个构造函数,我们已经见怪不怪了,几乎有所的类中的默认构造函数都是无参,并且赋值为0或空。

第二个就是我们最常用的,但是一般情况,我们只赋值前三个,第一个参数表示蓝色,第二个参数表示绿色,第三个参数表示红色,也就是BGR:

    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);Scalar(0, 0, 255); // 红色Scalar(0, 255, 0); // 绿色Scalar(255, 0, 0); // 蓝色

第三个只设置第一个参数,是因为后面的每个都默认设置为0了:

template<typename _Tp> inline
Scalar_<_Tp>::Scalar_(_Tp v0)
{this->val[0] = v0;this->val[1] = this->val[2] = this->val[3] = 0;
}

后两个就是用别的Scalar赋值。

2.基本操作

在Scalar_中有如下基本操作:

//! 将所有元素都设为v0static Scalar_<_Tp> all(_Tp v0);//! 转换为其他类型template<typename T2> operator Scalar_<T2>() const;//! 乘积Scalar_<_Tp> mul(const Scalar_<_Tp>& a, double scale=1 ) const;//! 返回 (v0, -v1, -v2, -v3)Scalar_<_Tp> conj() const;//! 返回真 true 如果 v1 == v2 == v3 == 0bool isReal() const;

第一个,将所有元素都设为v0

实现代码如下:

template<typename _Tp> inline
Scalar_<_Tp> Scalar_<_Tp>::all(_Tp v0)
{return Scalar_<_Tp>(v0, v0, v0, v0);
}

实验代码如下:

 Scalar color = Scalar();color = color.all(120);cout << color << endl;

输出结果如下:

第二个,计算两个Scalar的乘积

实现代码如下,其中scale是一个标量参数,saturate_cast是将数据范围控制在0-255之间,但是我们要注意,在输出的时候,还是原来的数值,但是在以颜色输出就会控制在0-255之间了:

template<typename _Tp> inline
Scalar_<_Tp> Scalar_<_Tp>::mul(const Scalar_<_Tp>& a, double scale ) const
{return Scalar_<_Tp>(saturate_cast<_Tp>(this->val[0] * a.val[0] * scale),saturate_cast<_Tp>(this->val[1] * a.val[1] * scale),saturate_cast<_Tp>(this->val[2] * a.val[2] * scale),saturate_cast<_Tp>(this->val[3] * a.val[3] * scale));
}

实验代码如下:

 Scalar color1 = Scalar(12, 255, 14);Scalar color2 = Scalar(122, 14, 145);Scalar color3 = color1.mul(color2);cout << color3 << endl;Mat img = Mat(200, 200, CV_8UC3, color3);imshow("test2", img);

输出结果如下:

当三个都是255的时候,是纯白色图像。

第三个,返回 (v0, -v1, -v2, -v3)

实现代码如下:

template<typename _Tp> inline
Scalar_<_Tp> Scalar_<_Tp>::conj() const
{return Scalar_<_Tp>(saturate_cast<_Tp>( this->val[0]),saturate_cast<_Tp>(-this->val[1]),saturate_cast<_Tp>(-this->val[2]),saturate_cast<_Tp>(-this->val[3]));
}

实验代码如下:

 Scalar color2 = Scalar(122, 14, 145);Scalar color4 = color2.conj();cout << color4 << endl;

执行结果如下:

第四个,如果前三个都是0,那么返回true

实现代码如下:

template<typename _Tp> inline
bool Scalar_<_Tp>::isReal() const
{return this->val[1] == 0 && this->val[2] == 0 && this->val[3] == 0;
}

实验代码如下:

 Scalar color5 = Scalar();if (color5.isReal()) {cout << color5 << " is real" << endl;}

执行结果如下:

3.使用时的数据类型

当我们定义了Scalar_类之后,跟上面一样,我们要定义具体的使用过程中的类型:

typedef Scalar_<double> Scalar;

2、常用方法

接下来我们要说的就是方法,颜色没有那么多花花肠子,只涉及到最基本的数值运算 。

template<typename _Tp> static inline
Scalar_<_Tp>& operator += (Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{a.val[0] += b.val[0];a.val[1] += b.val[1];a.val[2] += b.val[2];a.val[3] += b.val[3];return a;
}template<typename _Tp> static inline
Scalar_<_Tp>& operator -= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{a.val[0] -= b.val[0];a.val[1] -= b.val[1];a.val[2] -= b.val[2];a.val[3] -= b.val[3];return a;
}template<typename _Tp> static inline
Scalar_<_Tp>& operator *= ( Scalar_<_Tp>& a, _Tp v )
{a.val[0] *= v;a.val[1] *= v;a.val[2] *= v;a.val[3] *= v;return a;
}template<typename _Tp> static inline
bool operator == ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b )
{return a.val[0] == b.val[0] && a.val[1] == b.val[1] &&a.val[2] == b.val[2] && a.val[3] == b.val[3];
}template<typename _Tp> static inline
bool operator != ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b )
{return a.val[0] != b.val[0] || a.val[1] != b.val[1] ||a.val[2] != b.val[2] || a.val[3] != b.val[3];
}template<typename _Tp> static inline
Scalar_<_Tp> operator + (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{return Scalar_<_Tp>(a.val[0] + b.val[0],a.val[1] + b.val[1],a.val[2] + b.val[2],a.val[3] + b.val[3]);
}template<typename _Tp> static inline
Scalar_<_Tp> operator - (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{return Scalar_<_Tp>(saturate_cast<_Tp>(a.val[0] - b.val[0]),saturate_cast<_Tp>(a.val[1] - b.val[1]),saturate_cast<_Tp>(a.val[2] - b.val[2]),saturate_cast<_Tp>(a.val[3] - b.val[3]));
}template<typename _Tp> static inline
Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, _Tp alpha)
{return Scalar_<_Tp>(a.val[0] * alpha,a.val[1] * alpha,a.val[2] * alpha,a.val[3] * alpha);
}template<typename _Tp> static inline
Scalar_<_Tp> operator * (_Tp alpha, const Scalar_<_Tp>& a)
{return a*alpha;
}template<typename _Tp> static inline
Scalar_<_Tp> operator - (const Scalar_<_Tp>& a)
{return Scalar_<_Tp>(saturate_cast<_Tp>(-a.val[0]),saturate_cast<_Tp>(-a.val[1]),saturate_cast<_Tp>(-a.val[2]),saturate_cast<_Tp>(-a.val[3]));
}template<typename _Tp> static inline
Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{return Scalar_<_Tp>(saturate_cast<_Tp>(a[0]*b[0] - a[1]*b[1] - a[2]*b[2] - a[3]*b[3]),saturate_cast<_Tp>(a[0]*b[1] + a[1]*b[0] + a[2]*b[3] - a[3]*b[2]),saturate_cast<_Tp>(a[0]*b[2] - a[1]*b[3] + a[2]*b[0] + a[3]*b[1]),saturate_cast<_Tp>(a[0]*b[3] + a[1]*b[2] - a[2]*b[1] + a[3]*b[0]));
}template<typename _Tp> static inline
Scalar_<_Tp>& operator *= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{a = a * b;return a;
}template<typename _Tp> static inline
Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, _Tp alpha)
{return Scalar_<_Tp>(a.val[0] / alpha,a.val[1] / alpha,a.val[2] / alpha,a.val[3] / alpha);
}template<typename _Tp> static inline
Scalar_<float> operator / (const Scalar_<float>& a, float alpha)
{float s = 1 / alpha;return Scalar_<float>(a.val[0] * s, a.val[1] * s, a.val[2] * s, a.val[3] * s);
}template<typename _Tp> static inline
Scalar_<double> operator / (const Scalar_<double>& a, double alpha)
{double s = 1 / alpha;return Scalar_<double>(a.val[0] * s, a.val[1] * s, a.val[2] * s, a.val[3] * s);
}template<typename _Tp> static inline
Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, _Tp alpha)
{a = a / alpha;return a;
}template<typename _Tp> static inline
Scalar_<_Tp> operator / (_Tp a, const Scalar_<_Tp>& b)
{_Tp s = a / (b[0]*b[0] + b[1]*b[1] + b[2]*b[2] + b[3]*b[3]);return b.conj() * s;
}template<typename _Tp> static inline
Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{return a * ((_Tp)1 / b);
}template<typename _Tp> static inline
Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{a = a / b;return a;
}template<typename _Tp> static inline
Scalar operator * (const Matx<_Tp, 4, 4>& a, const Scalar& b)
{Matx<double, 4, 1> c((Matx<double, 4, 4>)a, b, Matx_MatMulOp());return reinterpret_cast<const Scalar&>(c);
}template<> inline
Scalar operator * (const Matx<double, 4, 4>& a, const Scalar& b)
{Matx<double, 4, 1> c(a, b, Matx_MatMulOp());return reinterpret_cast<const Scalar&>(c);
}

1.加法及加赋值运算

我们先从最简单的加法及加赋值说起,有如下几个:

template<typename _Tp> static inline
Scalar_<_Tp> operator + (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{return Scalar_<_Tp>(a.val[0] + b.val[0],a.val[1] + b.val[1],a.val[2] + b.val[2],a.val[3] + b.val[3]);
}template<typename _Tp> static inline
Scalar_<_Tp>& operator += (Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{a.val[0] += b.val[0];a.val[1] += b.val[1];a.val[2] += b.val[2];a.val[3] += b.val[3];return a;
}

注:个人见解

如果要用到像素中,上面的代码是有问题的,因为加法可能超出255的范围,也有可能输入是负值。所以如果是要用到像素中,要修改像素的范围区间的。后面的类似。

加法和加赋值无疑是最简单的,就是两个类型的对应数值分别相加,我们看个简单示例:

 Scalar color6 = Scalar(152, 100, 4);Scalar color7 = Scalar(2, 120, 105);cout << "color6 + color7 = " << color6 + color7 << endl;color6 += color7;cout << "color6 += color7  " << color6 << endl;

执行结果如下:

2.减法及减赋值运算

减法及减赋值和加法及加赋值是类似的,有如下几个:


template<typename _Tp> static inline
Scalar_<_Tp> operator - (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{return Scalar_<_Tp>(saturate_cast<_Tp>(a.val[0] - b.val[0]),saturate_cast<_Tp>(a.val[1] - b.val[1]),saturate_cast<_Tp>(a.val[2] - b.val[2]),saturate_cast<_Tp>(a.val[3] - b.val[3]));
}template<typename _Tp> static inline
Scalar_<_Tp>& operator -= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{a.val[0] -= b.val[0];a.val[1] -= b.val[1];a.val[2] -= b.val[2];a.val[3] -= b.val[3];return a;
}

我们看个简单示例:

 Scalar color6 = Scalar(152, 100, 4);Scalar color7 = Scalar(2, 120, 105);cout << "color6 = " << color6 << endl;cout << "color7 = " << color7 << endl;cout << "color6 + color7 = " << color6 + color7 << endl;color6 += color7;cout << "color6 += color7  " << color6 << endl;

执行结果如下:

3.乘法及乘赋值运算

乘法就比较多啦,有如下几个:

template<typename _Tp> static inline
Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, _Tp alpha)
{return Scalar_<_Tp>(a.val[0] * alpha,a.val[1] * alpha,a.val[2] * alpha,a.val[3] * alpha);
}template<typename _Tp> static inline
Scalar_<_Tp> operator * (_Tp alpha, const Scalar_<_Tp>& a)
{return a*alpha;
}template<typename _Tp> static inline
Scalar_<_Tp>& operator *= ( Scalar_<_Tp>& a, _Tp v )
{a.val[0] *= v;a.val[1] *= v;a.val[2] *= v;a.val[3] *= v;return a;
}template<typename _Tp> static inline
Scalar_<_Tp> operator * (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{return Scalar_<_Tp>(saturate_cast<_Tp>(a[0]*b[0] - a[1]*b[1] - a[2]*b[2] - a[3]*b[3]),saturate_cast<_Tp>(a[0]*b[1] + a[1]*b[0] + a[2]*b[3] - a[3]*b[2]),saturate_cast<_Tp>(a[0]*b[2] - a[1]*b[3] + a[2]*b[0] + a[3]*b[1]),saturate_cast<_Tp>(a[0]*b[3] + a[1]*b[2] - a[2]*b[1] + a[3]*b[0]));
}template<typename _Tp> static inline
Scalar_<_Tp>& operator *= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{a = a * b;return a;
}template<typename _Tp> static inline
Scalar operator * (const Matx<_Tp, 4, 4>& a, const Scalar& b)
{Matx<double, 4, 1> c((Matx<double, 4, 4>)a, b, Matx_MatMulOp());return reinterpret_cast<const Scalar&>(c);
}template<> inline
Scalar operator * (const Matx<double, 4, 4>& a, const Scalar& b)
{Matx<double, 4, 1> c(a, b, Matx_MatMulOp());return reinterpret_cast<const Scalar&>(c);
}

我们发现这个时候,就不仅仅是两个向量之间的运算了,还包括向量和标量的运算,我们看简单示例:

 Scalar color6 = Scalar(152, 100, 4);Scalar color7 = Scalar(2, 120, 105);Mat img = Mat(200, 600, CV_8UC3, color6);imshow("color6", img);img = Mat(200, 600, CV_8UC3, color7);imshow("color7", img);cout << "color6 * 5 = " << color6 * 5 << endl;cout << "5 * color6 = " << 5 * color6 << endl;color6 *= 5;cout << "color6 *= 5  " << color6 << endl;color6 = Scalar(152, 100, 4);color7 = Scalar(2, 120, 105);cout << "color6 = " << color6 << endl;cout << "color7 = " << color7 << endl;cout << "color6 * color7 = " << color6 * color7 << endl;color6 *= color7;cout << "color6 *= color7  " << color6 << endl;img = Mat(200, 600, CV_8UC3, color6);imshow("color6 * color7", img);

执行结果如下:

4.除法及除赋值运算

减法及减赋值和加法及加赋值是类似的,有如下几个:

template<typename _Tp> static inline
Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, _Tp alpha)
{return Scalar_<_Tp>(a.val[0] / alpha,a.val[1] / alpha,a.val[2] / alpha,a.val[3] / alpha);
}template<typename _Tp> static inline
Scalar_<float> operator / (const Scalar_<float>& a, float alpha)
{float s = 1 / alpha;return Scalar_<float>(a.val[0] * s, a.val[1] * s, a.val[2] * s, a.val[3] * s);
}template<typename _Tp> static inline
Scalar_<double> operator / (const Scalar_<double>& a, double alpha)
{double s = 1 / alpha;return Scalar_<double>(a.val[0] * s, a.val[1] * s, a.val[2] * s, a.val[3] * s);
}template<typename _Tp> static inline
Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, _Tp alpha)
{a = a / alpha;return a;
}template<typename _Tp> static inline
Scalar_<_Tp> operator / (_Tp a, const Scalar_<_Tp>& b)
{_Tp s = a / (b[0]*b[0] + b[1]*b[1] + b[2]*b[2] + b[3]*b[3]);return b.conj() * s;
}template<typename _Tp> static inline
Scalar_<_Tp> operator / (const Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{return a * ((_Tp)1 / b);
}template<typename _Tp> static inline
Scalar_<_Tp>& operator /= (Scalar_<_Tp>& a, const Scalar_<_Tp>& b)
{a = a / b;return a;
}

我们看个简单示例:

 Scalar color6 = Scalar(152, 100, 4);Scalar color7 = Scalar(2, 120, 105);cout << "color6 / 5 = " << color6 / 5 << endl;cout << "5.0 / color6 = " << 5.0 / color6 << endl; //注意不能用: 5 / color6cout << "color6 / color7 = " << color6 / color7 << endl;

执行结果如下:

5.等于与不等于

等于不等于比较简单,实现如下:

template<typename _Tp> static inline
bool operator == ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b )
{return a.val[0] == b.val[0] && a.val[1] == b.val[1] &&a.val[2] == b.val[2] && a.val[3] == b.val[3];
}template<typename _Tp> static inline
bool operator != ( const Scalar_<_Tp>& a, const Scalar_<_Tp>& b )
{return a.val[0] != b.val[0] || a.val[1] != b.val[1] ||a.val[2] != b.val[2] || a.val[3] != b.val[3];
}

6.负号

负号运算符如下:

template<typename _Tp> static inline
Scalar_<_Tp> operator - (const Scalar_<_Tp>& a)
{return Scalar_<_Tp>(saturate_cast<_Tp>(-a.val[0]),saturate_cast<_Tp>(-a.val[1]),saturate_cast<_Tp>(-a.val[2]),saturate_cast<_Tp>(-a.val[3]));
}

3、代码实战——构建纯色图像

接下来我们走进实战,为我们以后的使用打好基础吧。

大家还记不记的我们最开始学习Mat构建图像,其中有一个类别是使用Scalar构建彩色图像:

class CV_EXPORTS Mat
{
public: Mat(int rows, int cols, int type, const Scalar& s);Mat(Size size, int type, const Scalar& s);Mat(int ndims, const int* sizes, int type, const Scalar& s);Mat(const std::vector<int>& sizes, int type, const Scalar& s);};

我们一般都是需要尺寸+类型+颜色。这里,我们用到类型,主要有如下几种:

//! @name Data types
//! primitive types
//! - schar  - signed 1 byte integer
//! - uchar  - unsigned 1 byte integer
//! - short  - signed 2 byte integer
//! - ushort - unsigned 2 byte integer
//! - int    - signed 4 byte integer
//! - uint   - unsigned 4 byte integer
//! - int64  - signed 8 byte integer
//! - uint64 - unsigned 8 byte integer
//! @{
#if !defined _MSC_VER && !defined __BORLANDC__
#  if defined __cplusplus && __cplusplus >= 201103L && !defined __APPLE__
#    include <cstdint>
#    ifdef __NEWLIB__typedef unsigned int uint;
#    elsetypedef std::uint32_t uint;
#    endif
#  else
#    include <stdint.h>typedef uint32_t uint;
#  endif
#elsetypedef unsigned uint;
#endiftypedef signed char schar;#ifndef __IPL_H__typedef unsigned char uchar;typedef unsigned short ushort;
#endif#if defined _MSC_VER || defined __BORLANDC__typedef __int64 int64;typedef unsigned __int64 uint64;
#  define CV_BIG_INT(n)   n##I64
#  define CV_BIG_UINT(n)  n##UI64
#elsetypedef int64_t int64;typedef uint64_t uint64;
#  define CV_BIG_INT(n)   n##LL
#  define CV_BIG_UINT(n)  n##ULL
#endif#define CV_USRTYPE1 (void)"CV_USRTYPE1 support has been dropped in OpenCV 4.0"#define CV_CN_MAX     512
#define CV_CN_SHIFT   3
#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
#define CV_16F  7#define CV_MAT_DEPTH_MASK       (CV_DEPTH_MAX - 1)
#define CV_MAT_DEPTH(flags)     ((flags) & CV_MAT_DEPTH_MASK)#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))
#define CV_MAKE_TYPE CV_MAKETYPE#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
#define CV_8UC2 CV_MAKETYPE(CV_8U,2)
#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
#define CV_8UC4 CV_MAKETYPE(CV_8U,4)
#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))#define CV_8SC1 CV_MAKETYPE(CV_8S,1)
#define CV_8SC2 CV_MAKETYPE(CV_8S,2)
#define CV_8SC3 CV_MAKETYPE(CV_8S,3)
#define CV_8SC4 CV_MAKETYPE(CV_8S,4)
#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n))#define CV_16UC1 CV_MAKETYPE(CV_16U,1)
#define CV_16UC2 CV_MAKETYPE(CV_16U,2)
#define CV_16UC3 CV_MAKETYPE(CV_16U,3)
#define CV_16UC4 CV_MAKETYPE(CV_16U,4)
#define CV_16UC(n) CV_MAKETYPE(CV_16U,(n))#define CV_16SC1 CV_MAKETYPE(CV_16S,1)
#define CV_16SC2 CV_MAKETYPE(CV_16S,2)
#define CV_16SC3 CV_MAKETYPE(CV_16S,3)
#define CV_16SC4 CV_MAKETYPE(CV_16S,4)
#define CV_16SC(n) CV_MAKETYPE(CV_16S,(n))#define CV_32SC1 CV_MAKETYPE(CV_32S,1)
#define CV_32SC2 CV_MAKETYPE(CV_32S,2)
#define CV_32SC3 CV_MAKETYPE(CV_32S,3)
#define CV_32SC4 CV_MAKETYPE(CV_32S,4)
#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n))#define CV_32FC1 CV_MAKETYPE(CV_32F,1)
#define CV_32FC2 CV_MAKETYPE(CV_32F,2)
#define CV_32FC3 CV_MAKETYPE(CV_32F,3)
#define CV_32FC4 CV_MAKETYPE(CV_32F,4)
#define CV_32FC(n) CV_MAKETYPE(CV_32F,(n))#define CV_64FC1 CV_MAKETYPE(CV_64F,1)
#define CV_64FC2 CV_MAKETYPE(CV_64F,2)
#define CV_64FC3 CV_MAKETYPE(CV_64F,3)
#define CV_64FC4 CV_MAKETYPE(CV_64F,4)
#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n))#define CV_16FC1 CV_MAKETYPE(CV_16F,1)
#define CV_16FC2 CV_MAKETYPE(CV_16F,2)
#define CV_16FC3 CV_MAKETYPE(CV_16F,3)
#define CV_16FC4 CV_MAKETYPE(CV_16F,4)
#define CV_16FC(n) CV_MAKETYPE(CV_16F,(n))
//! @}

我们最常用的是CV_8UC3。

示例如下:

 Mat img = Mat(300, 300, CV_8UC3, Scalar(0, 0, 255));imshow("red", img);img = Mat(300, 300, CV_8UC3, Scalar(0, 255, 0));imshow("green", img);img = Mat(300, 300, CV_8UC3, Scalar(255, 0, 0));imshow("blue", img);

说在后面的话

到这,我们的基础结构就讲完了,还记不记的我们第一次讲的时候说的,这个很重要,这个是真的很重要,因为在以后的实战中,我们经常会用到这些。我只着重讲了其中四个,因为这四个是我们最常用的四个。

以前自学OpenCV的时候,好像没有人单独把这一部分拿出来详细讲解。所以我学的时候,真的是一头雾水。

但现在好啦,我已经有了很好的基础,看源码已经不是问题了。所以我要把我的理解讲给大家,把我的想法告诉大家,如果你是一个初学者,我不希望你跟我当初一样,自己一个人辛苦摸索很久。我希望,你能通过的博客,打好基础,在以后的学习和实战中,能够有个清晰地认识,看别人的代码也知道,是什么意思,就算不理解,也能自己看源码慢慢了解。

计算机视觉领域,我想很多人都跟我一样是在自学吧!这条路上的苦,或许只有我们自己知道。但是请不要担心,因为我会陪你们一直走下去。

就像我们开篇说的,当你再坚持梦想的道路上行走,全世界都是你的帮手!恰好,我就是其中一个!

【opencv4.3.0教程】06之基础结构3之Scalar_结构详解相关推荐

  1. python3 format函数_Python学习教程:Python3之字符串格式化format函数详解(上)

    Python学习教程:Python3之字符串格式化format函数详解(上) 概述 在Python3中,字符串格式化操作通过format()方法或者f'string'实现.而相比于老版的字符串格式化方 ...

  2. ElasticSearch最全详细使用教程:入门、索引管理、映射详解、索引别名、分词器、文档管理、路由、搜索详解...

    墨墨导读:之前我们分享了ElasticSearch最全详细使用教程:入门.索引管理.映射详解,本文详细介绍ElasticSearch的索引别名.分词器.文档管理.路由.搜索详解. 一.索引别名 1. ...

  3. format函数_Python学习教程:Python3之字符串格式化format函数详解(上)

    Python学习教程:Python3之字符串格式化format函数详解(上) 概述 在Python3中,字符串格式化操作通过format()方法或者f'string'实现.而相比于老版的字符串格式化方 ...

  4. Android 8.0学习(32)---Android 8.0源码目录结构详解

    Android 8.0源码目录结构详解 android的移植按如下流程:     (1)android linux 内核的普通驱动移植,让内核可以在目标平台上运行起来.     (2)正确挂载文件系统 ...

  5. java调用javascript函数_[Java教程]JavaScript函数的4种调用方法详解

    [Java教程]JavaScript函数的4种调用方法详解 0 2016-08-09 00:00:12 在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而非像C# ...

  6. ubuntu20.0.4更新至中文环境 | 具体步骤 + 图文详解

    ubuntu20.0.4更新至中文环境 | 具体步骤 + 图文详解 1.找到 Settings 即设置 2.找到Language and Region:点击下方的 Manage installed L ...

  7. php sprintf 后面补0,PHP数字前补0的自带函数sprintf 和number_format的用法(详解)

    下面小编就为大家带来一篇PHP数字前补0的自带函数sprintf 和number_format的用法(详解).小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 很多时候我们 ...

  8. Android4.0源码目录结构详解

    Android4.0源码目录结构详解 Android4.0与2.1目录差不多 alsa这块,注意external/tinyalsa下有: include/tinyalsa/asoundlib.h mi ...

  9. Pinterest 3.0 for iOS设计过程——升级iOS7设计思路详解

    Pinterest 3.0 for iOS设计过程--升级iOS7设计思路详解 时间2013-12-11 11:39:31  苹果开发中文站 原文  http://www.cocoachina.com ...

最新文章

  1. 护壁桩嵌入深度_泥浆护壁成孔灌注桩施工时泥浆的作用有哪些?
  2. String比较 运用String.equals
  3. android 原生分享界面_手机资讯:省时省力!直接在锁屏界面打开应用App
  4. linux c 数据库访问框架,linux c 开发通用结构,框架
  5. redhat enterprise linux 哪个版本好,Red Hat Enterprise Linux 版本显示中(Santiago)是啥意思?...
  6. JDK源码学习之前言
  7. 职员)2015-11-09 星期一 日志
  8. 数据挖掘前景及工作方向选择
  9. [2018.10.23 T1] 战争
  10. 基于MC1496乘法器的AM信号调制
  11. if语句 power query_判断(if)语句
  12. mysql回收站恢复数据恢复_回收站清空了如何恢复?金山数据恢复大师恢复回收站清空文件的方法...
  13. JVM 为什么使用元空间替换了永久代?
  14. pyspark读取ES数据报array错误
  15. css 细线表格,如何在Dreamweaver中制作细线表格?
  16. 分析全基因组上的蛋白信息
  17. 关于斐讯K2路由器 j.s9w.cc 劫持的问题。
  18. /phalcon.zep.c:130892: error: ‘ZEND_FE_END’ undeclared here (not in a function)
  19. vue移动端van-uploader上传图片压缩工具类
  20. Graphviz安装向导及入门指南

热门文章

  1. MySQL生成随机数(正负值掺杂)
  2. 是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
  3. 微信域名检测php,微信域名检测接口(官方api)——PHP请求示例
  4. 网络规划设计师复习笔记--网络需求分析
  5. (java)求税后工资问题
  6. 太强了哎 突然发现一个网安神器~
  7. Windows环境QtCharts安装配置说明(qt5.12.2+qtCharts5.12)
  8. 电影mysql设计_mysql – 如何设计电影数据库?
  9. 会编程的孩子有多厉害?8岁女儿写代码哄程序员爸爸开心,网友直呼:破防了!...
  10. 如何显示计算机语言栏,如何显示语言栏 显示语言栏简单步骤介绍