Download presentation
Presentation is loading. Please wait.
1
Intel® 开源计算机视觉库OpenCV
2
OpenCV参考手册 OpenCV概述 FAQ中文 CxCore中文参考手册 基础结构 数组操作 动态结构 绘图函数
数据保存和运行时类型信息 其它混合函数 错误处理和系统函数 机器学习中文参考手册 CvAux中文参考手册 CvvImage类参考手册 CvImage类参考手册 CvImage中的陷阱和BUG Cv中文参考手册 图像处理 结构分析 运动分析与对象跟踪 模式识别 照相机定标和三维重建 HighGUI中文参考手册 HighGUI概述 简单图形界面 读取与保存图像 视频读写函数 实用函数与系统函数 OpenCV 编码样式指南(阅读OpenCV代码前必读)
3
OpenCV概述 目录 1 什么是OpenCV 2 重要特性 3 谁创建了它 4 新特征 5 从哪里下载 OpenCV
8 中文翻译者
4
什么是OpenCV OpenCV是Intel®开源计算机视觉库。它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法。
5
重要特性 OpenCV 拥有包括 300 多个C函数的跨平台的中、高层 API。它不依赖于其它的外部库——尽管也可以使用某些外部库。
OpenCV 对非商业应用和商业应用都是免费(FREE)的。(细节参考 license)。 OpenCV 为Intel® Integrated Performance Primitives (IPP) 提供了透明接口。 这意味着如果有为特定处理器优化的的 IPP 库, OpenCV 将在运行时自动加载这些库。 更多关于 IPP 的信息请参考:
6
谁创建了它 作者列表可以在文件AUTHORS中找到。
此外,还有很多人给出了建议、补丁、BUG 报告等等。一个不太完整的列表在文件THANKS中。
7
新特征 请参考OpenCVChangeLog
8
从哪里下载 OpenCV 访问 。如果有问题,在 Google ( )中输入 "OpenCV" 搜索。
9
如果在安装/运行/使用 OpenCV 中遇到问题
阅读FAQ中文 在 OpenCV 邮件列表 ( )中搜索。 加入到 yahoo group 上的 OpenCV 邮件列表中(如何加入请参考 FAQs),并发送你的问题到邮件列表中。(这个邮件列表可能会迁移到OpenCV's SourceForge site) 参考 OpenCV 的例子代码,阅读参考手册 :)
10
OpenCV参考手册 CxCore中文参考手册 Cv中文参考手册 CvAux中文参考手册 HighGUI中文参考手册
11
中文翻译者 于仕琪,中科院自动化所自由软件协会 HUNNISH,阿须数码
取自"
12
FAQ中文 目录 1 安装配置问题 2 使用库的技术问题 3 中文翻译者 1.1 缺少highgui100.dll 2.1 视频读写出现问题
2.2 怎么访问图像像素 2.3 如何访问矩阵元素? 2.4 如何在 OpenCV 中处理我自己的数据 2.5 如何读入和显示图像 2.6 如何检测和处理轮廓线 2.7 如何用 OpenCV 来定标摄像机 3 中文翻译者
13
安装配置问题 缺少highgui100.dll 是由于highgui100.dll所在目录(一般为C:\Program Files\OpenCV\bin)没有添加到系统环境变量所致,请参考VC6下安装与配置#配置Windows环境变量
14
使用库的技术问题 视频读写出现问题 请参考:视频读写概述。
15
怎么访问图像像素 (坐标是从0开始的,并且是相对图像原点的位置。图像原点或者是左上角 (img->origin=IPL_ORIGIN_TL) 或者是左下角 (img->origin=IPL_ORIGIN_BL) ) 假设有 8-bit 1-通道的图像 I (IplImage* img): I(x,y) ~ ((uchar*)(img->imageData + img->widthStep*y))[x]
16
假设有 8-bit 3-通道的图像 I (IplImage* img):
I(x,y)blue ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3] I(x,y)green ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3+1] I(x,y)red ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3+2] 例如,给点 (100,100) 的亮度增加 30 ,那么可以这样做: CvPoint pt = {100,100}; ((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3] += 30; ((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3+1] += 30; ((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3+2] += 30; 或者更高效地: CvPoint pt = {100,100}; uchar* temp_ptr = &((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3]; temp_ptr[0] += 30; temp_ptr[1] += 30; temp_ptr[2] += 30;
17
假设有 32-bit 浮点数, 1-通道 图像 I (IplImage* img):
I(x,y) ~ ((float*)(img->imageData + img->widthStep*y))[x]
18
现在,一般的情况下,假设有 N-通道,类型为 T 的图像:
I(x,y)c ~ ((T*)(img->imageData + img->widthStep*y))[x*N + c] 你可以使用宏 CV_IMAGE_ELEM( image_header, elemtype, y, x_Nc ) I(x,y)c ~ CV_IMAGE_ELEM( img, T, y, x*N + c ) 也有针对各种图像(包括 4 通道图像)和矩阵的函数(cvGet2D, cvSet2D), 但是它们非常慢。
19
如何访问矩阵元素? 方法是类似的(下面的例子都是针对 0 起点的列和行)
设有 32-bit 浮点数的实数矩阵 M (CvMat* mat): M(i,j) ~ ((float*)(mat->data.ptr + mat->step*i))[j]
20
设有 64-bit 浮点数的复数矩阵 M (CvMat* mat):
Re M(i,j) ~ ((double*)(mat->data.ptr + mat->step*i))[j*2] Im M(i,j) ~ ((double*)(mat->data.ptr + mat->step*i))[j*2+1]
21
M(i,j) ~ CV_MAT_ELEM( mat, float, i, j ),
对单通道矩阵,有宏 CV_MAT_ELEM( matrix, elemtype, row, col ), 例如对 32-bit 浮点数的实数矩阵: M(i,j) ~ CV_MAT_ELEM( mat, float, i, j ), 例如,这儿是一个 3x3 单位矩阵的初始化: CV_MAT_ELEM( mat, float, 0, 0 ) = 1.f; CV_MAT_ELEM( mat, float, 0, 1 ) = 0.f; CV_MAT_ELEM( mat, float, 0, 2 ) = 0.f; CV_MAT_ELEM( mat, float, 1, 0 ) = 0.f; CV_MAT_ELEM( mat, float, 1, 1 ) = 1.f; CV_MAT_ELEM( mat, float, 1, 2 ) = 0.f; CV_MAT_ELEM( mat, float, 2, 0 ) = 0.f; CV_MAT_ELEM( mat, float, 2, 1 ) = 0.f; CV_MAT_ELEM( mat, float, 2, 2 ) = 1.f;
22
如何在 OpenCV 中处理我自己的数据 设你有 300x bit 浮点数 image/array, 也就是对一个有 个元素的数组。 int cols = 300, rows = 200; float* myarr = new float[rows*cols]; // 第一步,初始化 CvMat 头 CvMat mat = cvMat( rows, cols, CV_32FC1, // 32 位浮点单通道类型 myarr // 用户数据指针(数据没有被复制) ); // 第二步,使用 cv 函数, 例如计算 l2 (Frobenius) 模 double norm = cvNorm( &mat, 0, CV_L2 ); ... delete myarr 其它情况在参考手册中有描述。 见 cvCreateMatHeader,cvInitMatHeader,cvCreateImageHeader, cvSetData 等 ;
23
如何读入和显示图像 /* usage: prog <image_name> */ #include "cv.h"
#include "highgui.h" int main( int argc, char** argv ) { IplImage* img; if( argc == 2 && (img = cvLoadImage( argv[1], 1)) != 0 ) cvNamedWindow( "Image view", 1 ); cvShowImage( "Image view", img ); cvWaitKey(0); // 非常重要,内部包含事件处理循环 cvDestroyWindow( "Image view" ); cvReleaseImage( &img ); return 0; } return -1;
24
如何检测和处理轮廓线 /*在程序里找寻矩形*/ #ifdef _CH_ #pragma package <opencv>
#endif#ifndef _EiC #include "cv.h“ #include "highgui.h“ #include <stdio.h> #include <math.h> #include <string.h> #endifint thresh = 50; IplImage* img = 0; IplImage* img0 = 0; CvMemStorage* storage = 0; CvPoint pt[4]; const char* wndname = "Square Detection Demo";
25
// helper function: // finds a cosine of angle between vectors // from pt0->pt1 and from pt0->pt2 double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 ) { double dx1 = pt1->x - pt0->x; double dy1 = pt1->y - pt0->y; double dx2 = pt2->x - pt0->x; double dy2 = pt2->y - pt0->y; return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); } // returns sequence of squares detected on the image. // the sequence is stored in the specified memory storage CvSeq* findSquares4( IplImage* img, CvMemStorage* storage ) CvSeq* contours; int i, c, l, N = 11; CvSize sz = cvSize( img->width & -2, img->height & -2 ); IplImage* timg = cvCloneImage( img ); // make a copy of input image IplImage* gray = cvCreateImage( sz, 8, 1 ); IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 ); IplImage* tgray; CvSeq* result; double s, t;
26
// create empty sequence that will contain points –
// 4 points per square (the square's vertices) CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage ); // select the maximum ROI in the image // with the width and height divisible by 2 cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height )); // down-scale and upscale the image to filter out the noise cvPyrDown( timg, pyr, 7 ); cvPyrUp( pyr, timg, 7 ); tgray = cvCreateImage( sz, 8, 1 ); // find squares in every color plane of the image for( c = 0; c < 3; c++ ) { // extract the c-th color plane cvSetImageCOI( timg, c+1 ); cvCopy( timg, tgray, 0 );
27
// try several threshold levels
for( l = 0; l < N; l++ ) { // hack: use Canny instead of zero threshold level. // Canny helps to catch squares with gradient shading if( l == 0 ) {// apply Canny. Take the upper threshold from slider // and set the lower to 0 (which forces edges merging) cvCanny( tgray, gray, 0, thresh, 5 ); // dilate canny output to remove potential // holes between edge segments cvDilate( gray, gray, 0, 1 ); } else { // apply threshold if l!=0: // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY ); }
28
// find contours and store them all as a list cvFindContours( gray, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) ); // test each contour while( contours ) { // approximate contour with accuracy proportional // to the contour perimeter result = cvApproxPoly( contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 ); // square contours should have 4 vertices after approximation // relatively large area (to filter out noisy contours) // and be convex. // Note: absolute value of an area is used because // area may be positive or negative - in accordance with the // contour orientation
29
if( result->total == 4 &&fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 && cvCheckContourConvexity(result) ) { s = 0; for( i = 0; i < 5; i++ ) { // find minimum angle between joint // edges (maximum of cosine) if( i >= 2 ) { t = fabs(angle( (CvPoint*)cvGetSeqElem( result, i ), (CvPoint*)cvGetSeqElem( result, i-2 ), (CvPoint*)cvGetSeqElem( result, i-1 ))); s = s > t ? s : t; }
30
// if cosines of all angles are small
// (all angles are ~90 degree) then write quandrange // vertices to resultant sequence if( s < 0.3 ) for( i = 0; i < 4; i++ ) cvSeqPush( squares, (CvPoint*)cvGetSeqElem( result, i )); } // take the next contour contours = contours->h_next; // release all the temporary images cvReleaseImage( &gray ); cvReleaseImage( &pyr ); cvReleaseImage( &tgray ); cvReleaseImage( &timg ); return squares;
31
// the function draws all the squares in the image
void drawSquares( IplImage* img, CvSeq* squares ) { CvSeqReader reader; IplImage* cpy = cvCloneImage( img ); int i; // initialize reader of the sequence cvStartReadSeq( squares, &reader, 0 ); // read 4 sequence elements at a time (all vertices of a square) for( i = 0; i < squares->total; i += 4 ) { CvPoint* rect = pt; int count = 4; // read 4 vertices memcpy( pt, reader.ptr, squares->elem_size ); CV_NEXT_SEQ_ELEM( squares->elem_size, reader ); memcpy( pt + 1, reader.ptr, squares->elem_size ); CV_NEXT_SEQ_ELEM( squares->elem_size, reader ); memcpy( pt + 2, reader.ptr, squares->elem_size ); CV_NEXT_SEQ_ELEM( squares->elem_size, reader ); memcpy( pt + 3, reader.ptr, squares->elem_size ); CV_NEXT_SEQ_ELEM( squares->elem_size, reader ); // draw the square as a closed polyline cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 ); } // show the resultant image cvShowImage( wndname, cpy ); cvReleaseImage( &cpy ); }
32
void on_trackbar( int a )
{ if( img ) drawSquares( img,findSquares4( img,storage ) ); } char* names[] = { "pic1.png", "pic2.png", "pic3.png", "pic4.png", "pic5.png", "pic6.png", 0 };
33
int main(int argc, char** argv)
{ int i, c; // create memory storage that will contain all the dynamic data storage = cvCreateMemStorage(0); for( i = 0; names[i] != 0; i++ ) { // load i-th image img0 = cvLoadImage( names[i], 1 ); if( !img0 ) { printf("Couldn't load %s\n", names[i] ); continue; } img = cvCloneImage( img0 ); // create window and a trackbar (slider) with parent "image" and set callback // (the slider regulates upper threshold, passed to Canny edge detector) cvNamedWindow( wndname, 1 ); cvCreateTrackbar( "canny thresh", wndname, &thresh, 1000, on_trackbar ); // force the image processing on_trackbar(0); // wait for key. // Also the function cvWaitKey takes care of event processing c = cvWaitKey(0); // release both images cvReleaseImage( &img ); cvReleaseImage( &img0 ); // clear memory storage - reset free space position cvClearMemStorage( storage ); if( c == 27 ) break; } cvDestroyWindow( wndname ); return 0; } #ifdef _EiC main(1,"squares.c"); #endif
34
如何用 OpenCV 来定标摄像机 可以使用\OpenCV\samples\c目录下的calibration.cpp这个程序,程序的输入支持USB摄像机,avi文件或者图片 1。使用说明 a.输入为图片时: // example command line (for copy-n-paste): // calibration -w 6 -h 8 -s 2 -n 10 -o camera.yml -op -oe [<list_of_views.txt>] /* The list of views may look as following (discard the starting and ending separators): view000.png view001.png #view002.png view003.png view010.png one_extra_view.jpg that is, the file will contain 6 lines, view002.png will not be used for calibration, other ones will be (those, in which the chessboard pattern will be found)
35
b.输入为摄像机或者avi文件时 "When the live video from camera is used as input, the following hot-keys may be used:\n" " <ESC>, 'q' - quit the program\n" " 'g' - start capturing images\n" " 'u' - switch undistortion on/off\n";
36
C.输入参数说明 "Usage: calibration\n" " -w <board_width> # the number of inner corners per one of board dimension\n" " -h <board_height> # the number of inner corners per another board dimension\n" " [-n <number_of_frames>] # the number of frames to use for calibration\n" " # (if not specified, it will be set to the number\n" " # of board views actually available)\n" " [-d <delay>] # a minimum delay in ms between subsequent attempts to capture a next view\n" " # (used only for video capturing)\n" " [-s <square_size>] # square size in some user-defined units (1 by default)\n" " [-o <out_camera_params>] # the output filename for intrinsic [and extrinsic] parameters\n" " [-op] # write detected feature points\n" " [-oe] # write extrinsic parameters\n" " [-zt] # assume zero tangential distortion\n" " [-a <aspect_ratio>] # fix aspect ratio (fx/fy)\n" " [-p] # fix the principal point at the center\n" " [-v] # flip the captured images around the horizontal axis\n" " [input_data] # input data, one of the following:\n" " # - text file with a list of the images of the board\n" " # - name of video file with a video of the board\n" " # if input_data not specified, a live view from the camera is used\n" 2.经多次使用发现,不指定 -p参数时计算的结果误差较大,主要表现在对u0,v0的估计误差较大,因此建议使用时加上-p参数
37
中文翻译者 于仕琪,中科院自动化所自由软件协会 HUNNISH,阿须数码
取自"
38
CxCore中文参考手册 基础结构 数组操作 动态结构 绘图函数 数据保存和运行时类型信息 其它混合函数 错误处理和系统函数
39
Cxcore基础结构 目录 1 CvPoint 2 CvPoint2D32f 3 CvPoint3D32f 4 CvSize
5 CvSize2D32f 6 CvRect 7 CvScalar 8 CvTermCriteria 9 CvMat 10 CvMatND 11 CvSparseMat 12 IplImage 13 CvArr
40
CvPoint 二维坐标系下的点,类型为整型 typedef struct CvPoint {
int x; /* X坐标, 通常以0为基点 */ int y; /* y坐标, 通常以0为基点 */ } CvPoint; /* 构造函数 */ inline CvPoint cvPoint( int x, int y ); /* 从 CvPoint2D32f类型转换得来 */ inline CvPoint cvPointFrom32f( CvPoint2D32f point )
41
CvPoint2D32f 二维坐标下的点,类型为浮点 typedef struct CvPoint2D32f {
float x;/* X坐标, 通常以0为基点*/ float y; /* Y坐标, 通常以0为基点*/ } CvPoint2D32f; /* 构造函数 */ inline CvPoint2D32f cvPoint2D32f( double x, double y ); /* 从CvPoint转换来 */ inline CvPoint2D32f cvPointTo32f( CvPoint point );
42
CvPoint3D32f 三维坐标下的点,类型为浮点 typedef struct CvPoint3D32f
{ float x; /* x-坐标, 通常基于0 */ float y; /* y-坐标, 通常基于0 */ float z; /* z-坐标, 通常基于0 */ } CvPoint3D32f; /* 构造函数 */ inline CvPoint3D32f cvPoint3D32f( double x, double y, double z );
43
CvSize 矩形框大小,以像素为精度 typedef struct CvSize { int width; /* 矩形宽 */
int height; /* 矩形高 */ } CvSize; /* 构造函数 */ inline CvSize cvSize( int width, int height );
44
CvSize2D32f 以亚像素精度标量矩形框大小 typedef struct CvSize2D32f {
float width; /* 矩形宽 */ float height; /* 矩形高 */ } CvSize2D32f; /* 构造函数*/ inline CvSize2D32f cvSize2D32f( double width, double height ); { CvSize2D32f s; s.width = (float)width; s.height = (float)height; return s; }
45
CvRect 矩形框的偏移和大小 typedef struct CvRect { int x; /* 方形的最左角的x-坐标 */
int y; /* 方形的最上或者最下角的y-坐标 */ int width; /* 宽 */ int height; /* 高 */ } CvRect; /* 构造函数*/ inline CvRect cvRect( int x, int y, int width, int height );
46
CvScalar 可存放在1-,2-,3-,4-TUPLE类型的捆绑数据的容器 typedef struct CvScalar
{ double val[4] } CvScalar; /* 构造函数:用val0初始化val[0]用val1初始化val[1], 以此类推*/ inline CvScalar cvScalar( double val0, double val1=0, double val2=0, double val3=0 ); /* 构造函数:用val0123初始化所有val[0]...val[3] */ inline CvScalar cvScalarAll( double val0123 ); /* 构造函数:用val0初始化val[0],用0初始val[1],val[2],val[3] */ inline CvScalar cvRealScalar( double val0 );
47
CvTermCriteria 迭代算法的终止准则 #define CV_TERMCRIT_ITER 1
#define CV_TERMCRIT_NUMBER CV_TERMCRIT_ITER #define CV_TERMCRIT_EPS 2 typedef struct CvTermCriteria { int type; /* CV_TERMCRIT_ITER 和CV_TERMCRIT_EPS二值之一,或者二者的组合 */ int max_iter; /* 最大迭代次数 */ double epsilon; /* 结果的精确性 */ } CvTermCriteria; /* 构造函数 */ inline CvTermCriteria cvTermCriteria( int type, int max_iter, double epsilon ); 在满足max_iter和epsilon的条件下检查终止准则并将其转换使得type=CV_TERMCRIT_ITER+CV_TERMCRIT_EPS */ CvTermCriteria cvCheckTermCriteria( CvTermCriteria criteria, double default_eps, int default_max_iters );
48
CvMat多通道矩阵
49
CvMatND 多维、多通道密集数组
50
CvSparseMat 多维、多通道稀疏数组
51
IplImage IPL 图像头
52
IplImage结构来自于 Intel Image Processing Library(是其本身所具有的)。OpenCV 只支持其中的一个子集:
alphaChannel 在OpenCV中被忽略。 colorModel 和channelSeq 被OpenCV忽略。OpenCV颜色转换的唯一函数 cvCvtColor把原图像的颜色空间的目标图像的颜色空间作为一个参数。 dataOrder 必须是IPL_DATA_ORDER_PIXEL (颜色通道是交叉存取),然而平面图像的被选择通道可以被处理,就像COI(感兴趣的通道)被设置过一样。 align 是被OpenCV忽略的,而用 widthStep 去访问后继的图像行。 不支持maskROI 。处理MASK的函数把他当作一个分离的参数。MASK在 OpenCV 里是 8-bit,然而在 IPL他是 1-bit。 tileInfo 不支持。 BorderMode和BorderConst是不支持的。每个 OpenCV 函数处理像素的邻近的像素,通常使用单一的固定代码边际模式。 除了上述限制,OpenCV处理ROI有不同的要求。要求原图像和目标图像的尺寸或 ROI的尺寸必须(根据不同的操作,例如cvPyrDown 目标图像的宽(高)必须等于原图像的宽(高)除以2 ±1)精确匹配,而IPL处理交叉区域,如图像的大小或ROI大小可能是完全独立的。 [编辑]
53
CvArr 不确定数组 typedef void CvArr; CvArr* 仅仅是被用于作函数的参数,用于指示函数接收的数组类型可以不止一个,如 IplImage*, CvMat* 甚至 CvSeq*. 最终的数组类型是在运行时通过分析数组头的前4 个字节判断。 取自"
54
Cxcore数组操作
Similar presentations