cvUndistort2() 和 cvRemap() 崩溃 [英] cvUndistort2 () and cvRemap () crash
问题描述
我正在做 Bradski 的Learning OpenCV"的示例 11-1.不幸的是,给定的示例在我的计算机上不起作用.
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.
校准部分工作正常,当程序试图不扭曲图像时出现问题.我尝试了 cvUndistort2() 和 cvRemap(),在这两种情况下,输出窗口都会冻结并且程序崩溃,所以我必须强制关闭它.
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.
代码如下:
#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;
//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;
}
以下是保存在 Intrinsics.xml 和 Distortion.xml 中的校准结果:
Here are the calibration results saved in Intrinsics.xml and Distortion.xml:
Intrinsics.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>
失真.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.相机是笔记本电脑的网络摄像头.
I use OpenCV2.0, Eclipse, Windows Vista. Camera is a webcam of the laptop.
推荐答案
问题是cvUndistort2和cvRemap只能接收8bit的图片.因此,为了处理彩色图像,必须使用 cvSplit 和 cvMerge:
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屋!