cvUndistort2()和cvRemap()崩溃 [英] cvUndistort2 () and cvRemap () crash

查看:311
本文介绍了cvUndistort2()和cvRemap()崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做Bradski的Learning OpenCV的例子11-1。很遗憾,给定的示例在我的计算机上不起作用。



程序应该使用棋盘校准摄像机,然后从摄像机输出未失真的视频输出。



校准部件工作正常,当程序尝试解除图像失真时出现问题。我试过两个cvUndistort2()和cvRemap(),在这两种情况下输出窗口冻结和程序崩溃,所以我必须强制关闭它。



这里是代码:

  #include< cv.h> 
#include< highgui.h>
#include< stdio.h>
#include< stdlib.h>
#include< iostream>

int n_boards = 0;
int board_dt = 15;
int board_w;
int board_h;
int main(int argc,char * argv []){

CvCapture * capture;
/ *
if(argc!= 5){
printf(\\\
ERROR:Wrong number of input parameters);
help();
return -1;
}
* /

board_w = 7; // atoi(argv [1]);
board_h = 7; // atoi(argv [2]);
n_boards = 8; // atoi(argv [3]);

CvSize board_sz = cvSize(board_w,board_h);
capture = cvCreateCameraCapture(0);
if(!capture){printf(\\\
Couldn't open the camera\\\
); return -1;}

cvNamedWindow(Calibration);
IplImage * image = cvQueryFrame(capture);

int board_n = board_w * board_h;

//分配存储
CvMat * image_points = cvCreateMat(n_boards * board_n,2,CV_32FC1);
CvMat * object_points = cvCreateMat(n_boards * board_n,3,CV_32FC1);
CvMat * point_counts = cvCreateMat(n_boards,1,CV_32SC1);
CvMat * intrinsic_matrix = cvCreateMat(3,3,CV_32FC1);
CvMat * distortion_coeffs = cvCreateMat(5,1,CV_32FC1);

CvPoint2D32f * corners = new CvPoint2D32f [board_n];
int corner_count;
int successes = 0;
int step,frame = 0;

IplImage * gray_image = cvCreateImage(cvGetSize(image),8,1); //子像素

//捕获角色视图循环直到我们的GOT n_boards
//成功的CAPTURES(所有的角色都被发现)
while(成功< n_boards){
//跳过每一个board_dt帧以允许用户移动棋盘
if %board_dt)== 0){
//查找棋盘角:
int found = cvFindChessboardCorners(
image,board_sz,corner,& corner_count,
CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS
);

//获取这些角落的子像素精度
cvCvtColor(image,gray_image,CV_BGR2GRAY);
cvFindCornerSubPix(gray_image,corners,corner_count,
cvSize(11,11),cvSize(-1,-1),cvTermCriteria(
CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,30,0.1)

//绘制
cvDrawChessboardCorners(image,board_sz,corner,
corner_count,found);
cvShowImage(Calibration,image);

//如果我们有一个好的板子,将它添加到我们的数据
if(corner_count == board_n){
step = successes * board_n;
for(int i = step,j = 0; j CV_MAT_ELEM(* image_points,float,i,0)= corners [j] .x ;
CV_MAT_ELEM(* image_points,float,i,1)= corners [j] .y;
CV_MAT_ELEM(* object_points,float,i,0)= j / board_w;
CV_MAT_ELEM(* object_points,float,i,1)= j%board_w;
CV_MAT_ELEM(* object_points,float,i,2)= 0.0f;
}
CV_MAT_ELEM(* point_counts,int,successes,0)= board_n;
successes ++;
}
} // end skip board_dt chessboard capture
//处理暂停/取消暂停和ESC
int c = cvWaitKey(15);
if(c =='p'){
c = 0;
while(c!='p'& c!= 27){
c = cvWaitKey(250);
}
}
if(c == 27)
return 0;
image = cvQueryFrame(capture); // Get next image
} // END COLLECTION WHILE LOOP。

//根据多少个CHESSBOARDS,分配数组
CvMat * object_points2 = cvCreateMat(successes * board_n,3,CV_32FC1);
CvMat * image_points2 = cvCreateMat(successes * board_n,2,CV_32FC1);
CvMat * point_counts2 = cvCreateMat(successes,1,CV_32SC1);
//将指针转移到正确的大小数组
for(int i = 0; i CV_MAT_ELEM(* image_points2,float,i,0 )= CV_MAT_ELEM(* image_points,float,i,0);
CV_MAT_ELEM(* image_points2,float,i,1)= CV_MAT_ELEM(* image_points,float,i,1)
CV_MAT_ELEM(* object_points2,float,i,0)= CV_MAT_ELEM(* object_points,float,i,0)
CV_MAT_ELEM(* object_points2,float,i,1)= CV_MAT_ELEM(* object_points,float,i,1)
CV_MAT_ELEM(* object_points2,float,i,2)= CV_MAT_ELEM(* object_points,float,i,2)
}
for(int i = 0; i CV_MAT_ELEM(* point_counts2,int,i,0)= CV_MAT_ELEM (* point_counts,int,i,0);
}

//初始化内在矩阵,使两个焦点
//长度的比率为1.0
CV_MAT_ELEM(* intrinsic_matrix,float,0,0 )= 1.0f;
CV_MAT_ELEM(* intrinsic_matrix,float,1,1)= 1.0f;
// CALIBRATE THE CAMERA!
cvCalibrateCamera2(
object_points2,image_points2,
point_counts2,cvGetSize(image),
intrinsic_matrix,distortion_coeffs,
NULL,NULL // 0 CV_CALIB_FIX_ASPECT_RATIO
) ;

//保存内在和错误
cvSave(Intrinsics.xml,intrinsic_matrix);
cvSave(Distortion.xml,distort_coeffs);

cvReleaseMat(& object_points);
cvReleaseMat(& image_points);
cvReleaseMat(& point_counts);
cvReleaseMat(& object_points2);
cvReleaseMat(& image_points2);
cvReleaseMat(& point_counts2);
cvReleaseMat(& intrinsic_matrix);
cvReleaseMat(& distortion_coeffs);

//加载这些数据的示例回到:
CvMat * intrinsic =(CvMat *)cvLoad(Intrinsics.xml);
CvMat * distortion =(CvMat *)cvLoad(Distortion.xml);

//构建我们将用于所有
//后续帧的undistort映射。
IplImage * mapx = cvCreateImage(cvGetSize(image),IPL_DEPTH_32F,1);
IplImage * mapy = cvCreateImage(cvGetSize(image),IPL_DEPTH_32F,1);
cvInitUndistortMap(
intrinsic,
distortion,
mapx,
mapy
);

//只需运行相机到屏幕,现在显示原始和
//未失真的图像
cvNamedWindow(Undistort);
while(image){
IplImage * t = cvCloneImage(image);

//问题在这里!
// cvRemap(image,t,mapx,mapy); // undistort image
cvUndistort2(image,t,intrinsic,distortion);

cvShowImage(Calibration,image); // Show raw image
cvShowImage(Undistort,t); //显示更正的图片
cvReleaseImage(& t);
//处理暂停/取消暂停和ESC
int c = cvWaitKey(30);
if(c =='p'){
c = 0;
while(c!='p'& c!= 27){
c = cvWaitKey(250);
}
}
if(c == 27)
break;
image = cvQueryFrame(capture);
}
cvReleaseMat(& intrinsic);
cvReleaseMat(& distortion);

cvReleaseImage(& image);
cvReleaseImage(& gray_image);
cvReleaseImage(& mapx);
cvReleaseImage(& mapy);
cvDestroyWindow(Calibration);
cvDestroyWindow(Undistort);
return 0;
}

这里是保存在Intrinsics.xml和Distortion.xml中的校准结果: / p>

Intrinsics.xml:

 <?xml version =1.0 > 
< opencv_storage>
< Intrinsics type_id =opencv-matrix>
< rows> 3< / rows>
< cols> 3< / cols>
< dt> f< / dt>
< data>
649.64843750 0. 288.47882080 0. 647.89129639 271.92953491 0. 0. 1.< / data>< / Intrinsics>
< / opencv_storage>

Distortion.xml:

 <?xml version =1.0?> 
< opencv_storage>
< Distortion type_id =opencv-matrix>
< rows> 5< / rows>
< cols> 1< / cols>
< dt> f< / dt>
< data>
-0.37764871 22.05950546 0.06449836 -0.03288389 -209.10910034< / data>< / Distortion>
< / opencv_storage>

我使用OpenCV2.0,Eclipse,Windows Vista。相机是笔记本电脑的网络摄像头。

解决方案

问题是cvUndistort2和cvRemap只接收8位图像。
因此,为了处理彩色图像,必须使用cvSplit和cvMerge:

  IplImage * r = cvCreateImage cvGetSize(image),8,1); // subpixel 
IplImage * g = cvCreateImage(cvGetSize(image),8,1); // subpixel
IplImage * b = cvCreateImage(cvGetSize ,8,1); // subpixel

while(image){
cvShowImage(Calibration,image); //显示原始图片
// cvCvtColor(image,gray_image,CV_BGR2GRAY);
cvSplit(image,r,g,b,NULL);

cvRemap(r,r,mapx,mapy); // undistort image
cvRemap(g,g,mapx,mapy); // Undistort image
cvRemap(b,b,mapx,mapy); // Undistort image

cvMerge(r,g,b,NULL,image);
cvShowImage(Undistort,image); //显示更正的图像


I was doing example 11-1 of "Learning OpenCV" by Bradski. Unfortunately the given example doesn't work on my computer.

The program is supposed to calibrate camera using chessboard and then output undistorted video output from the camera.

The calibration part works fine, the problem arises when the program tries to undistort the image. I tried both cvUndistort2() and cvRemap(), in both cases the output windows freeze and the the program crashes, so that I have to force close it.

Here is the code:

#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

int n_boards = 0;
int board_dt = 15;
int board_w;
int board_h;
int main(int argc, char* argv[]) {

  CvCapture* capture;
  /*
  if(argc != 5){
    printf("\nERROR: Wrong number of input parameters");
    help();
    return -1;
  }
  */

  board_w  = 7;//atoi(argv[1]);
  board_h  = 7;//atoi(argv[2]);
  n_boards = 8;//atoi(argv[3]);

  CvSize board_sz = cvSize( board_w, board_h );
  capture = cvCreateCameraCapture( 0 );
  if(!capture) { printf("\nCouldn't open the camera\n"); return -1;}

  cvNamedWindow( "Calibration" );
  IplImage *image = cvQueryFrame( capture );

  int board_n  = board_w * board_h;

  //ALLOCATE STORAGE
  CvMat* image_points      = cvCreateMat(n_boards*board_n,2,CV_32FC1);
  CvMat* object_points     = cvCreateMat(n_boards*board_n,3,CV_32FC1);
  CvMat* point_counts      = cvCreateMat(n_boards,1,CV_32SC1);
  CvMat* intrinsic_matrix  = cvCreateMat(3,3,CV_32FC1);
  CvMat* distortion_coeffs = cvCreateMat(5,1,CV_32FC1);

  CvPoint2D32f* corners = new CvPoint2D32f[ board_n ];
  int corner_count;
  int successes = 0;
  int step, frame = 0;

  IplImage *gray_image = cvCreateImage(cvGetSize(image),8,1);//subpixel

  // CAPTURE CORNER VIEWS LOOP UNTIL WE'VE GOT n_boards
  // SUCCESSFUL CAPTURES (ALL CORNERS ON THE BOARD ARE FOUND)
  while (successes < n_boards) {
        //Skip every board_dt frames to allow user to move chessboard
        if((frame++ % board_dt) == 0) {
           //Find chessboard corners:
           int found = cvFindChessboardCorners(
                    image, board_sz, corners, &corner_count,
                    CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS
           );

           //Get Subpixel accuracy on those corners
           cvCvtColor(image, gray_image, CV_BGR2GRAY);
           cvFindCornerSubPix(gray_image, corners, corner_count,
                      cvSize(11,11),cvSize(-1,-1), cvTermCriteria(
                      CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));

           //Draw it
           cvDrawChessboardCorners(image, board_sz, corners,
                      corner_count, found);
           cvShowImage( "Calibration", image );

           // If we got a good board, add it to our data
           if( corner_count == board_n ) {
               step = successes*board_n;
               for( int i=step, j=0; j<board_n; ++i,++j ) {
                   CV_MAT_ELEM(*image_points, float,i,0) = corners[j].x;
                   CV_MAT_ELEM(*image_points, float,i,1) = corners[j].y;
                   CV_MAT_ELEM(*object_points,float,i,0) = j/board_w;
                   CV_MAT_ELEM(*object_points,float,i,1) = j%board_w;
                   CV_MAT_ELEM(*object_points,float,i,2) = 0.0f;
               }
               CV_MAT_ELEM(*point_counts, int,successes,0) = board_n;
               successes++;
           }
        } //end skip board_dt between chessboard capture
       //Handle pause/unpause and ESC
       int c = cvWaitKey(15);
       if (c == 'p'){
           c = 0;
           while(c != 'p' && c != 27){
               c = cvWaitKey(250);
           }
       }
       if(c == 27)
           return 0;
       image = cvQueryFrame( capture ); //Get next image
  } //END COLLECTION WHILE LOOP.

   //ALLOCATE MATRICES ACCORDING TO HOW MANY CHESSBOARDS FOUND
   CvMat* object_points2 = cvCreateMat(successes*board_n,3,CV_32FC1);
   CvMat* image_points2 = cvCreateMat(successes*board_n,2,CV_32FC1);
   CvMat* point_counts2 = cvCreateMat(successes,1,CV_32SC1);
   //TRANSFER THE POINTS INTO THE CORRECT SIZE MATRICES
   for(int i = 0; i<successes*board_n; ++i) {
       CV_MAT_ELEM( *image_points2, float, i, 0) = CV_MAT_ELEM( *image_points, float, i, 0);
       CV_MAT_ELEM( *image_points2, float, i, 1) = CV_MAT_ELEM( *image_points, float, i, 1);
       CV_MAT_ELEM( *object_points2, float, i, 0) = CV_MAT_ELEM( *object_points, float, i, 0) ;
       CV_MAT_ELEM( *object_points2, float, i, 1) = CV_MAT_ELEM( *object_points, float, i, 1) ;
       CV_MAT_ELEM( *object_points2, float, i, 2) = CV_MAT_ELEM( *object_points, float, i, 2) ;
   }
   for(int i=0; i<successes; ++i){ //These are all the same number
       CV_MAT_ELEM( *point_counts2, int, i, 0) = CV_MAT_ELEM( *point_counts, int, i, 0);
   }

   // Initialize the intrinsic matrix such that the two focal
   // lengths have a ratio of 1.0
   CV_MAT_ELEM( *intrinsic_matrix, float, 0, 0 ) = 1.0f;
   CV_MAT_ELEM( *intrinsic_matrix, float, 1, 1 ) = 1.0f;
   //CALIBRATE THE CAMERA!
   cvCalibrateCamera2(
       object_points2, image_points2,
       point_counts2, cvGetSize( image ),
       intrinsic_matrix, distortion_coeffs,
       NULL, NULL,0 //CV_CALIB_FIX_ASPECT_RATIO
   );

   // SAVE THE INTRINSICS AND DISTORTIONS
   cvSave("Intrinsics.xml",intrinsic_matrix);
   cvSave("Distortion.xml",distortion_coeffs);

   cvReleaseMat(&object_points);
   cvReleaseMat(&image_points);
   cvReleaseMat(&point_counts);
   cvReleaseMat(&object_points2);
   cvReleaseMat(&image_points2);
   cvReleaseMat(&point_counts2);
   cvReleaseMat(&intrinsic_matrix);
   cvReleaseMat(&distortion_coeffs);

   // EXAMPLE OF LOADING THESE MATRICES BACK IN:
   CvMat *intrinsic = (CvMat*)cvLoad("Intrinsics.xml");
   CvMat *distortion= (CvMat*)cvLoad("Distortion.xml");

   // Build the undistort map that we will use for all
   // subsequent frames.
   IplImage* mapx = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1 );
   IplImage* mapy = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1 );
   cvInitUndistortMap(
       intrinsic,
       distortion,
       mapx,
       mapy
   );

   // Just run the camera to the screen, now showing the raw and
   // the undistorted image
   cvNamedWindow( "Undistort" );
   while(image) {
       IplImage *t = cvCloneImage(image);

       // PROBLEM HERE!
       //cvRemap( image, t, mapx, mapy ); // Undistort image
       cvUndistort2(image, t, intrinsic, distortion);

       cvShowImage( "Calibration", image ); // Show raw image
       cvShowImage( "Undistort", t); // Show corrected image
       cvReleaseImage(&t);
       //Handle pause/unpause and ESC
       int c = cvWaitKey(30);
       if(c == 'p') {
           c = 0;
           while(c != 'p' && c != 27) {
               c = cvWaitKey(250);
           }
       }
       if(c == 27)
           break;
       image = cvQueryFrame( capture );
   }
   cvReleaseMat(&intrinsic);
   cvReleaseMat(&distortion);

   cvReleaseImage(&image);
   cvReleaseImage(&gray_image);
   cvReleaseImage(&mapx);
   cvReleaseImage(&mapy);
   cvDestroyWindow("Calibration");
   cvDestroyWindow("Undistort");
   return 0;
}

Here are the calibration results saved in Intrinsics.xml and Distortion.xml:

Intrinsics.xml:

<?xml version="1.0"?>
<opencv_storage>
<Intrinsics type_id="opencv-matrix">
  <rows>3</rows>
  <cols>3</cols>
  <dt>f</dt>
  <data>
    649.64843750 0. 288.47882080 0. 647.89129639 271.92953491 0. 0. 1.</data></Intrinsics>
</opencv_storage>

Distortion.xml:

<?xml version="1.0"?>
<opencv_storage>
<Distortion type_id="opencv-matrix">
  <rows>5</rows>
  <cols>1</cols>
  <dt>f</dt>
  <data>
    -0.37764871 22.05950546 0.06449836 -0.03288389 -209.10910034</data></Distortion>
</opencv_storage>

I use OpenCV2.0, Eclipse, Windows Vista. Camera is a webcam of the laptop.

解决方案

The problem is that cvUndistort2 and cvRemap receive 8bit images only. Hence, in order to process color images, one must use cvSplit and cvMerge:

   IplImage *r = cvCreateImage(cvGetSize(image),8,1);//subpixel
   IplImage *g = cvCreateImage(cvGetSize(image),8,1);//subpixel
   IplImage *b = cvCreateImage(cvGetSize(image),8,1);//subpixel

   while(image) {
       cvShowImage( "Calibration", image ); // Show raw image
       //cvCvtColor(image, gray_image, CV_BGR2GRAY);
       cvSplit(image, r,g,b, NULL);

       cvRemap( r, r, mapx, mapy ); // Undistort image
       cvRemap( g, g, mapx, mapy ); // Undistort image
       cvRemap( b, b, mapx, mapy ); // Undistort image

       cvMerge(r,g,b, NULL, image);
   cvShowImage( "Undistort", image); // Show corrected image

这篇关于cvUndistort2()和cvRemap()崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆