目标:从相机的透视图中取一个点(或一组点)并将它们/它们转换为相应的地平面点。
方法:使用findHomography
获取单应性Mat
。计划使用perspectiveTransform()
。
问题:无法解读单应性Mat
,也无法理解如何继续。它看起来9个元素中有5个是空的,我认为这是因为单应性是错误的,虽然无法解释结果,所以制作了许多印刷语句。
import org.opencv.calib3d.*;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.*;
import java.util.List;
import java.util.LinkedList;
import java.util.ArrayList;
final public class HomographyTest {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // needed by OpenCV
String rfileoutput = "/home/will/dev/Homog.jpg";
String ofileoutput = "/home/will/dev/HomogOutput.jpg";
Point SEShedCornerDst = new Point(49, 74);
Point CloseForsythiaDst = new Point(41, 41);
Point CornerHazelDst = new Point(111, 157);
Point FarForsythiaDst = new Point(175, 21);
Point FirstLiquidAmberDst = new Point(235, 164);
Point SecondLiquidAmberDst = new Point(282, 721);
Point ThirdLiquidAmberDst = new Point(317, 544);
Point SEShedCornerSrc = new Point(30, 231);
Point CloseForsythiaSrc = new Point(160, 290);
Point CornerHazelSrc = new Point(50, 125);
Point FarForsythiaSrc = new Point(628, 146);
Point FirstLiquidAmberSrc = new Point(299, 64);
Point SecondLiquidAmberSrc = new Point(146, 37);
Point ThirdLiquidAmberSrc = new Point(48,34);
Point [] srcArray = new Point[7];
srcArray[0] = SEShedCornerSrc;
srcArray[1] = CloseForsythiaSrc;
srcArray[2] = CornerHazelSrc;
srcArray[3] = FarForsythiaSrc;
srcArray[4] = FirstLiquidAmberSrc;
srcArray[5] = SecondLiquidAmberSrc;
srcArray[6] = ThirdLiquidAmberSrc;
Mat OutputMat = new Mat();
LinkedList<Point> dstArray = new LinkedList<Point>();
dstArray.add(SEShedCornerDst);
dstArray.add(CloseForsythiaDst);
dstArray.add(CornerHazelDst);
dstArray.add(FarForsythiaDst);
dstArray.add(FirstLiquidAmberDst);
dstArray.add(SecondLiquidAmberDst);
dstArray.add(ThirdLiquidAmberDst);
MatOfPoint2f dst = new MatOfPoint2f();
dst.fromList(dstArray);
MatOfPoint2f src = new MatOfPoint2f();
src.fromArray(srcArray);
Mat Homog;
Homog = Calib3d.findHomography(src, dst, Calib3d.RANSAC, 10, OutputMat);
System.out.println("Columns = " + Homog.cols());
System.out.println("Rows = " + Homog.rows());
System.out.println("Width = " + Homog.width());
System.out.println("Dims = " + Homog.dims());
for (int i=1; i<= Homog.cols();i++){
for (int j=1; j<=Homog.rows();j++){
System.out.println("Row, column " + i + "," + j + " = " + Homog.get(j, i));
}
System.out.println();
}
System.out.println(Homog.toString());
System.out.println(OutputMat.toString());
Highgui.imwrite(rfileoutput, Homog);
Highgui.imwrite(ofileoutput, OutputMat);
}
}
输出;
Columns = 3
Rows = 3
Width = 3
Dims = 2
Row, column 1,1 = [D@674f1c67
Row, column 1,2 = [D@7ad1e32d
Row, column 1,3 = null
Row, column 2,1 = [D@6999de59
Row, column 2,2 = [D@74d4db38
Row, column 2,3 = null
Row, column 3,1 = null
Row, column 3,2 = null
Row, column 3,3 = null
Mat [ 3*3*CV_64FC1, isCont=true, isSubmat=false, nativeObj=0x7f744016bb50, dataAddr=0x7f744016b940 ]
Mat [ 7*1*CV_8UC1, isCont=true, isSubmat=false, nativeObj=0x7f7440166fe0, dataAddr=0x7f744016b9b0 ]
我是否在正确的轨道上?如果没有,我该怎么办?
如果是,请在Mat
的src perspectiveTransform
中输入什么类型,如何在需要的两个频道中执行此操作?
答案 0 :(得分:1)
我无法真正解释你的代码,特别是你的观点,但我认为这并不重要,因为正如你所说的那样,你的目标是从2组点创建单应矩阵,并用生成的单应矩阵透视变换图像
迭代单应矩阵
首先,你通过单应矩阵(3x3矩阵)从迭代中得到null
的原因是因为Mat
索引就像0处的数组一样开始,结束于“长度 - 1" 。
看起来应该是这样的:
for (int i = 0; i < homography.cols(); i++){
for (int j = 0; j < homography.rows(); j++){
System.out.println("[" + i + "," + j + "] = " + Arrays.toString(homography.get(j, i)));
}
}
查找单应性并应用(到图像)
要查找src
和dst
平面之间的单应矩阵,您可以使用findHomography()
。有关此函数的更多信息,请参阅API
// obtain your homography mat (picked your parameters.. you have to play to get the right results)
Mat homography = Calib3d.findHomography(src, dst, Calib3d.RANSAC, 10);
// image you want to transform
Mat image = Highgui.imread("image/img.jpg");
// outputMat will contain the perspectively changed image
Imgproc.warpPerspective(image, outputMat, homography, new Size(image.cols(), image.rows()));
将单应性应用于单点(非图像)
Mat src = new Mat();
// push a mat object with your points to the src
src.push_back(new MatOfPoint2f(new Point(x,y)));
// dst will contain your transformed points
Core.perspectiveTransform(src, dst, homography)
Btw ..
在Java中,通常的做法是使用小写字母启动变量名称。我看到了Homog
和OutputMat
。当我读到类似的东西时,我希望它们是课程。