这个系列的目的是通过对OpenCV示例,进一步了解OpenCV函数的使用,不涉及具体原理。
目录
简介
Example运行截图
Example分析
Example代码
简介
本文记录了对OpenCV示例polar_transforms.cpp的分析。
这个示例主要演示了如何使用OpenCV,cvLogPolar和cvLinearPolar
函数将图像从二维坐标转换至极坐标,并从极坐标转换回二维坐标。
对数极坐标变换
对数极坐标图像几何学首先是从生物视觉系统的视网膜生理结构获得灵感的,具有数据压缩特性。在人工视觉系统中,与常见的笛卡尔坐标系中的图像对比,在没有减小视域大小和视网膜中心部分图像的分辨率的情况下,对数极坐标图像允许更加快速的采样率。OpenCV 采用
cvLogPolar函数实现此功能。
线性极坐标变换
其实cvLogPolar这个函数是对数极坐标变换,在计算过程中对半径做了log变换,来模拟人眼看到中间分辨率高,边缘分辨率低的效果,而在机器视觉应用中,线性极坐标变换更为常用。OpenCV采用
cvLinearPolar函数实现次功能。
CvCapture操作多媒体数据源
CvCapture是一个结构体,用来保存图像捕获的信息,就像一种数据类型(如int,char等)只是存放的内容不一样,在OpenCV中,它最大的作用就是处理视频时(程序是按一帧一帧读取),让程序读下一帧的位置,CvCapture结构中,每获取一帧后,这些信息都将被更新,获取下一帧回复。
cvLogPolar函数
将图像的二维坐标映射成极坐标
函数原型:
CVAPI(void) cvLogPolar( const CvArr* src, CvArr* dst,
CvPoint2D32f center, double M,
int flags CV_DEFAULT(CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS));
参数说明:
src: 源图像
dst: 目标图像
center: 转换变化前图像中心的二维坐标
M: 变化幅度的尺度参数
flags::插值方法
CV_INTER_LINEAR 插值方法标志
与以下标志的结合
CV_WARP_FILL_OUTLIERS 填充目标图像中的所有像素,若某些像素点对应于源图像的位置,则用0填充
CV_WARP_INVERSE_MAP 表示矩阵是由输出图像到输入图像的逆变化,可直接用于像素插值。
正变换(未设置CV_WARP_INVERSE_MAP时): dst(phi,rho) -> src(x,y)
反变换(设置CV_WARP_INVERSE_MAP): dst(x,y) ← src(phi,rho)
示例
cvLogPolar(frame,log_polar_img,
cvPoint2D32f
(frame->width >> 1,frame->height >> 1),
70
,
CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS
);
|
cvLinearPolar
函数
线性极坐标变换
函数原型:
CVAPI(void) cvLinearPolar( const CvArr* src, CvArr* dst,
CvPoint2D32f center, double maxRadius,
int flags CV_DEFAULT(CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS));
参数说明:
srcarr:原图像
dstarr:目标图像
center:图像在直角坐标系中的圆心坐标
maxRadius:逆向变换中的最大变径
flags::插值方法
CV_INTER_LINEAR 插值方法标志
与以下标志的结合
CV_WARP_FILL_OUTLIERS 填充目标图像中的所有像素,若某些像素点对应于源图像的位置,则用0填充
CV_WARP_INVERSE_MAP 表示矩阵是由输出图像到输入图像的逆变化,可直接用于像素插值。
示例
cvLinearPolar(frame,lin_polar_img,cvPoint2D32f(frame->width >> 1,frame->height >> 1),70, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS);
|
Example运行截图
从截图可以看出Linear-Polar和Log-Polar两个窗口显示了极坐标转换的结果,而最后的R
ecovered窗口则显示了从极坐标转换回二维坐标的结果。
Example分析
1.声明变量
CvCapture* capture = 0;
IplImage* log_polar_img = 0;
IplImage* lin_polar_img = 0;
IplImage* recovered_img = 0;
2.根据参数判断使用摄像头还是AVI文件创建CvCapture对象
if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
capture =
cvCaptureFromCAM( argc == 2 ? argv[1][0] -
'0'
: 0 );
else
if( argc == 2 )
capture =
cvCaptureFromAVI( argv[1] );
if( !capture )
{
fprintf(stderr,
"Could not initialize capturing...\n");
fprintf(stderr,
"Usage: %s <CAMERA_NUMBER> , or \n %s <VIDEO_FILE>\n",argv[0],argv[0]);
help();
return
-1;
}
3.声明预览窗口并移动其位置以便于观察
cvNamedWindow(
"Linear-Polar", 0 );
cvNamedWindow(
"Log-Polar", 0 );
cvNamedWindow(
"Recovered image", 0 );
cvMoveWindow(
"Linear-Polar", 20,20 );
cvMoveWindow(
"Log-Polar", 700,20 );
cvMoveWindow(
"Recovered image", 20,700 );
4.通过循环从CvCapture结构体中获取一帧并处理
for(;;)
{
... ...
}
4.1声明Iplimage对象
IplImage* frame = 0;
4.2表示从摄像头或者文件中抓取并返回一帧
frame = cvQueryFrame( capture );
if( !frame )
break;
PS:
IplImage* cvQueryFrame(CvCapture* capture);函数cvQueryFrame从摄像头或者文件中抓取一帧,然后解压并且返回这一帧。这个函数仅仅是函数cvGrabFrame和函数cvRetrieveFrame在一起调用的组合。返回的图像不可以被用户释放或者修改。
cvQueryFrame的参数是CvCapture结构的指针。用来将下一帧视频文件载入内存,返回一个对应当前帧的指针。与cvLoadImage不同的是cvLoadImage为图像分配内存空间,而cvQueryFrame使用已经在cvCapture结构中分配好的内存,
这样就没必要通过cvReleaseImage()对这个返回的图像指针进行释放,当CvCapture结构被释放后,每一帧图像对应的内存空间会被释放。
4.3如果三个全局IplImage对象没有初始化则根据当前帧进行初始化
if( !log_polar_img )
{
log_polar_img = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U, frame->nChannels );
lin_polar_img = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U, frame->nChannels );
recovered_img = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_8U, frame->nChannels );
}
4.4使用
cvLogPolar和cvLinearPolar函数实现极坐标转换,再从极坐标转换为二维坐标
cvLogPolar(frame,log_polar_img,cvPoint2D32f(frame->width >> 1,frame->height >> 1),70, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS);
cvLinearPolar(frame,lin_polar_img,cvPoint2D32f(frame->width >> 1,frame->height >> 1),70, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS);
#if 0
cvLogPolar(log_polar_img,recovered_img,cvPoint2D32f(frame->width >> 1,frame->height >> 1),70, CV_WARP_INVERSE_MAP+CV_INTER_LINEAR);
#else
cvLinearPolar(lin_polar_img,recovered_img,cvPoint2D32f(frame->width >> 1,frame->height >> 1),70, CV_WARP_INVERSE_MAP+CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS);
#endif
4.5显示预览图用于观察
cvShowImage("Log-Polar", log_polar_img );
cvShowImage("Linear-Polar", lin_polar_img );
cvShowImage("Recovered image", recovered_img );
4.6阻断程序以便于观察
cvWaitKey(0);
if( cvWaitKey(10) >= 0 )
break;
5.释放资源
cvReleaseCapture( &capture );
cvDestroyWindow("Linear-Polar");
cvDestroyWindow("Log-Polar");
cvDestroyWindow("Recovered image");
参考资料: