我正试图实时测量从立体声对到场景中检测到的人的距离 . 首先,我使用9x6棋盘(方形尺寸为59 mm)分别校准两个相机,并且我获得了两个相机的均方根误差在0.15和0.19之间 . 使用获得的参数,我校准了立体声对,均方根误差为0.36 . 后来,我纠正了,unistort并重新映射立体声对给我这个结果:rectified and undistorted stereo
做到这一点,我使用stereoSGBM计算立体声对应 . 这就是我做的:
Mat imgDisp= Mat(frame1.cols, frame1.rows,CV_16S);
cvtColor(frame1, frame1, CV_BGR2GRAY);
cvtColor(frame2, frame2, CV_BGR2GRAY);
//parameters for stereoSGBM
stereo.SADWindowSize = 3;
stereo.numberOfDisparities = 144;
stereo.preFilterCap = 63;
stereo.minDisparity = -39;
stereo.uniquenessRatio = 10;
stereo.speckleWindowSize = 100;
stereo.speckleRange = 32;
stereo.disp12MaxDiff = 1;
stereo.fullDP = false;
stereo.P1 = 216;
stereo.P2 = 864;
double minVal; double maxVal;
minMaxLoc(imgDisp, &minVal, &maxVal);
return imgDisp;
我在这里附上了stereoSGBM的结果:disparity map .
为了检测场景中的人,我使用了hog svm(默认的人检测器)并用光流跟踪该人(cvCalcOpticalFlowPyrLK()) . 使用在立体对应过程中获得的视差图,我获得了从一个人跟踪的每个角的视差如下:
int x= cornersA[k].x;
int y= cornersA[k].y;
short pixVal= mapaDisp.at<short>(y,x);
float dispFeatures= pixVal/ 16.0f;
对于在场景中为一个人跟踪的每个角落的视差,我计算了最大视差并使用公式((焦点*基线)/ disp)计算该像素中的深度:
float Disp =maxDisp_v[p];
cout<< "max disp"<< Disp<<endl;
float d = ((double)(879.85* 64.32)/(double)(Disp))/10; //distance in cms.
**对于焦距我计算了在相机矩阵[3x3]参数中获得的fx和fy之间的平均值:
CM1:[9.0472706037497187e 02 0. 3.7829164759284492e 02 0. 8.4576999835299739e 02 1.8649783393160138e 02 0. 0 . 1.] CM2:[9.1390904648169953e 02 0. 3.5700689147467887e 02 0. 8.5514555697458811e 02 2.1723345133656409e 02 0. 0 . 1]
所以fx camera1:904.7; fy camera1:845.7; fx camera2:913.9; fy camera2:855.1
** T [0,0]矩阵的结果与我手动测量的基线相匹配,因此我认为这是正确的基线 .
**由于棋盘的方形尺寸以mm为单位,我认为基线必须在同一单位,这就是为什么我在基线上放置64.32 mm的原因 .
距离的结果是aprox . 55厘米,但真正的距离是300厘米 . 我已经检查了很多次,但测得的距离仍然不正确:distanceResult
请帮助我!,我不知道我做错了什么 .
***我在osx系统中使用opencv 2.4.9 .
2 回答
我认为你用单位犯了一个错误:焦距以像素提供,基线以cm为单位提供视差 . 对?根据公式,你有pix * cm / pix = cm . 但是你将其除以10并获得dm . 所以你的距离大约是55dm,比300大两倍 . 这对你来说并不是一个坏的例子 .
您不能在校正后的图像上使用简单的并行摄像机三角测量公式,因为您需要撤消校正单应性 .
使用cv2.reprojectImageTo3D