/// <summary>
/// Computes an optimal affine transformation between two 3D point sets.
/// </summary>
/// <param name="src">First input 3D point set.</param>
/// <param name="dst">Second input 3D point set.</param>
/// <param name="estimate">Output 3D affine transformation matrix.</param>
/// <param name="inliers">Output vector indicating which points are inliers.</param>
/// <param name="ransacThreshold">Maximum reprojection error in the RANSAC algorithm to consider a point as an inlier.</param>
/// <param name="confidence">Confidence level, between 0 and 1, for the estimated transformation. Anything between 0.95 and 0.99 is usually good enough. Values too close to 1 can slow down the estimation significantly. Values lower than 0.8-0.9 can result in an incorrectly estimated transformation.</param>
/// <returns></returns>
public static int CvEstimateAffine3D(MCvPoint3D32f[] src, MCvPoint3D32f[] dst, out Matrix <double> estimate, out Byte[] inliers, double ransacThreshold, double confidence)
{
GCHandle srcHandle = GCHandle.Alloc(src, GCHandleType.Pinned);
GCHandle dstHandle = GCHandle.Alloc(dst, GCHandleType.Pinned);
int result;
estimate = new Matrix <double>(3, 4);
using (Util.Mat affineEstimate = new Util.Mat())
using (Matrix <float> srcMat = new Matrix <float>(1, src.Length, 3, srcHandle.AddrOfPinnedObject(), Marshal.SizeOf(typeof(MCvPoint3D32f)) * src.Length))
using (Matrix <float> dstMat = new Matrix <float>(1, dst.Length, 3, dstHandle.AddrOfPinnedObject(), Marshal.SizeOf(typeof(MCvPoint3D32f)) * dst.Length))
using (Util.VectorOfByte vectorOfByte = new Util.VectorOfByte())
{
result = _CvEstimateAffine3D(srcMat, dstMat, affineEstimate, vectorOfByte, ransacThreshold, confidence);
inliers = vectorOfByte.ToArray();
CvInvoke.cvMatCopyToCvArr(affineEstimate, estimate);
}
srcHandle.Free();
dstHandle.Free();
return(result);
}