I'm using OpenCV to get an birdseye view of the captured frames. This is done by providing a chessboard pattern on the plane which will form the birdseye view.
Although it seems like the camera is already pretty on top of this plain, I need it to be perfect in order to determine the relationship between pixels and centimeters.
In the next phase the captures frames are being warped. It gives the expected result:
However, by performing this transformation, data outside the chessboard pattern is being lost. What I need is rotating the image instead of warping a known quadrangle.
Question: How to rotate an image by an camera angle so that it's top-down?
Some code to illustrate what I'm currently doing:
Size chessboardSize = new Size(12, 8); // Size of the chessboard
Size captureSize = new Size(1920, 1080); // Size of the captured frames
Size viewSize = new Size((chessboardSize.width / chessboardSize.height) * captureSize.height, captureSize.height); // Size of the view
MatOfPoint2f imageCorners; // Contains the imageCorners obtained in a earlier stage
Mat H; // Homography
The code which finds the corners:
Mat grayImage = new Mat();
//Imgproc.resize(source, temp, new Size(source.width(), source.height()));
Imgproc.cvtColor(source, grayImage, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(grayImage, grayImage, 0.0, 255.0, Imgproc.THRESH_OTSU);
imageCorners = new MatOfPoint2f();
Imgproc.GaussianBlur(grayImage, grayImage, new Size(5, 5), 5);
boolean found = Calib3d.findChessboardCorners(grayImage, chessboardSize, imageCorners, Calib3d.CALIB_CB_NORMALIZE_IMAGE + Calib3d.CALIB_CB_ADAPTIVE_THRESH + Calib3d.CALIB_CB_FILTER_QUADS);
if (found) {
determineHomography();
}
The code which determines the homography:
Point[] data = imageCorners.toArray();
if (data.length < chessboardSize.area()) {
return;
}
Point[] roi = new Point[] {
data[0 * (int)chessboardSize.width - 0], // Top left
data[1 * (int)chessboardSize.width - 1], // Top right
data[((int)chessboardSize.height - 1) * (int)chessboardSize.width - 0], // Bottom left
data[((int)chessboardSize.height - 0) * (int)chessboardSize.width - 1], // Bottom right
};
Point[] roo = new Point[] {
new Point(0, 0),
new Point(viewSize.width, 0),
new Point(0, viewSize.height),
new Point(viewSize.width, viewSize.height)
};
MatOfPoint2f objectPoints = new MatOfPoint2f(), imagePoints = new MatOfPoint2f();
objectPoints.fromArray(roo);
imagePoints.fromArray(roi);
Mat H = Imgproc.getPerspectiveTransform(imagePoints, objectPoints);
Finally, the captured frames are being warped:
Imgproc.warpPerspective(capture, view, H, viewSize);
Question&Answers:
os