-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calculate distances on the ground plane #297
Comments
Are we currently doing anything to correct for the fish-eye lenses on the cameras? I feel like I've heard people talk about that, but am not sure. |
Not yet, but we will need to. JavaCV is a wrapper around the OpenCV methods which will give us access to methods like findChessboardCorners and calibrateCamera. We'll also need a way to save the checkerboard images, camera distortion matrix, and the intrinsic camera values for each of the cameras |
Okay, So I've come up with a newer approach to this problem which does not require the IMU. After we calibrate the camera we will have the camera matrix, and the distortion coefficients of that camera. Once we have this we can remove the effects of radial distortion on the test image. With the intrinsic camera values it is possible to determine the translational and rotational offsets of points on the ground plane by examining image-coordinate vs object-coordinate point pairs. Using Perspective-n-Point (PnP) algorithms we can determine the transformation that an object-coordinate must undergo to be projected onto the image-plane. By solving this set of equations, it is possible to determine the camera offset and rotation in terms of object coordinates. The object coordinates are arbitrary but must be in proper proportion to the real world. Assume that we choose one of the cargo containers and estimate a 90 degree angle with two equal sides. This plot provides us with a set of pixel and object coordinate pairs. The translational and rotational vecotors can be obtained using the opencv_calib3d.solvePnP(
objectCoordinates, // found using gui
targetCoordinates, // found using gui
cameraMatrix, // found during calibration
distortionCoeffs, // found during calibration
rotationalVector, // returned by method
translationalVector); // returned by method These vectors provide a way to get image coordinates from object coordinates, however, in this case we require object coordinates from image coordinates (we will later find a scalar to transform object units into world units). The tricky part here is that a 3D coordinate projects onto a 2D image plane in only one unique spot, however, an image coordinate maps into a 3D space as a ray (infinitely many locations). Because we know the interest point is restricted to where the ray intersects with the object plane we have enough information to solve this problem.
Once this system is solved we can take any image point and project the point onto the object plane. Knowing the height of the camera from depth will allow us to translate the Java code example: final Mat P = new Mat(3, 1, opencv_core.CV_32F);
final DoubleIndexer PIndexer = P.createIndexer();
PIndexer.put(0, 0, x);
PIndexer.put(1, 0, y);
PIndexer.put(2, 0, 1); // make image point P homogeneous
Mat T = translationalVector;
Mat R = rotationalMatrix;
Mat C = cameraMatrix;
Mat Rinv = R.inv().asMat();
Mat Cinv = C.inv().asMat();
Mat Rinv_Cinv = new Mat();
opencv_core.gemm(Rinv, Cinv, 1, new Mat(), 0, Rinv_Cinv);
Mat Cinv_P = new Mat();
opencv_core.gemm(Cinv, P, 1, new Mat(), 0, Cinv_P);
Mat Rinv_Cinv_P = new Mat();
opencv_core.gemm(Rinv, Cinv_P, 1, new Mat(), 0, Rinv_Cinv_P);
Mat Rinv_T = new Mat();
opencv_core.gemm(Rinv, T, 1, new Mat(), 0, Rinv_T);
DoubleIndexer i1 = Rinv_Cinv_P.createIndexer();
DoubleIndexer i2 = Rinv_T.createIndexer();
double s = i2.get(2,0)/i1.get(2,0);
Mat Rinv_Cinv_s_P = opencv_core.multiply(s, Rinv_Cinv_P).asMat();
Mat O = opencv_core.subtract(Rinv_Cinv_s_P, Rinv_T).asMat(); |
Just for my own understanding, can you answer the following questions about the distance calculator tool? These aren't meant to be criticisms, I just think it's cool and want to understand a little more I know we've talked about it, but I have no experience in Computer Vision and minimal experience with ROV competitions
|
Fair questions; questions are good 👍
You only need can capture a few points of interest in each image you take. In the following image you'll need to have some overlapping points from the last image in order to locate the newer points with respect to the last.
Right now we're making guesses.. I feel like there should be a way to determine the translation/ rotational matrix by just knowing 90 degree angles, but the math hasn't hit me yet. The idea right now is to draw multiple 90 degree triangles on the image and examine the rotational/ translational matrices caused by each triangle. If we assign one triangle to be the origin we can use that to find the world coordinates of the other triangles. If this image-to-object projection causes the other triangle not to be 90 degrees, we can go back and tweak our inputs. In the following image we have 3 possible object origins: Say red was chosen as the origin. We'd then have to project the purple and green image points onto the object plane we derived from selecting red (numbers made up). We can then verify after the projection that the green and the purple triangles are still 90 degree angles with two equal sides using some trig. Once we're happy with the values on screen we can apply a weighting to the coordinate space by equating the pressure sensor height reading to the camera origin
Still needs to be tested fully. I'm assuming the error would be proportional to the side and angle error on the guessed triangle. The larger the triangle, the easier it will be to place good points, the lower the error will be on the guessed triangle. |
This looks like it has a lot of potential. Our past relative measuring tools weren't able to account for all of the 3d-perspective-funkiness but the combination of sticking to the ground plane and those nice 90 degree references makes it a lot more feasible. One concern I have is that our current camera set up might have issues getting a wide, clean shot of everything you want to measure. It's no dealbreaker though |
This is a proposed idea for calculating and determining the relative distance between multiple points on the ground plane. It combines data from the IMU and depth sensor to allow us to determine distances on the ground plane in respect to the ROV. This issue is being created to discuss possible implementations and hash out a full solution for detecting these distances.
Determining Depth
By recording the pressure at the bottom of the pool we will be able to determine the distance from the surface to the ground plane. After this value is recorded, the distance from the ROV to the ground plane can be determined at any time by subtracting the distance from the surface to the ROV using the latest pressure reading.
Determining Position
Using the accelerometer/gyroscope on the ROV and/or by placing the camera at a known angle, we will be able to determine the angle between the image plane's normal vector and the depth vector. Knowing the intrinsic properties of our camera will let us determine the angle between the image plane's normal vector and a target pixel. Consider the following case where the target pixel is below the center pixel (which is in line with the normal vector).
We now have three knowns in the solution- the height of the camera; the angle between the target and the depth vector, and that there is a right-angle between the ground plane and the depth vector. Using simple trig we can then calculate the distance of the target. This solution can then be easily expanded to calculate distances given both horizontal and vertical displacement of the target pixel.
**
The text was updated successfully, but these errors were encountered: