初衷是,使用双目摄像头的两组人脸图像(其中,一组图像全部有人脸坐标的标注,另一组图像只有少数有标注),获取fundamental matrix后,基于它在已知一张图像的25个人脸坐标,来获取另一张图像的25个人脸坐标,到目前为止,没有找到对应的实现接口,请大师帮忙指点,多谢!!!
后来,我想先做这一步,先求出fundamental matrix,再求出epipolar lines,再验证fundamental matrix的准确性,发现准确性比较差,不知道是不是我的实现有问题,请指教!!!
以下是我的实现代码:
#include <opencv2/features2d.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/highgui.hpp> //for imshow
#include <opencv2/sfm/fundamental.hpp>
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
#define MAX_LANDMARK_NUM 25
using namespace std;
using namespace cv;
const double ransac_thresh = 2.5f; // RANSAC inlier threshold
int main()
{
vector<cv::Point2f> LeftImgPoints;
vector<cv::Point2f> RightImgPoints;
LeftImgPoints.resize(MAX_LANDMARK_NUM);
RightImgPoints.resize(MAX_LANDMARK_NUM);
/***********************left image points landmarks*************************/
float LeftPoints[MAX_LANDMARK_NUM*2]={
/*0:*/ 266.494568, 136.649475,
/*1:*/ 326.338684, 138.954971,
/*2:*/ 243.827042, 123.274399,
/*3:*/ 282.252808, 120.761002,
/*4:*/ 310.646332, 121.924484,
/*5:*/ 348.195129, 126.660583,
/*6:*/ 296.718231, 134.861343,
/*7:*/ 297.636292, 168.063354,
/*8:*/ 298.398010, 194.067596,
/*9:*/ 298.489471, 210.286652,
/*10:*/ 272.073181, 200.278076,
/*11:*/ 324.186432, 201.395721,
/*12:*/ 311.821350, 178.312271,
/*13:*/ 282.899780, 177.943405,
/*14:*/ 298.447723, 201.113388,
/*15:*/ 297.691620, 180.510712,
/*16:*/ 278.787048, 138.599457,
/*17:*/ 266.053955, 140.525177,
/*18:*/ 254.396240, 137.555054,
/*19:*/ 338.479065, 140.511414,
/*20:*/ 326.387634, 142.896149,
/*21:*/ 314.163147, 139.965424,
/*22:*/ 262.127167, 114.590073,
/*23:*/ 330.401642, 117.000320,
/*24:*/ 298.632935, 246.623245
};
![](/qrcode.jpg)
/***********************right image points landmarks*************************/
float RightPoints[MAX_LANDMARK_NUM*2]={
/*0:*/ 256.945526, 150.456421,
/*1:*/ 312.700500, 150.243561,
/*2:*/ 236.628906, 135.709900,
/*3:*/ 271.273041, 134.200012,
/*4:*/ 298.863220, 134.269821,
/*5:*/ 331.507080, 135.001953,
/*6:*/ 285.332886, 147.685806,
/*7:*/ 287.318542, 178.595795,
/*8:*/ 287.446777, 201.479797,
/*9:*/ 287.730133, 217.580078,
/*10:*/ 264.293762, 208.232605,
/*11:*/ 309.134857, 207.639862,
/*12:*/ 299.079712, 187.576447,
/*13:*/ 273.375397, 188.002472,
/*14:*/ 287.539459, 208.525635,
/*15:*/ 287.101318, 189.247604,
/*16:*/ 268.616272, 151.772964,
/*17:*/ 256.426056, 154.131134,
/*18:*/ 245.320145, 151.107941,
/*19:*/ 323.970581, 150.674774,
/*20:*/ 312.713165, 153.930023,
/*21:*/ 301.221008, 151.662827,
/*22:*/ 253.150726, 129.308319,
/*23:*/ 315.920593, 129.135010,
/*24:*/ 287.617065, 244.829483
};
//////////////to Point2f
for(int i = 0; i < MAX_LANDMARK_NUM; i++)
{
LeftImgPoints[i].x = LeftPoints[2*i];
LeftImgPoints[i].y = LeftPoints[2*i+1];
RightImgPoints[i].x = RightPoints[2*i];
RightImgPoints[i].y = RightPoints[2*i+1];
LeftImgPoints3D[i].x = LeftPoints[2*i];
LeftImgPoints3D[i].y = LeftPoints[2*i+1];
LeftImgPoints3D[i].z = 0;
RightImgPoints3D[i].x = RightPoints[2*i];
RightImgPoints3D[i].y = RightPoints[2*i+1];
RightImgPoints3D[i].z = 0;
}
////////////////compute homography
cv::Mat fundamental,lines;
double scale = 0;
fundamental = cv::findFundamentalMat(RightImgPoints, LeftImgPoints);///获取fundamental matrix
printf("%d,%d,%d,%d\n", fundamental.rows, fundamental.cols, fundamental.channels() , fundamental.depth());
cv::computeCorrespondEpilines(LeftImgPoints, 2, fundamental, lines);///获取epipolar lines
printf("lines:%d,%d,%d,%d\n", lines.rows, lines.cols, lines.channels() , lines.depth());
float *dataTmp = (float*)(lines.data);
for(int i = 0; i < lines.rows; i++)
{
for(int j = 0; j < lines.cols; j++)
{
printf("(%f, %f, %f),%f\n", *dataTmp, *(dataTmp+1), *(dataTmp+2),
RightImgPoints[i].x * *dataTmp + RightImgPoints[i].y * *(dataTmp+1) + *(dataTmp+2) );
dataTmp +=3;
}
}
printf("\n*************************\n");
/*
*#define CV_8U 0
#define CV_8S 1
#define CV_16U 2
#define CV_16S 3
#define CV_32S 4
#define CV_32F 5
#define CV_64F 6
#define CV_USRTYPE1 7
*/
////////////////////////////////////////使用另外一组坐标点来验证fundamental matrix是否准确
float RightPoints_2[MAX_LANDMARK_NUM*2]={
/*0:*/ 258.861206, 159.249191,
/*1:*/ 306.307526, 158.586502,
/*2:*/ 241.442245, 146.764008,
/*3:*/ 270.690125, 143.485550,
/*4:*/ 293.419861, 143.074249,
/*5:*/ 322.782593, 145.337845,
/*6:*/ 282.460052, 155.938721,
/*7:*/ 283.747131, 181.839294,
/*8:*/ 284.975586, 202.937912,
/*9:*/ 285.468079, 215.837234,
/*10:*/ 265.193726, 209.560028,
/*11:*/ 304.983063, 208.645966,
/*12:*/ 295.072510, 190.770813,
/*13:*/ 272.856720, 191.418793,
/*14:*/ 285.181946, 208.586288,
/*15:*/ 284.183563, 191.816833,
/*16:*/ 268.457977, 160.034073,
/*17:*/ 258.657227, 162.402756,
/*18:*/ 249.403030, 160.190613,
/*19:*/ 315.969025, 159.130295,
/*20:*/ 306.408325, 161.778259,
/*21:*/ 296.859192, 159.674164,
/*22:*/ 255.231232, 139.219284,
/*23:*/ 308.625824, 138.274918,
/*24:*/ 286.368469, 243.561890
};
float LeftPoints_2[MAX_LANDMARK_NUM*2]={
/*0:*/ 269.969788, 149.457718,
/*1:*/ 317.636932, 148.411469,
/*2:*/ 252.532684, 139.018097,
/*3:*/ 280.601746, 137.239380,
/*4:*/ 302.707092, 136.273941,
/*5:*/ 334.577972, 137.098648,
/*6:*/ 292.269165, 147.340607,
/*7:*/ 293.107971, 176.336655,
/*8:*/ 297.368896, 197.832214,
/*9:*/ 299.383087, 212.971039,
/*10:*/ 279.862427, 204.545059,
/*11:*/ 320.124664, 202.883026,
/*12:*/ 307.166565, 183.458328,
/*13:*/ 284.374634, 184.732239,
/*14:*/ 298.398254, 204.409851,
/*15:*/ 295.368713, 186.161865,
/*16:*/ 279.359558, 150.014496,
/*17:*/ 269.830841, 152.328812,
/*18:*/ 261.126801, 150.462006,
/*19:*/ 327.682495, 148.769012,
/*20:*/ 317.710266, 151.377640,
/*21:*/ 308.231659, 149.386490,
/*22:*/ 265.603241, 133.261902,
/*23:*/ 318.869568, 131.495270,
/*24:*/ 302.055756, 241.381653
};
vector<cv::Point2f> RightImgPoints_2, LeftImgPoints_2;
RightImgPoints_2.resize(MAX_LANDMARK_NUM);
LeftImgPoints_2.resize(MAX_LANDMARK_NUM);
for(int i = 0; i < MAX_LANDMARK_NUM; i++)
{
RightImgPoints_2[i].x = RightPoints_2[2*i];
RightImgPoints_2[i].y = RightPoints_2[2*i+1];
LeftImgPoints_2[i].x = LeftPoints_2[2*i];
LeftImgPoints_2[i].y = LeftPoints_2[2*i+1];
}
Mat lines2;
cv::computeCorrespondEpilines(LeftImgPoints_2, 2, fundamental, lines2);
printf("lines:%d,%d,%d,%d\n", lines2.rows, lines2.cols, lines2.channels() , lines2.depth());
dataTmp = (float*)(lines2.data);
for(int i = 0; i < lines2.rows; i++)
{
for(int j = 0; j < lines2.cols; j++)
{
printf("(%f, %f, %f),%f\n", *dataTmp, *(dataTmp+1), *(dataTmp+2),
RightImgPoints_2[i].x * *dataTmp + RightImgPoints_2[i].y * *(dataTmp+1) + *(dataTmp+2) );
dataTmp +=3;
}
}
printf("\n*************************\n");
return 0;
}
输出结果如下:
root@opzoon-All-Series:/data_1/songqing/opencv/example/fundamental# ./fundamental.out
3,3,1,6
lines:25,1,3,5
(-0.342973, -0.939345, 229.704300),0.248398
(-0.874419, -0.485171, 346.325165),0.000000
(-0.141155, -0.989987, 170.150299),2.397766
(-0.162641, -0.986685, 176.752274),0.218948
(-0.307967, -0.951397, 219.783844),0.000000
(-0.889622, 0.456698, 233.260742),0.000000
(-0.477205, -0.878792, 265.947357),-0.000031
(-0.800531, -0.599292, 336.498932),-0.539368
(-0.890252, -0.455469, 347.772919),0.105164
(-0.918322, -0.395834, 349.465790),-0.888763
(-0.800952, -0.598729, 336.565857),0.204407
(-0.979566, -0.201125, 345.064240),0.484833
(-0.915003, -0.403447, 349.336029),0.000031
(-0.764893, -0.644157, 330.484344),0.278229
(-0.904014, -0.427504, 348.762238),-0.322845
(-0.851138, -0.524942, 343.706848),0.000000
(-0.419459, -0.907774, 250.723328),0.274170
(-0.385505, -0.922706, 241.507309),0.436050
(-0.314108, -0.949387, 221.537399),1.020370
(-0.993793, -0.111247, 338.446960),-0.274750
(-0.900328, -0.435212, 348.524719),-0.011902
(-0.727196, -0.686430, 323.472198),0.319641
(-0.048440, -0.998826, 140.983093),-0.435944
(-0.338830, -0.940848, 228.539719),0.000015
(-0.951987, -0.306140, 349.218506),0.458862
*************************
lines:25,1,3,5
(-0.495431, -0.868647, 270.627472),4.048248
(-0.843023, -0.537877, 342.678101),-0.846313
(-0.323807, -0.946123, 224.295258),7.257782
(-0.411118, -0.911582, 248.476883),6.392380
(-0.550446, -0.834871, 284.358978),3.398773
(-0.963600, -0.267347, 348.149536),-1.739502
(-0.607148, -0.794589, 297.826385),2.424133
(-0.811681, -0.584101, 338.236237),1.711578
(-0.893935, -0.448197, 348.064301),2.358521
(-0.924525, -0.381120, 349.647583),3.465088
(-0.842678, -0.538417, 342.633148),6.329376
(-0.971479, -0.237126, 346.935059),1.175079
(-0.904654, -0.426147, 348.801300),0.566376
(-0.800632, -0.599156, 336.515076),3.367462
(-0.909340, -0.416053, 349.066681),2.956238
(-0.857345, -0.514742, 344.455505),2.075928
(-0.550542, -0.834808, 284.382446),2.987427
(-0.521625, -0.853175, 277.241852),3.761810
(-0.465071, -0.885274, 262.797394),4.994843
(-0.936378, -0.350992, 349.742523),-1.977509
(-0.861538, -0.507694, 344.941254),-1.174835
(-0.760452, -0.649394, 329.690369),0.251770
(-0.299324, -0.954151, 217.306931),8.073761
(-0.660926, -0.750451, 309.855621),2.108185
(-0.955404, -0.295303, 348.976318),3.454315
结果分析:
如果使用另一组坐标点来求epipolar lines的话,发现误差还是很大的啊,问题出在哪里????