OpenCV生成随机数、写文字
一、学习目标
- 学会使用OpenCV的RNG接口生成随机数
- 学会使用OpenCV在图像上书写文字
二、使用CV::RNG生成随机数
在之前的教程中,我们绘制了各种几何图形,其输入参数,如坐标(cv::Point的形式)、颜色、粗细等,我们为这些参数指定了特定的值。在本教程中,我们打算为绘图参数使用随机值。此外,我们打算用大量几何图形填充图像。因为我们将以随机方式初始化它们,这个过程将是自动的,并通过使用循环来完成。
首先,我们需要初始化一个随机数生成器对象(RNG):
RNG rng( 0xFFFFFFFF );
RNG实现了一个随机数生成器。在这个例子中,rng是一个初始值为0xFFFFFFFF的对象
RNG类有两个构造函数:
cv::RNG::RNG() // 无参构造函数
和:
cv::RNG::RNG(uint64 state) // 有参构造函数
第一种形式将state设置为一些预定义的值,在当前实现中等于232-1。第二种形式将状态设置为指定的值。如果传递state=0,构造函数将使用上面的默认值来代替,以避免由所有零组成的奇异随机数序列。
接下来,有了随机数生成器后,我们便可以调用生成器对象的接口生成随机数:
int min=0;
int max=100;
Point pt1;
pt1.x = rng.uniform( min, max);
pt1.y = rng.uniform( min, max);
对于点pt1,其坐标值x和y均为随机值。
rng.uniform函数的原型为:
int cv::RNG::uniform(int a,
int b)
- 参数 a: 生成随机数的下边界,包含值a在内
- 参数 b: 生成随机数的上边界,不包括值b在内
cv::RNG::uniform函数返回[a,b)范围内均匀分布的整数随机数。该方法使用MWC算法对状态进行转换,并从范围[a, b)中返回由输入参数类型推导出的下一个指定类型的均匀分布随机数。这个函数还有另外两种重载形式,与上述函数的唯一区别就在于接受参数的类型分别为 float 和 double 类型。下面的例子说明了其中的细微差别:
RNG rng;
// a的值一直是0,因为参数类型为整型,[0, 1)之间的整数取值为集合{0}
double a = rng.uniform(0, 1);
// a1的值是区间[0, 1)之间的均匀分布的double类型的小数
double a1 = rng.uniform((double)0, (double)1);
// b的值是区间[0, 1)之间的均匀分布的float类型的小数
float b = rng.uniform(0.f, 1.f);
// c的值是区间[0, 1)之间的均匀分布的double类型的小数
double c = rng.uniform(0., 1.);
// 由于参数类型的歧义性,下面的代码可能会产生编译错误
double d = rng.uniform(0, 0.999999);
三、在图像上书写文本
OpenCV提供了 cv::putText 函数作为接口,以便在图像上书写文本。其函数原型为:
void cv::putText(InputOutputArray img,
const String & text,
Point org,
int fontFace,
double fontScale,
Scalar color,
int thickness = 1,
int lineType = LINE_8,
bool bottomLeftOrigin = false)
- 参数 img: 书写文本的图像
- 参数 text: 要绘制的文本字符串
- 参数 org: 图像中文本字符串的左下角位置
- 参数 fontFace: 字体类型,枚举自HersheyFonts
- 参数 fontScale: 字体比例系数乘以特定字体的基础大小
- 参数 color: 字体的颜色
- 参数 thickness: 用于绘制文本的线条的粗细
- 参数 lineType: 字体的线条类型
- 参数 bottomLeftOrigin: 当为true时,图像数据坐标原点位于左下角。否则,它在左上角
函数cv::putText在图像中呈现指定的文本字符串,不能使用指定字体呈现的符号将被问号替换。字体的取值见下表:
| 参数取值 | 取值说明 |
|---|---|
| FONT_HERSHEY_SIMPLEX | 正常大小 |
| FONT_HERSHEY_PLAIN | 小号无衬线字体 |
| FONT_HERSHEY_DUPLEX | 正常大小无衬线字体(比FONT_HERSHEY_SIMPLEX更复杂) |
| FONT_HERSHEY_COMPLEX | 正常大小的衬线字体 |
| FONT_HERSHEY_TRIPLEX | 正常大小衬线字体(比FONT_HERSHEY_COMPLEX更复杂) |
| FONT_HERSHEY_COMPLEX_SMALL | FONT_HERSHEY_COMPLEX的小版本 |
| FONT_HERSHEY_SCRIPT_SIMPLEX | 手写风格的字体 |
| FONT_HERSHEY_SCRIPT_COMPLEX | FONT_HERSHEY_SCRIPT_SIMPLEX的更复杂的变体 |
| FONT_ITALIC | 斜体字体 |
其中,我们常用FONT_HERSHEY_SIMPLEX字体,其它字体可以在需要的时候查询即可。
使用实例:
Mat src = Mat::zeros...;
putText( src, "OpenCV forever!", Size(100,100), FONT_HERSHEY_COMPLEX,
3,Scalar(255, 255, 255), 5, LINE_8);
在某些应用中,我们可能需要搭配 cv::getTextSize 函数使用,其原型为:
Size cv::getTextSize(const String & text,
int fontFace,
double fontScale,
int thickness,
int * baseLine)
- 参数 text: 输入文本字符串
- 参数 fontFace: 使用的字体
- 参数 fontScale: 字体比例系数乘以特定字体的基础大小
- 参数 thickness: 文本的线条的粗细
- 参数 baseLine: 基线相对于最底部文本点的y坐标函数
cv::getTextSize计算并返回包含指定文本的框的大小。下面的代码实现了将文本绘制在图像的正中间,并在文本的周围紧贴了一个矩形框:
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// 声明和初始化要显示的文本内容
String text = "Funny text inside the box";
// 定义字体、系数和字体线条的粗细
int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;
double fontScale = 2;
int thickness = 3;
// 声明并初始化一个600*800的画布,背景颜色为黑色
Mat img(600, 800, CV_8UC3, Scalar::all(0));
int baseline = 0;
// 获取在指定文本、字体、系数和线条粗细的情况下的框体大小
Size textSize = getTextSize(text, fontFace, fontScale, thickness, &baseline);
baseline += thickness;
// 定义文本的位置,使文本框处于画布的正中间。注意结合理解:
// 在绘制文本时,用到的是文本框左下角的位置(不指定bottomLeftOrigin值为True的情况),要使文本框
// 处于画布中间,则需要让文本框的左下角位置偏移文本框大小一半的尺寸,正如下面公式所示
Point textOrg((img.cols - textSize.width) / 2, (img.rows + textSize.height) / 2);
// 由于文本线条的粗细占用了一定像素,在考虑偏移时需要注意
rectangle(img, textOrg + Point(0, baseline), textOrg + Point(textSize.width, -textSize.height), Scalar(0, 0, 255));
line

本文档详细介绍了如何使用OpenCV库生成随机数并绘制文本。通过CV::RNG类生成随机数,用于在图像上绘制随机位置、颜色和大小的几何图形。同时,利用putText函数在图像上书写文本,调整字体、位置和颜色。示例代码展示了如何实现这一系列操作,包括随机线条、矩形、椭圆、多边形、圆以及文本的绘制。
最低0.47元/天 解锁文章
1584

被折叠的 条评论
为什么被折叠?



