最近看美剧 《TELL LIE TO ME》,对里边的一些东西非常感兴趣,具体就是摄像头目录然后会自动截取眼睛的图像到另外一个屏幕,想用OPENCV实现下。
自己开始使用OPENCV对很多东西都不怎么熟悉,可以使用OPENCV既有的算法检测到眼睛,然后就差截取眼睛部分的图像了,在网络上找了很多,大概只有一种可用的方法,具体如下:
使用的函数只有两个:
//
CvMat* cvGetSubRect(const CvArr* arr, CvMat* submat, CvRect rect); /* arr Input array submat Pointer to the resultant sub-array header rect Zero-based coordinates of the rectangle of interest The function returns header, corresponding to a specified rectangle of the input array. In other words, it allows the user to treat a rectangular part of input array as a stand-alone array. ROI is taken into account by the function so the sub-array of ROI is actually extracted. */
|
从结构arr中获取rect指向的内容,然后将这些内容复制到submat结构中,表达式采用链式表达,把内容复制到submat后,并返回submat的地址,使用过opencv的人都知道, CvArr不是一种具体的结构,可以使图像、矩阵等,具体图像位置有CvRect结构决定。
typedef struct CvRect { int x; //矩形的起始点X坐标 int y; //矩形的起始点Y坐标 int width; //矩形的宽 int height; //矩形的高 } CvRect;
|
使用完cvGetSubRect()函数后,截取的图像就被复制到submat结构中了,下一步需要做的是从CvMat结构中转换数据到IPlImage类型。使用如下函数:
IplImage* cvGetImage(const CvArr* arr, IplImage* imageHeader);
/* arr Input array imageHeader Pointer to IplImage structure used as a temporary buffer */
|
这同样是一个链式表达,arr参数就是使用cvGetSubRect()函数中的submat参数对应的参数,IplImage*参数就对应实际图像结构的指针,同样链式表达也会返回这个结构的指针。
使用如上的函数就可以完成图像的截取。
基于上述的链式表达,可以使用一条语句完成,如:
cvGetImage(cvGetSubRect(frame_copy,&test,Rect_eys),eye_img);
具体参数不做详细解释了。
这里需要注意一些常犯的错误:
1.CvMat* cvGetSubRect(const CvArr* arr, CvMat* submat, CvRect rect);
这个函数中的 submat,一定要申请相应的空间在传递参数,实际的数据会复制到相应指针指向的空间,这里我犯了错误。
2. CvMat* cvGetSubRect(const CvArr* arr, CvMat* submat, CvRect rect);
函数中的参数rect需要注意,它制定的复制数据的位置的大小,可能会发生数据越界,需要额外注意。比如实际图像是400x300,而你制定的起点是(350,250),而宽是100,高是100,这时候,矩形的另外一个顶点就是(450,350),实际图像数据结构中并没有这些空间,就造成越界,我这样的初学者就犯了这样的错误。
阅读(8457) | 评论(0) | 转发(0) |