OpenCV_tutorials 07 core module-Random generator and text with OpenCV

在这篇教程可以学会:

  • 使用随机数发生器RNG类以及如何获取服从均匀分布的随机数
  • 使用putText在OpenCV窗口上显示文本

目录

1 关于RNG类

2 putText函数

3 我的练习


1 关于RNG类

core.hpp中关于RNG类声明:

/*!
   Random Number Generator

   The class implements RNG using Multiply-with-Carry algorithm
*/
class CV_EXPORTS RNG
{
public:
    enum { UNIFORM=0, NORMAL=1 };

    RNG();
    RNG(uint64 state);
    //! updates the state and returns the next 32-bit unsigned integer random number
    unsigned next();

    operator uchar();
    operator schar();
    operator ushort();
    operator short();
    operator unsigned();
    //! returns a random integer sampled uniformly from [0, N).
    unsigned operator ()(unsigned N);
    unsigned operator ()();
    operator int();
    operator float();
    operator double();
    //! returns uniformly distributed integer random number from [a,b) range
    int uniform(int a, int b);
    //! returns uniformly distributed floating-point random number from [a,b) range
    float uniform(float a, float b);
    //! returns uniformly distributed double-precision floating-point random number from [a,b) range
    double uniform(double a, double b);
    void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false );
    //! returns Gaussian random variate with mean zero.
    double gaussian(double sigma);

    uint64 state;
};

下面结合文档opencv2refman.pdf中RNG的说明简单讲一下自己的理解。

(1)构造函数

可以看到RNG有两个构造函数,第一个构造参数设置的state是默认值0xffffffff,第二个构造参数的格式设置state为特定值,如果state为0,使用默认值(0xffffffff)避免单一的随机数序列都为0。

// Multiply-with-Carry RNG
inline RNG::RNG() { state = 0xffffffff; }
inline RNG::RNG(uint64 _state) { state = _state ? _state : 0xffffffff; }

 

(2)uinform函数

uinform函数返回[a,b)范围内的随机数,类型可以是int、float、double。需要注意的是编译器并不关心你uniform函数返回值变量的类型,它仅仅考虑的是上下限a,b的类型。因此如果你想要一个float类型的随机数,要么在整数后面放点(rng.uniform(0., 1.)),如果是常量要么使用显式的类型转换符,就像a1的初始化那样(rng.uniform((double)0, (double)1))。

其他函数暂时不做研究,本篇教程使用的主要是RNG的构造函数还有uniform函数。

2 putText函数

函数声明:

//! renders text string in the image
CV_EXPORTS_W void putText( Mat& img, const string& text, Point org,
                         int fontFace, double fontScale, Scalar color,
                         int thickness=1, int lineType=8,
                         bool bottomLeftOrigin=false );

函数说明:

参数说明:

img-图像

text-文本

org-图像中显示文本字符串的左下角位置

fontFace-文本的字体类型

fontScale-文本的尺度因子

color-文本颜色

thickness-文本线的粗细,默认值为1

lineType-文本线的类型,默认值为8

bottomLeftOrigin-如果为真,图像数据原点就在左下角,否则在左上角。默认值为false。

相关函数getTextSize()

函数声明:

//! returns bounding box of the text string
CV_EXPORTS_W Size getTextSize(const string& text, int fontFace,
                            double fontScale, int thickness,
                            CV_OUT int* baseLine);

返回文本字符串的包围矩形size.

text-输入文本字符串

fontFace-文本的字体类型

fontScale-文本的尺度因子

thickness-文本线的粗细

baseLine-输出参数,y坐标的基准线,相对于文本最底部点

3 我的练习

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int Width = 400;	//图像宽
int Height = 400;	//图像高
int xMin = 0;		//横坐标下限
int xMax = Width;	//横坐标上限
int yMin = 0;		//纵坐标下限
int yMax = Height;	//纵坐标上限
int Num = 25;		//数量

static cv::Scalar RandomColor(cv::RNG &rng);

int main()
{
	//创建空白图像
	cv::Mat src = cv::Mat::zeros(Width, Height, CV_8UC3);

	//创建RNG对象
	cv::RNG rng;

	for (int i = 0; i < Num; i++)
	{
		//产生均匀分布的两个点
		cv::Point P1;
		P1.x = rng.uniform(xMin, xMax);
		P1.y = rng.uniform(yMin, yMax);
		cv::Point P2;
		P2.x = rng.uniform(xMin, xMax);
		P2.y = rng.uniform(yMin, yMax);

		//画随机线
		const Scalar color = RandomColor(rng);
		int thickness = rng.uniform(1, 10);
		int lineType = 8;
		int shift = 0;

		cv::line(src, P1, P2, color, thickness, 8, 0);
	}
	
	//输出文本
	const std::string str = "hungry";
	cv::Point P3;
	P3.x = rng.uniform(xMin, xMax);
	P3.y = rng.uniform(yMin, yMax);
	int fontFace = rng.uniform(0, 8); 
	double fontScale = rng.uniform((double)1, (double)1.5);
	Scalar color = RandomColor(rng);
	int thickness = rng.uniform(1, 5); 
	int lineType = 8;
	bool bottomLeftOrigin = false;
	putText(src, str, P3, fontFace, fontScale, color, thickness, 8, false);

	int baseline = 0;
	cv::Size textsize = getTextSize(str, fontFace, fontScale, thickness, &baseline);
	cv::Point P4;
	P4.x = (Width -  textsize.width) / 2;
	P4.y = (Height -  textsize.height) / 2;
	putText(src, str, P4, fontFace, fontScale, color, thickness, 8, false);

	return 0;
}

//返回随机颜色
static cv::Scalar RandomColor(cv::RNG &rng)
{
	int value = (unsigned)rng;
	return cv::Scalar(value & 255, (value >> 8) & 255, (value >> 16) & 255);
}

RandomColor函数说明:

使用了operator unsigned();查看函数定义

inline RNG::operator unsigned() { return next(); }

实际调用了next()函数

inline unsigned RNG::next()
{
    state = (uint64)(unsigned)state*CV_RNG_COEFF + (unsigned)(state >> 32);
    return (unsigned)state;
}

next函数说明:

利用MWC算法更新state值的并且返回32位随机数。

MWC算法https://en.wikipedia.org/wiki/Multiply-with-carry

有时间可以研究一下。

cv::Scalar(value & 255, (value >> 8) & 255, (value >> 16) & 255)这句话是通过移位运算符分别获取B、G、R值,并且注意不要超出范围[0,255]。

以后涉及随机颜色可以采用教程中的这个函数,很简短方便。

注意这个函数前加了static,这样有什么作用呢?与普通函数有什么区别呢?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值