7 随机数发生器&绘制文字
RNG rng( 0xFFFFFFFF );//实例化一个随机数发生器对象,rng 是用数值 0xFFFFFFFF 来实例化的一个RNG对象
/// 初始化一个0矩阵
Mat image = Mat::zeros( window_height, window_width, CV_8UC3 );
/// 把它绘制到一个窗口中
imshow( window_name, image );
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 次
{
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 ); //rng.uniform(a,b) 。这指定了一个在 a 和 b 之间的均匀分布(包含 a, 但不含 b)。
if( waitKey( DELAY ) >= 0 )
{ return -1; }
}
return 0;
}
//颜色的随机选取,右移8位,16位,位的与运算,确保数值在0-255
static Scalar randomColor( RNG& rng )
{
int icolor = (unsigned) rng;
return Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
}
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)x0.05 + 0.1 指定(表示它的范围是0.1, 5.1)
字体的颜色是随机的 (记为 randomColor(rng))。
字体的粗细范围是从 1 到 10, 表示为 rng.uniform(1,10) 。
Size textsize = getTextSize("OpenCV forever!", CV_FONT_HERSHEY_COMPLEX, 3, 5, 0);
其中前四个参数都好理解:第一个参数为文本,第二个参数为文本的字体类型,第三个参数为文本大小的倍数,第四个为文本的粗细。最后一个参数是指距离文本最低点对应的y坐标,即下面红线与蓝线的距离。
8 离散傅立叶变换
对一张图像使用傅立叶变换就是将它分解成正弦和余弦两部分。也就是将图像从空间域转换到频域。任一函数都可以表示成无数个正弦和余弦函数的和的形式。傅立叶变换就是一个用来将函数分解的工具。
转换之后的频域值是复数, 因此,显示傅立叶变换之后的结果需要使用实数图像加虚数图像, 或者幅度图像加相位图像。实际的图像处理过程中,仅仅使用了幅度图像,因为幅度图像包含了原图像的几乎所有我们需要的几何信息。
当图像的尺寸是2, 3,5的整数倍时,计算速度最快。经常通过添凑新的边缘像素的方法获取最佳图像尺寸。函数 getOptimalDFTSize()返回最佳尺寸,而函数 copyMakeBorder()填充边缘像素
Mat padded; //将输入图像延扩到最佳的尺寸
int m = getOptimalDFTSize( I.rows );
int n = getOptimalDFTSize( I.cols ); // 在边缘添加0
copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));
dft(complexI, complexI); // 变换结果很好的保存在原始矩阵中
//复数转化为幅度
split(complexI, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude,(实部,虚部,输出)
Mat magI = planes[0];
傅立叶变换的幅度值范围大到不适合在屏幕上显示。高值在屏幕上显示为白点,而低值为黑点,高低值的变化无法有效分辨。为了在屏幕上凸显出高低变化的连续性,我们可以用对数尺度来替换线性尺度
magI += Scalar::all(1); // 转换到对数尺度
log(magI, magI);
剪切和重分布幅度图象限
将上一步得到的幅度图从中间划开得到四张1/4子图像,将每张子图像看成幅度图的一个象限,重新分布即将四个角点重叠到图片中心。 这样的话原点(0,0)就位移到图像中心。
归一化
有了重分布后的幅度图,但是幅度值仍然超过可显示范围[0,1] 。我们使用 normalize()函数将幅度归一化到可显示范围。
normalize(magI, magI, 0, 1, CV_MINMAX); // 将float类型的矩阵转换到可显示图像范围
// (float [0, 1]).
离散傅立叶变换的一个应用是决定图片中物体的几何方向.
9 输入输出XML和YAML文件
你的输出(和相应的输入)文件可能仅具有其中一个扩展名以及对应的文件结构。XML和YAML的串行化分别采用两种不同的数据结构: mappings (就像STL map) 和 element sequence。map中每个元素都有一个唯一的标识名供用户访问;而在sequences中你必须遍历所有的元素才能找到指定元素。
10 与 OpenCV 1 同时使用
OpenCV 2 接受按需定制。所有函数不再装入一个单一的库中。如果你仅仅需要使用OpenCV的一部分功能,使用时,你仅需要包含用到的头文件。
所有OpenCV用到的东西都被放入名字空间 cv ,你必须在名称之前冠以 cv::,或者在包含头文件后。
Mat I; //可以使用 IplImage 或 CvMat 操作符来转换 Mat 对象。
IplImage pI = I;
CvMat mI = I;
获取指针,转换就变得麻烦一点。可以通过调用 IplImage 和 CvMat 操作符来获取他们的指针。
Mat I;
IplImage* pI = &I.operator IplImage();
CvMat* mI = &I.operator CvMat();
OpenCV引进了一种智能指针。它将自动释放不再使用的对象。使用时,指针将被声明为 Ptr 模板的特化:
Ptr<IplImage> piI = &I.operator IplImage();
将C接口的数据结构转换为 Mat 时,可将其作为构造函数的参数传入,例如:
Mat K(piL), L;
L = Mat(pI);
程序支持两种模式:C和C++混合,以及纯C++。如果你宏定义了DEMO_MIXED_API_USE* ,程序将按第一种模式编译。