【OpenCV 学习】自带示例:随机数发生器&绘制文字 代码注释解析
来源:互联网 发布:淘宝报名活动有哪些 编辑:程序博客网 时间:2024/05/21 10:55
最近开始尝试学习OpenCV,确实发现了这个东西很有意思。
市面上的书基本上都是关于OpenCV 1.0版本的,包括《学习OpenCV》等,不过考虑到2.0+版本更方(sha)便(gua),我就没有去搞1.0版本,所以那个什么IplImage的,我是真的不懂,看着那么复杂的代码就头大,相较而言Mat就亲切多了。
然后就是发现OpenCV的中文文档非常不错啊(虽然是翻译的,但偷懒没去看英文,英语很捉急。。。),尤其是教程(Tutorial)那一块,示例详尽,解说简洁,没有大讲特讲原理(这些可以通过其他教材来弥补),而是尽快的跑一段程序出来,这才是最重要的!
然后就是我看到随机数发生器和绘制文字那一小节的时候,一方面看到网站上没有给出完整的代码(那个链接貌似失效了),就在网上搜了代码出来(本地文件夹里面也有,在...\opencv\sources\samples\cpp\tutorial_code\core\Matrix目录下面,Drawing_2.cpp),另一方面觉得那个demo效果很酷炫啊,尤其是最后的渐变消失的思想很有意思,另外也考虑到要稍微做点小结,不然看过印象太浅,就自己打算把哥哥随机图形的生成过程稍微解析一下,虽然教程里面已经有示例了,而且教程的前一篇就是各个图形的生成过程,但是。。。
代码先一段一段的贴,文末会附上完整的代码。
首先先大概说一下几个结构体。
Point
Point pt;pt.x = 10;pt.y = 8;就是一个二维点的坐标。
Scalar
Scalar( a, b, c )
是一个一维数组,最多有四个元素,对应的应该是像素的channel(最多可以有4个channel),一般如果使用RGB的话,用不到第四个参数就不用管它了,同样的如果是黑白的,那就只需要第一个值就够了。
所以Scalar这个类型被大量用于传递像素值。
不过需要注意的是,如果使用上述代码中的定义,a,b,c对应的分别是B,G,R,貌似OpenCV中都是使用BGR,而不是RGB的。
以下是全部的头文件、预定义、函数声明。
#include <iostream>#include <stdio.h>using namespace cv;/// Global Variablesconst int NUMBER = 100; const int DELAY = 5;const int window_width = 900;const int window_height = 600;int x_1 = -window_width/2;int x_2 = window_width*3/2;int y_1 = -window_width/2;int y_2 = window_width*3/2;/// Function headersstatic Scalar randomColor( RNG& rng );int Drawing_Random_Lines( Mat image, char* window_name, RNG rng );int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng );int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng );int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng );int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng );int Drawing_Random_Circles( Mat image, char* window_name, RNG rng );int Displaying_Random_Text( Mat image, char* window_name, RNG rng );int Displaying_Big_End( Mat image, char* window_name, RNG rng );
最后的几个函数就是核心的随机绘图函数了,下面一一的来看一下。
随机颜色函数
/** * @function randomColor * @brief Produces a random color given a random object */static Scalar randomColor( RNG& rng )//这里rng是一个随机数发生器{ int icolor = (unsigned) rng;//将随机数以无符号形式赋给icolor return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );//随机的颜色}
最后return的时候,返回的正是之前提到的Scalar,括号里的3个数分别对应B,G,R。
括号里使用了C语言的位运算,
icolor&255是与操作,事实上将icolor的低8位保留了下来,作为B channel的值
(icolor >> 8) & 255是右移再与的操作,将随机数icolor右移8位之后,保留现在的低8位
(icolor >> 16) & 255是右移再与的操作,将随机数icolor右移16位之后,保留现在的低8位
这样操作完的结果,就是根据随机的一个数,分别取了其末24位作为三个channel的值,从而就生成了一种随机的颜色。
随机直线函数
/** * @function Drawing_Random_Lines */int Drawing_Random_Lines( Mat image, char* window_name, RNG rng )//输入参数:要画直线的图像、画直线窗口的名字、随机数{ int lineType = 8; Point pt1, pt2; for( int i = 0; i < NUMBER; i++ )//NUMBER 定义为 100,表示的是要随机画的直线条数 { pt1.x = rng.uniform( x_1, x_2 ); pt1.y = rng.uniform( y_1, y_2 ); pt2.x = rng.uniform( x_1, x_2 ); pt2.y = rng.uniform( y_1, y_2 ); line( image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8 ); imshow( window_name, image ); if( waitKey( DELAY ) >= 0 ) { return -1; } } return 0;}
函数解释:
x_1,x_2,y_1,y_2均在开头定义了
const int window_width = 900;const int window_height = 600;int x_1 = -window_width/2;int x_2 = window_width*3/2;int y_1 = -window_width/2;int y_2 = window_width*3/2;
另外,代码中调用了rng.uniform(a, b),这里实质上就是产生了一个[a, b)的随机值
核心的一句
line( image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8 );意思是:
- 画一条从点 pt1 到点 pt2 的直线段
- 此线段将被画到图像 img 上
- 线的颜色由 randomColor(rng) 来定义(这里是随机颜色)
- 线的粗细由 rng.uniform(1,10) 设定(这里是随机粗细)
- 此线为8联通 (lineType = 8)
然后用imshow在图像上显示就可以了。
随机长方形函数
/** * @function Drawing_Rectangles */int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng ){ Point pt1, pt2; int lineType = 8; int thickness = rng.uniform( -3, 10 ); for( int i = 0; i < NUMBER; i++ ) { pt1.x = rng.uniform( x_1, x_2 ); pt1.y = rng.uniform( y_1, y_2 ); pt2.x = rng.uniform( x_1, x_2 ); pt2.y = rng.uniform( y_1, y_2 ); rectangle( image, pt1, pt2, randomColor(rng), MAX( thickness, -1 ), lineType ); imshow( window_name, image ); if( waitKey( DELAY ) >= 0 ) { return -1; } } return 0;}
这里其他部分和画直线的函数基本一致,核心的一句
rectangle( image, pt1, pt2, randomColor(rng), MAX( thickness, -1 ), lineType );意思是:
- 矩形将被画到图像 image 上
- 矩形两个对角顶点为 pt1 和 pt2
- 矩形的颜色为 randomColor(rng),这里是随机颜色
- 线条的粗细是MAX(thickness, -1),取得二者较大值,如果最后结果不是-1,就表示的是线条的粗细,如果线粗为 -1, 此矩形将被填充
随机椭圆函数
/** * @function Drawing_Random_Ellipses */int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng ){ int lineType = 8; for ( int i = 0; i < NUMBER; i++ ) { Point center;<span style="white-space:pre"></span>//定义了一个中心点 center.x = rng.uniform(x_1, x_2); center.y = rng.uniform(y_1, y_2); Size axes;<span style="white-space:pre"></span>//定义了一个长方形 axes.width = rng.uniform(0, 200); axes.height = rng.uniform(0, 200); double angle = rng.uniform(0, 180); ellipse( image, center, axes, angle, angle - 100, angle + 200, randomColor(rng), rng.uniform(-1,9), lineType ); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}
画椭圆的话参数稍微多一些,
ellipse( image, center, axes, angle, angle - 100, angle + 200, randomColor(rng), rng.uniform(-1,9), lineType );意思是:
- 椭圆将被画到图像 image 上
- 椭圆中心为点 center 并且大小位于矩形 axes 内
- 椭圆旋转角度为 angle
- 椭圆扩展的弧度从 angle - 100 度到 angle + 100 度
- 图形颜色为 randomColor(rng) ,即随机颜色
- 椭圆的线粗为rng.uniform(-1, 9)
随机多边形函数
/** * @function Drawing_Random_Polylines */int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng ){ int lineType = 8; for( int i = 0; i< NUMBER; i++ ) { Point pt[2][3]; pt[0][0].x = rng.uniform(x_1, x_2); pt[0][0].y = rng.uniform(y_1, y_2); pt[0][1].x = rng.uniform(x_1, x_2); pt[0][1].y = rng.uniform(y_1, y_2); pt[0][2].x = rng.uniform(x_1, x_2); pt[0][2].y = rng.uniform(y_1, y_2); pt[1][0].x = rng.uniform(x_1, x_2); pt[1][0].y = rng.uniform(y_1, y_2); pt[1][1].x = rng.uniform(x_1, x_2); pt[1][1].y = rng.uniform(y_1, y_2); pt[1][2].x = rng.uniform(x_1, x_2); pt[1][2].y = rng.uniform(y_1, y_2); const Point* ppt[2] = {pt[0], pt[1]}; int npt[] = {3, 3}; polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1,10), lineType); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}
要画随机的多边形当然得随机产生一些折点。
核心的一句:
polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1,10), lineType);意思是:
- 多边形将被画到图像 image 上
- 多边形的顶点集为 ppt
- 要绘制的多边形顶点数目为 npt
- 要绘制的多边形数量为 2
- 该多边形是封闭的
- 多边形的颜色定义为 randomColor(rng)
- 多边形的线条粗细是rng.uniform(1, 10)
随机填充多边形函数
/** * @function Drawing_Random_Filled_Polygons */int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng ){ int lineType = 8; for ( int i = 0; i < NUMBER; i++ ) { Point pt[2][3]; pt[0][0].x = rng.uniform(x_1, x_2); pt[0][0].y = rng.uniform(y_1, y_2); pt[0][1].x = rng.uniform(x_1, x_2); pt[0][1].y = rng.uniform(y_1, y_2); pt[0][2].x = rng.uniform(x_1, x_2); pt[0][2].y = rng.uniform(y_1, y_2); pt[1][0].x = rng.uniform(x_1, x_2); pt[1][0].y = rng.uniform(y_1, y_2); pt[1][1].x = rng.uniform(x_1, x_2); pt[1][1].y = rng.uniform(y_1, y_2); pt[1][2].x = rng.uniform(x_1, x_2); pt[1][2].y = rng.uniform(y_1, y_2); const Point* ppt[2] = {pt[0], pt[1]}; int npt[] = {3, 3}; fillPoly( image, ppt, npt, 2, randomColor(rng), lineType ); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}
这个函数产生的是随机的填充的多边形,核心语句基本同上:
fillPoly( image, ppt, npt, 2, randomColor(rng), lineType );意思是:
- 多边形将被画到图像 iamge 上
- 多边形的顶点集为 ppt
- 要绘制的多边形顶点数目为 npt
- 要绘制的多边形数量为 2
- 多边形的颜色定义为randomColor(rng)
/** * @function Drawing_Random_Circles */int Drawing_Random_Circles( Mat image, char* window_name, RNG rng ){ int lineType = 8; for (int i = 0; i < NUMBER; i++) { Point center; center.x = rng.uniform(x_1, x_2); center.y = rng.uniform(y_1, y_2); circle( image, center, rng.uniform(0, 300), randomColor(rng), rng.uniform(-1, 9), lineType ); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}
随机产生圆,核心语句:
circle( image, center, rng.uniform(0, 300), randomColor(rng), rng.uniform(-1, 9), lineType );意思是:
- 圆将被画到图像 image 上
- 圆心由点 center 定义
- 圆的半径为: rng.uniform(0, 300)
- 圆的颜色为: randomColor(rng)
- 线粗定义为 rng.uniform(-1, 9),当线粗为-1时,圆将被填充
随机文本函数
/** * @function Displaying_Random_Text */int Displaying_Random_Text( Mat image, char* window_name, RNG rng ){ int lineType = 8; for ( int i = 1; i < NUMBER; i++ ) { Point org; org.x = rng.uniform(x_1, x_2); org.y = rng.uniform(y_1, y_2); putText( image, "Testing text rendering", org, rng.uniform(0,8), rng.uniform(0,100)*0.05+0.1, randomColor(rng), rng.uniform(1, 10), lineType); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}
函数功能是按照随机的格式位置显示字符串“Testing test rendering”
核心的一句:
putText( image, "Testing text rendering", org, rng.uniform(0,8), rng.uniform(0,100)*0.05+0.1, randomColor(rng), rng.uniform(1, 10), lineType);意思是:
- 在 image 上绘制文字 “Testing text rendering” 。
- 文字的左下角将用点 org 指定。
- 字体参数是用一个在 [0 , 8) 之间的整数来定义。
- 字体的缩放比例是用表达式 rng.uniform(0, 100)*0.05 + 0.1 指定,表示它的范围是 [0.1, 5.1)。
- 字体的颜色是随机的 (记为 randomColor(rng))。
- 字体的粗细范围是从 1 到 10, 表示为 rng.uniform(1,10) 。
结束文本输出函数
/** * @function Displaying_Big_End */int Displaying_Big_End( Mat image, char* window_name, RNG rng ){ Size textsize = getTextSize("OpenCV forever!", CV_FONT_HERSHEY_COMPLEX, 3, 5, 0); Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2); int lineType = 8; Mat image2; for( int i = 0; i < 255; i += 2 ) { image2 = image - Scalar::all(i); putText( image2, "OpenCV forever!", org, CV_FONT_HERSHEY_COMPLEX, 3, Scalar(i, i, 255), 5, lineType ); imshow( window_name, image2 ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}
其中的for循环产生了一种渐变的效果,实现方式也很有意思。
首先,getTextSize取得了某一种特定格式字符串的尺寸(长,宽),
核心语句:
putText( image2, "OpenCV forever!", org, CV_FONT_HERSHEY_COMPLEX, 3, Scalar(i, i, 255), 5, lineType );意思是:
- 在 image2 上绘制文字 “OpenCV forever!” 。
- 文字的左下角将用点 org 指定。
- 字体固定为CV_FONT_HERSHEY_COMPLEX。
- 字体的缩放比例固定为3
- 字体的颜色是随i变化的, 最初i = 0的时候,颜色是Scalar(0, 0, 255),根据BGR对应可知,最初颜色是纯红色,之后i逐渐增大,导致的结果是字体颜色像白色渐变,最终变成纯白色
- 字体的粗细固定为5
如何实现渐变?
上面已经说了颜色的渐变实现方式,从红色渐变到白色就是同时增加另外两个channel的分量值,那其他的地方要渐变到黑色怎么做呢?
根据代码可以看到,有这么两句话:
image2 = image - Scalar::all(i);
imshow( window_name, image2 );第一句话,将Image减去 i 不断增大的全 i 图像,可以料想image必定是不断的全面往黑色靠近。。。
第二句话将减去全 i 图像的新image2显示到原来的窗口,而putText的时候是显示到image2上面的,所以
实质上,渐变效果的形成就是通过不断的刷新窗口图像达到的(博主是第一次接触到这个,感觉很新鲜的样子,见怪不怪的牛牛们莫喷。。。)
最后附上完整的代码:
#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <iostream>#include <stdio.h>using namespace cv;/// Global Variablesconst int NUMBER = 100; const int DELAY = 5;const int window_width = 900;const int window_height = 600;int x_1 = -window_width/2;int x_2 = window_width*3/2;int y_1 = -window_width/2;int y_2 = window_width*3/2;/// Function headersstatic Scalar randomColor( RNG& rng );int Drawing_Random_Lines( Mat image, char* window_name, RNG rng );int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng );int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng );int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng );int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng );int Drawing_Random_Circles( Mat image, char* window_name, RNG rng );int Displaying_Random_Text( Mat image, char* window_name, RNG rng );int Displaying_Big_End( Mat image, char* window_name, RNG rng );/** * @function main */int main( int argc, char** argv ){ int c; /// Start creating a window char window_name[] = "Drawing_2 Tutorial"; /// Also create a random object (RNG) RNG rng( 0xFFFFFFFF ); /// Initialize a matrix filled with zeros Mat image = Mat::zeros( window_height, window_width, CV_8UC3 ); /// Show it in a window during DELAY ms imshow( window_name, image ); waitKey( DELAY ); /// Now, let's draw some lines c = Drawing_Random_Lines(image, window_name, rng); if( c != 0 ) return 0; /// Go on drawing, this time nice rectangles c = Drawing_Random_Rectangles(image, window_name, rng); if( c != 0 ) return 0; /// Draw some ellipses c = Drawing_Random_Ellipses( image, window_name, rng ); if( c != 0 ) return 0; /// Now some polylines c = Drawing_Random_Polylines( image, window_name, rng ); if( c != 0 ) return 0; /// Draw filled polygons c = Drawing_Random_Filled_Polygons( image, window_name, rng ); if( c != 0 ) return 0; /// Draw circles c = Drawing_Random_Circles( image, window_name, rng ); if( c != 0 ) return 0; /// Display text in random positions c = Displaying_Random_Text( image, window_name, rng ); if( c != 0 ) return 0; /// Displaying the big end! c = Displaying_Big_End( image, window_name, rng ); if( c != 0 ) return 0; waitKey(0); return 0;}/// Function definitions/** * @function randomColor * @brief Produces a random color given a random object */static Scalar randomColor( RNG& rng ){ int icolor = (unsigned) rng; return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );}/** * @function Drawing_Random_Lines */int Drawing_Random_Lines( Mat image, char* window_name, RNG rng ){ int lineType = 8; Point pt1, pt2; for( int i = 0; i < NUMBER; i++ ) { pt1.x = rng.uniform( x_1, x_2 ); pt1.y = rng.uniform( y_1, y_2 ); pt2.x = rng.uniform( x_1, x_2 ); pt2.y = rng.uniform( y_1, y_2 ); line( image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8 ); imshow( window_name, image ); if( waitKey( DELAY ) >= 0 ) { return -1; } } return 0;}/** * @function Drawing_Rectangles */int Drawing_Random_Rectangles( Mat image, char* window_name, RNG rng ){ Point pt1, pt2; int lineType = 8; int thickness = rng.uniform( -3, 10 ); for( int i = 0; i < NUMBER; i++ ) { pt1.x = rng.uniform( x_1, x_2 ); pt1.y = rng.uniform( y_1, y_2 ); pt2.x = rng.uniform( x_1, x_2 ); pt2.y = rng.uniform( y_1, y_2 ); rectangle( image, pt1, pt2, randomColor(rng), MAX( thickness, -1 ), lineType ); imshow( window_name, image ); if( waitKey( DELAY ) >= 0 ) { return -1; } } return 0;}/** * @function Drawing_Random_Ellipses */int Drawing_Random_Ellipses( Mat image, char* window_name, RNG rng ){ int lineType = 8; for ( int i = 0; i < NUMBER; i++ ) { Point center; center.x = rng.uniform(x_1, x_2); center.y = rng.uniform(y_1, y_2); Size axes; axes.width = rng.uniform(0, 200); axes.height = rng.uniform(0, 200); double angle = rng.uniform(0, 180); ellipse( image, center, axes, angle, angle - 100, angle + 200, randomColor(rng), rng.uniform(-1,9), lineType ); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}/** * @function Drawing_Random_Polylines */int Drawing_Random_Polylines( Mat image, char* window_name, RNG rng ){ int lineType = 8; for( int i = 0; i< NUMBER; i++ ) { Point pt[2][3]; pt[0][0].x = rng.uniform(x_1, x_2); pt[0][0].y = rng.uniform(y_1, y_2); pt[0][1].x = rng.uniform(x_1, x_2); pt[0][1].y = rng.uniform(y_1, y_2); pt[0][2].x = rng.uniform(x_1, x_2); pt[0][2].y = rng.uniform(y_1, y_2); pt[1][0].x = rng.uniform(x_1, x_2); pt[1][0].y = rng.uniform(y_1, y_2); pt[1][1].x = rng.uniform(x_1, x_2); pt[1][1].y = rng.uniform(y_1, y_2); pt[1][2].x = rng.uniform(x_1, x_2); pt[1][2].y = rng.uniform(y_1, y_2); const Point* ppt[2] = {pt[0], pt[1]}; int npt[] = {3, 3}; polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1,10), lineType); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;} /** * @function Drawing_Random_Filled_Polygons */int Drawing_Random_Filled_Polygons( Mat image, char* window_name, RNG rng ){ int lineType = 8; for ( int i = 0; i < NUMBER; i++ ) { Point pt[2][3]; pt[0][0].x = rng.uniform(x_1, x_2); pt[0][0].y = rng.uniform(y_1, y_2); pt[0][1].x = rng.uniform(x_1, x_2); pt[0][1].y = rng.uniform(y_1, y_2); pt[0][2].x = rng.uniform(x_1, x_2); pt[0][2].y = rng.uniform(y_1, y_2); pt[1][0].x = rng.uniform(x_1, x_2); pt[1][0].y = rng.uniform(y_1, y_2); pt[1][1].x = rng.uniform(x_1, x_2); pt[1][1].y = rng.uniform(y_1, y_2); pt[1][2].x = rng.uniform(x_1, x_2); pt[1][2].y = rng.uniform(y_1, y_2); const Point* ppt[2] = {pt[0], pt[1]}; int npt[] = {3, 3}; fillPoly( image, ppt, npt, 2, randomColor(rng), lineType ); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}/** * @function Drawing_Random_Circles */int Drawing_Random_Circles( Mat image, char* window_name, RNG rng ){ int lineType = 8; for (int i = 0; i < NUMBER; i++) { Point center; center.x = rng.uniform(x_1, x_2); center.y = rng.uniform(y_1, y_2); circle( image, center, rng.uniform(0, 300), randomColor(rng), rng.uniform(-1, 9), lineType ); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}/** * @function Displaying_Random_Text */int Displaying_Random_Text( Mat image, char* window_name, RNG rng ){ int lineType = 8; for ( int i = 1; i < NUMBER; i++ ) { Point org; org.x = rng.uniform(x_1, x_2); org.y = rng.uniform(y_1, y_2); putText( image, "Testing text rendering", org, rng.uniform(0,8), rng.uniform(0,100)*0.05+0.1, randomColor(rng), rng.uniform(1, 10), lineType); imshow( window_name, image ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}/** * @function Displaying_Big_End */int Displaying_Big_End( Mat image, char* window_name, RNG rng ){ Size textsize = getTextSize("OpenCV forever!", CV_FONT_HERSHEY_COMPLEX, 3, 5, 0); Point org((window_width - textsize.width)/2, (window_height - textsize.height)/2); int lineType = 8; Mat image2; for( int i = 0; i < 255; i += 2 ) { image2 = image - Scalar::all(i); putText( image2, "OpenCV forever!", org, CV_FONT_HERSHEY_COMPLEX, 3, Scalar(i, i, 255), 5, lineType ); imshow( window_name, image2 ); if( waitKey(DELAY) >= 0 ) { return -1; } } return 0;}
再次强烈推荐OpenCV的文档!
- 【OpenCV 学习】自带示例:随机数发生器&绘制文字 代码注释解析
- OpenCV学习:随机数发生器&绘制文字
- 学习OpenCV(七)——随机数发生器和绘制文字
- opencv 2.x学习笔记(十)随机数发生器、绘制文字
- opencv c++函数 基础7 随机数发生器&绘制文字
- 随机数发生器&绘制文字-----学习记录(6)
- 随机数发生器&绘制文字---opencv2.4.11
- core核心模块--随机数发生器&文字绘制
- opencv学习日常之随机数发生器RNG
- OpenCV的随机数发生器
- opencv随机数发生器RNG
- OpenCV之core 模块. 核心功能(2)基本绘图 随机数发生器&绘制文字 离散傅立叶变换 输入输出XML和YAML文件 与 OpenCV 1 同时使用
- Node.js基础代码示例,带注释
- 解析Qt自带的Style示例
- 解析Qt自带的Style示例
- 解析Qt自带的Style示例
- 解析Qt自带的Style示例
- 解析Qt自带的Style示例
- Android四大核心组件之Activity2学习心得
- deepin2014、startos5.1试用
- Android Service学习之本地服务
- Android:onNewIntent()触发机制及注意事项
- c++备注事项:
- 【OpenCV 学习】自带示例:随机数发生器&绘制文字 代码注释解析
- 关于模板页中文本款ID的客户端获取问题
- Robotium学习笔记三
- ActivityGroup子Activity获得焦点返回键的处理
- HDU 1176 免费馅饼
- HDUJ 1231 最大连续子序列
- 购物车技术原理
- POJ, 1330 Nearest Common Ancestors(找出两个节点最近的公共节点——BFS)
- freemarker 整理手册