OpenCV Q&A Forum - RSS feedhttp://answers.opencv.org/questions/OpenCV answersenCopyright <a href="http://www.opencv.org">OpenCV foundation</a>, 2012-2018.Mon, 26 Nov 2018 11:04:12 -0600Wrong rank in Fundamental Matrixhttp://answers.opencv.org/question/204100/wrong-rank-in-fundamental-matrix/Hi guys,
I'm using the OpenCV for Python3 and, based on the Mastering OpenCV Book, try to compute the epipoles from many images (Structure from Motion algorithm).
In many books, they say which Fundamental Matrix has rank 2. But, the OpenCV function returns a rank 3 matrix.
How can I make this right?
orb = cv2.ORB_create()
# find the keypoints and descriptors with ORB
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)
# create BFMatcher object
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
# Match descriptors.
matches = bf.match(des1,des2)
# Sort them in the order of their distance.
matches = sorted(matches, key = lambda x:x.distance)
pts1 = []
pts2 = []
for m in matches:
pts2.append(kp2[m.trainIdx].pt)
pts1.append(kp1[m.queryIdx].pt)
F, mask = cv2.findFundamentalMat(pts1, pt2,cv2.FM_RANSAC)
pts1 = match['leftPts'][mask.ravel()==1]
pts2 = match['rightPts'][mask.ravel()==1]
# F is the Fundamental Matrix
From that code, the output are like
Processing image 0 and image 1
rank of F: 3
Processing image 0 and image 2
rank of F: 3
Processing image 0 and image 3
rank of F: 3
Processing image 0 and image 4
rank of F: 2
[...]
Someone could help me? Someone have any functional code for SfM using OpenCV?
Thanks in advance.
Lucas Amparo BarbosaMon, 26 Nov 2018 11:04:12 -0600http://answers.opencv.org/question/204100/Why findFundamentalMat gives different results for same but different orientation of points?http://answers.opencv.org/question/113067/why-findfundamentalmat-gives-different-results-for-same-but-different-orientation-of-points/Sorry if the title is kind of weird. It is quite hard to express the question of my problem.
So, I am in the middle of a 3D reconstruction project. The pipeline is more or less the same with the standard pipeline where
1. Undistort image
2. Detect points with keypoint detector
3. Track the points across frames (optical flow)
4. Calculate the fundamental matrix
and so on. The only different part is at step 2 where I use a Line Segment Detector and track it across frames.
So, if I am using a keypoint detector, giving two frame of images, I will get two set of keypoints (each set corresponds to each frame). But as for my situation, I have four set of keypoints (each two set correspond to each frame since a line has a start point and an end point).
In order to calculate the Fundamental matrix, I need to concatenate the two sets of point of each frame.
One way is by just vertically concatenate it: `np.vstack([start_point, end_point])`.
The other way is by :`np.hstack([start_point, end_point]).reshape(-1, 2)`. Means, it is concatenated 'alternately', i.e.
[[start_point[0],
end_point[0],
start_point[1],
end_point[1],
...]]
Both will end up with a same shape. But fair enough, they produce a quite different results. From my observation, the `vstack` produced a more '3D-like' result while the `hstack` produced a more 'planar-like' result for the reconstruction.
The question is why is this? And which one supposed to be better?
Below is sample code to give a view of this question:
import numpy as np
import cv2
np.random.seed(0)
def prepare_points(pts_frame1, pts_frame2):
# Prepare the four sets of points
(p1_f1, p2_f1) = pts_frame1
(p1_f2, p2_f2) = pts_frame2
v_stacked_f1f2 = (np.vstack([p1_f1, p2_f1]), np.vstack([p1_f2, p2_f2]))
h_stacked_f1f2 = (np.hstack([p1_f1, p2_f1]).reshape(-1, 2),
np.hstack([p1_f2, p2_f2]).reshape(-1, 2))
return (v_stacked_f1f2, h_stacked_f1f2)
pts_frame1 = np.random.random_sample((60, 2)).astype("float32")
pts_frame2 = np.random.random_sample((60, 2)).astype("float32")
# Emulate the two sets of points for each frame where
# the first set is the start point, while
# the second set is the end point of a line
pts_frame1 = (pts_frame1[::2], pts_frame1[1::2])
pts_frame2 = (pts_frame2[::2], pts_frame2[1::2])
(v_stacked_f1f2, h_stacked_f1f2) = prepare_points(pts_frame1, pts_frame2)
F_vstacked = cv2.findFundamentalMat(v_stacked_f1f2[0], v_stacked_f1f2[1],
cv2.FM_RANSAC, 3, 0.99)[0]
F_hstacked = cv2.findFundamentalMat(h_stacked_f1f2[0], h_stacked_f1f2[1],
cv2.FM_RANSAC, 3, 0.99)[0]
print("F_vstacked:\n", F_vstacked, "\n")
print("F_hstacked:\n", F_hstacked, "\n")
# The output:
# F_vstacked:
# [[ 3.31788127 -2.24336615 -0.77866782]
# [ 0.83418839 -1.4066019 -0.92088302]
# [-2.75413748 2.27311637 1. ]]
# F_hstacked:
# [[ 7.70558741 25.29966782 -16.20835082]
# [-12.95357284 -0.54474384 14.95490469]
# [ 1.79050172 -10.40077071 1. ]]
HilmanMon, 14 Nov 2016 22:59:48 -0600http://answers.opencv.org/question/113067/Validating the Funadamental Matrixhttp://answers.opencv.org/question/29876/validating-the-funadamental-matrix/I am calculating the fundamental matrix between two successive frames of a kinect, and according to Hartley and Zisserman the matrix should satisfy x'Fx=0.
I wrote up some quick code that I thought might do the job, but it's not working perfectly, which I will detail at the end of this question:
Mat RansakMask;
Mat F = findFundamentalMat(good_matches1,good_matches2,8,3.0,0.99,RansakMask);
cout << "Number of matches: " << RansakMask.size().height << endl;
int matches[2];
matches[0]=0;matches[1]=0;
for (int j = 0; j < (good_matches1.size()); j++)
{
if(RansakMask.at<uchar>(j, 0) != 1)continue;
cv::Mat p1(3,1, CV_64FC1), p2(3,1, CV_64FC1);
p1.at<double>(0) = good_matches1.at(j).x;
p1.at<double>(1) = good_matches1.at(j).y;
p1.at<double>(2) = 1.0;
p2.at<double>(0) = good_matches2.at(j).x;
p2.at<double>(1) = good_matches2.at(j).y;
p2.at<double>(2) = 1.0;
Mat m = (p1.t()*F*p2);
int i = (abs(m.at<double>(0))<0.5)?0:1;
matches[i]++;
}
cout << "Number of correct: " << matches[0] << endl << "Number of wrong: " << matches[1] << endl;
if(matches[1]>matches[0])
{
cout << "Fundamental Mat is wrong" << endl;
}
The basic idea was, out of all the inliers, compute which were accurate (<0.5f), and which weren't. If there are more accurate than wrong, we can proceed assuming F is relatively accurate.
However, when holding the camera still, this seems to work 9 frames out of 10, on the tenth frame usually giving an answer like (2 correct, 198 wrong) whereas every other frame is typically (198 correct, 2 wrong) etc.
When I move the camera, this turns into more of a 50% chance to be wrong. I don't want to have to throw away F every second frame, so I feel I must be missing something with this code.
Any advice would be appreciated. Thanks.FraserTWed, 12 Mar 2014 12:17:09 -0500http://answers.opencv.org/question/29876/