Dear Chris,
Thank you for taking time to reply and pointing out the focal length issue.
I
use ExtractEXIFMetaData function to find focal length. If that fails, I
read it from a list of focal lengths estimated by other method (Bundler estimated focal length for testing). If both fails, I assign an empty CameraIntrinsicsPrior object to that image as you suggested previously. Here is the relevant code block for your reference.
// Read EXIF data find focal length
printf("\nReading exif data %d/%d", i, numKeys);
CameraIntrinsicsPrior cPrior, dummyPrior;
bool status = exReader.ExtractEXIFMetadata(imgList.getImageName(i), &cPrior);
if(status) {
printf("\nRead EXIF data:");
if(cPrior.focal_length.is_set) {
calibrationFlag[i] = true;
focalLengths[i] = cPrior.focal_length.value;
camPriors.push_back(cPrior);
} else if(precompFocals[i] != 0) {
calibrationFlag[i] = true;
focalLengths[i] = precompFocals[i];
camPriors.push_back(cPrior);
} else {
camPriors.push_back(dummyPrior);
}
} else {
camPriors.push_back(dummyPrior);
}
}
The focal length supplied to VerifyTwoViewMatches is always either 0.000 (uninitialized object) or a valid focal length in pixels.
I printed the values of focal length in CameraIntrinsicsPrior object and TwoViewInfo object after verification.
VerifyTwoViewMatchesOptions options;
bool status = VerifyTwoViewMatches(options,
camPriors[img1], camPriors[img2],
featCorrs,&currPairInfo,&inliers);
if(status) {
printf("\nSuccessfully Verified Matches");
printf("\nFocal Length 1 = %f, Focal Length 2 = %f", camPriors[img1].focal_length.value,
camPriors[img2].focal_length.value);
printf("\nFocal Length 1 = %f, Focal Length 2 = %f", currPairInfo.focal_length_1, currPairInfo.focal_length_2);
for(int inl_id=0; inl_id < inliers.size(); inl_id++) {
inlFeatCorrs.push_back( featCorrs[inliers[inl_id]] );
}
ImagePairMatch imPair;
imPair.image1_index = img1;
imPair.image2_index = img2;
imPair.twoview_info = currPairInfo;
imPair.correspondences = inlFeatCorrs;
matches.push_back(imPair);
}
}
bool status = WriteMatchesAndGeometry("view_graph.bin", view_names, camPriors, matches);
if(!status) {
printf("\nSuccessfully written view-graph file");
}
The result is something like this,
Successfully Verified Matches
Focal Length 1 = 2582.260870, Focal Length 2 = 2804.869565 <--- #CameraIntrinsicsPrior
Focal Length 1 = 2582.260870, Focal Length 2 = 2804.869565 <--- #TwoViewInfo
Successfully Verified Matches
Focal Length 1 = 0.000000, Focal Length 2 = 2804.869565
Focal Length 1 = 2781.766951, Focal Length 2 = 1.043372
Successfully Verified Matches
Focal Length 1 = 0.000000, Focal Length 2 = 2804.869565
Focal Length 1 = 1425.175805, Focal Length 2 = 0.387760
Successfully Verified Matches
Focal Length 1 = 2727.334083, Focal Length 2 = 2804.869565
Focal Length 1 = 2727.334083, Focal Length 2 = 2804.869565
Successfully Verified Matches
Focal Length 1 = 0.000000, Focal Length 2 = 2804.869565
Focal Length 1 = 1140.065631, Focal Length 2 = 1.071549
So,
I understand that when any one of the two focal lengths is
un-initialized, two view geometry verify function probably estimates and assigns different
focal lengths to the cameras which doesn't come out very well. Should I discard all uncalibrated images from the list then?
On
a side note, I meanwhile wrote the two view information generated by theia (same
'view-graph.bin' file as above), and the other information as needed by
Kyle's 1D SFM and tried to run that. It runs without an error but I
haven't verified the output yet. I realize now that it would also be
erroneous due to the focal length issue.
Please suggest me the best way to handle uncalibrated images.
Please inform me if you need more information.