/// <summary> /// Try to stitch the given images. /// </summary> /// <param name="images">Input images.</param> /// <param name="rois">Region of interest rectangles.</param> /// <param name="pano">Final pano.</param> /// <returns>Status code.</returns> public Status Stitch(IEnumerable <Mat> images, Rect[][] rois, OutputArray pano) { if (images == null) { throw new ArgumentNullException(nameof(images)); } if (rois == null) { throw new ArgumentNullException(nameof(rois)); } if (pano == null) { throw new ArgumentNullException(nameof(pano)); } pano.ThrowIfNotReady(); var imagesPtrs = images.Select(x => x.CvPtr).ToArray(); using var roisPointer = new ArrayAddress2 <Rect>(rois); NativeMethods.HandleException( NativeMethods.stitching_Stitcher_stitch2_MatArray( ptr, imagesPtrs, imagesPtrs.Length, roisPointer.GetPointer(), roisPointer.GetDim1Length(), roisPointer.GetDim2Lengths(), pano.CvPtr, out var ret)); pano.Fix(); GC.KeepAlive(this); GC.KeepAlive(images); GC.KeepAlive(pano); return((Status)ret); }
/// <summary> /// Try to stitch the given images. /// </summary> /// <param name="images">Input images.</param> /// <param name="rois">Region of interest rectangles.</param> /// <param name="pano">Final pano.</param> /// <returns>Status code.</returns> public Status Stitch(InputArray images, Rect[][] rois, OutputArray pano) { if (images == null) { throw new ArgumentNullException(nameof(images)); } if (rois == null) { throw new ArgumentNullException(nameof(rois)); } if (pano == null) { throw new ArgumentNullException(nameof(pano)); } images.ThrowIfDisposed(); pano.ThrowIfNotReady(); using var roisPointer = new ArrayAddress2 <Rect>(rois); NativeMethods.HandleException( NativeMethods.stitching_Stitcher_stitch2_InputArray( ptr, images.CvPtr, roisPointer.GetPointer(), roisPointer.GetDim1Length(), roisPointer.GetDim2Lengths(), pano.CvPtr, out var ret)); pano.Fix(); GC.KeepAlive(this); GC.KeepAlive(images); GC.KeepAlive(pano); return((Status)ret); }
/// <summary> /// Constructor /// </summary> /// <param name="values"></param> public VectorOfVectorKeyPoint(KeyPoint[][] values) { if (values == null) { throw new ArgumentNullException(nameof(values)); } using var aa = new ArrayAddress2 <KeyPoint>(values); ptr = NativeMethods.vector_vector_KeyPoint_new3( aa.GetPointer(), aa.GetDim1Length(), aa.GetDim2Lengths()); }
/// <summary> /// Pose estimation for single markers /// </summary> /// <param name="corners">corners vector of already detected markers corners. /// For each marker, its four corners are provided, (e.g std::vector<std::vector<cv::Point2f>> ). /// For N detected markers, the dimensions of this array should be Nx4. The order of the corners should be clockwise.</param> /// <param name="markerLength">the length of the markers' side. The returning translation vectors will /// be in the same unit.Normally, unit is meters.</param> /// <param name="cameraMatrix">input 3x3 floating-point camera matrix /// \f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$</param> /// <param name="distortionCoefficients">vector of distortion coefficients /// \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements</param> /// <param name="rvec">array of output rotation vectors (@sa Rodrigues) (e.g. std::vector<cv::Vec3d>). /// Each element in rvecs corresponds to the specific marker in imgPoints.</param> /// <param name="tvec">array of output translation vectors (e.g. std::vector<cv::Vec3d>). /// Each element in tvecs corresponds to the specific marker in imgPoints.</param> /// <param name="objPoints">array of object points of all the marker corners</param> public static void EstimatePoseSingleMarkers( Point2f[][] corners, float markerLength, InputArray cameraMatrix, InputArray distortionCoefficients, OutputArray rvec, OutputArray tvec, OutputArray?objPoints = null) { if (corners == null) { throw new ArgumentNullException(nameof(corners)); } if (cameraMatrix == null) { throw new ArgumentNullException(nameof(cameraMatrix)); } if (distortionCoefficients == null) { throw new ArgumentNullException(nameof(distortionCoefficients)); } if (rvec == null) { throw new ArgumentNullException(nameof(rvec)); } if (tvec == null) { throw new ArgumentNullException(nameof(tvec)); } cameraMatrix.ThrowIfDisposed(); distortionCoefficients.ThrowIfDisposed(); rvec.ThrowIfNotReady(); tvec.ThrowIfNotReady(); objPoints?.ThrowIfNotReady(); using var cornersAddress = new ArrayAddress2 <Point2f>(corners); NativeMethods.HandleException( NativeMethods.aruco_estimatePoseSingleMarkers( cornersAddress.GetPointer(), cornersAddress.GetDim1Length(), cornersAddress.GetDim2Lengths(), markerLength, cameraMatrix.CvPtr, distortionCoefficients.CvPtr, rvec.CvPtr, tvec.CvPtr, objPoints?.CvPtr ?? IntPtr.Zero)); GC.KeepAlive(cameraMatrix); GC.KeepAlive(distortionCoefficients); rvec.Fix(); tvec.Fix(); objPoints?.Fix(); }
/// <summary> /// /// </summary> /// <param name="matches1to2"></param> /// <param name="correctMatches1to2Mask"></param> /// <returns>recallPrecisionCurve</returns> public static Point2f[] ComputeRecallPrecisionCurve( DMatch[][] matches1to2, byte[][] correctMatches1to2Mask) { if (matches1to2 == null) { throw new ArgumentNullException(nameof(matches1to2)); } if (correctMatches1to2Mask == null) { throw new ArgumentNullException(nameof(correctMatches1to2Mask)); } using var dm = new ArrayAddress2 <DMatch>(matches1to2); using var cm = new ArrayAddress2 <byte>(correctMatches1to2Mask); using var recall = new VectorOfPoint2f(); NativeMethods.HandleException( NativeMethods.features2d_computeRecallPrecisionCurve( dm.GetPointer(), dm.GetDim1Length(), dm.GetDim2Lengths(), cm.GetPointer(), cm.GetDim1Length(), cm.GetDim2Lengths(), recall.CvPtr)); return(recall.ToArray()); }
public Status EstimateTransform(InputArray images, Rect[][] rois) { if (images == null) { throw new ArgumentNullException(nameof(images)); } if (rois == null) { throw new ArgumentNullException(nameof(rois)); } images.ThrowIfDisposed(); using var roisPointer = new ArrayAddress2 <Rect>(rois); NativeMethods.HandleException( NativeMethods.stitching_Stitcher_estimateTransform_InputArray2( ptr, images.CvPtr, roisPointer.GetPointer(), roisPointer.GetDim1Length(), roisPointer.GetDim2Lengths(), out var ret)); GC.KeepAlive(this); GC.KeepAlive(images); return((Status)ret); }
public Status EstimateTransform(IEnumerable <Mat> images, Rect[][] rois) { if (images == null) { throw new ArgumentNullException(nameof(images)); } if (rois == null) { throw new ArgumentNullException(nameof(rois)); } var imagesPtrs = images.Select(x => x.CvPtr).ToArray(); using var roisPointer = new ArrayAddress2 <Rect>(rois); NativeMethods.HandleException( NativeMethods.stitching_Stitcher_estimateTransform_MatArray2( ptr, imagesPtrs, imagesPtrs.Length, roisPointer.GetPointer(), roisPointer.GetDim1Length(), roisPointer.GetDim2Lengths(), out var ret)); GC.KeepAlive(this); GC.KeepAlive(images); return((Status)ret); }
/// <summary> /// Draw a set of detected ChArUco Diamond markers. /// </summary> /// <param name="image">input/output image. It must have 1 or 3 channels. The number of channels is not altered.</param> /// <param name="diamondCorners">positions of diamond corners in the same format returned by detectCharucoDiamond(). (e.g std::vector<std::vector<cv::Point2f>>). For N detected markers, the dimensions of this array should be Nx4. The order of the corners should be clockwise.</param> /// <param name="diamondIds">vector of identifiers for diamonds in diamondCorners, in the same format returned by detectCharucoDiamond() (e.g. std::vector<Vec4i>). Optional, if not provided, ids are not painted.</param> /// <param name="borderColor">color of marker borders. Rest of colors (text color and first corner color) are calculated based on this one.</param> public static void DrawDetectedDiamonds(InputArray image, Point2f[][] diamondCorners, IEnumerable <Vec4i>?diamondIds, Scalar borderColor) { if (image == null) { throw new ArgumentNullException(nameof(image)); } if (diamondCorners == null) { throw new ArgumentNullException(nameof(diamondCorners)); } using var cornersAddress = new ArrayAddress2 <Point2f>(diamondCorners); if (diamondIds == null) { NativeMethods.HandleException( NativeMethods.aruco_drawDetectedDiamonds(image.CvPtr, cornersAddress.GetPointer(), cornersAddress.GetDim1Length(), cornersAddress.GetDim2Lengths(), IntPtr.Zero, borderColor)); } else { using var ids = new VectorOfVec4i(diamondIds); NativeMethods.HandleException( NativeMethods.aruco_drawDetectedDiamonds(image.CvPtr, cornersAddress.GetPointer(), cornersAddress.GetDim1Length(), cornersAddress.GetDim2Lengths(), ids.CvPtr, borderColor)); } GC.KeepAlive(image); }
/// <summary> /// Detect ChArUco Diamond markers. /// </summary> /// <param name="image">input image necessary for corner subpixel.</param> /// <param name="markerCorners">list of detected marker corners from detectMarkers function.</param> /// <param name="markerIds">list of marker ids in markerCorners.</param> /// <param name="squareMarkerLengthRate">rate between square and marker length: squareMarkerLengthRate = squareLength/markerLength. The real units are not necessary.</param> /// <param name="diamondCorners">output list of detected diamond corners (4 corners per diamond). The order is the same than in marker corners: top left, top right, bottom right and bottom left. Similar format than the corners returned by detectMarkers (e.g std::vector<std::vector<cv::Point2f>>).</param> /// <param name="diamondIds">ids of the diamonds in diamondCorners. The id of each diamond is in fact of type Vec4i, so each diamond has 4 ids, which are the ids of the aruco markers composing the diamond.</param> /// <param name="cameraMatrix">Optional camera calibration matrix.</param> /// <param name="distCoeffs">Optional camera distortion coefficients.</param> public static void DetectCharucoDiamond(InputArray image, Point2f[][] markerCorners, IEnumerable <int> markerIds, float squareMarkerLengthRate, out Point2f[][] diamondCorners, out Vec4i[] diamondIds, InputArray?cameraMatrix = null, InputArray?distCoeffs = null) { if (image == null) { throw new ArgumentNullException(nameof(image)); } if (markerCorners == null) { throw new ArgumentNullException(nameof(markerCorners)); } if (markerIds == null) { throw new ArgumentNullException(nameof(markerIds)); } if (cameraMatrix == null && distCoeffs != null) { throw new ArgumentNullException(nameof(cameraMatrix)); } if (cameraMatrix != null && distCoeffs == null) { throw new ArgumentNullException(nameof(distCoeffs)); } image.ThrowIfDisposed(); cameraMatrix?.ThrowIfDisposed(); distCoeffs?.ThrowIfDisposed(); using var markerCornersAddress = new ArrayAddress2 <Point2f>(markerCorners); using var markerIdsVec = new VectorOfInt32(markerIds); using var diamondCornersVec = new VectorOfVectorPoint2f(); using var diamondIdsVec = new VectorOfVec4i(); NativeMethods.HandleException( NativeMethods.aruco_detectCharucoDiamond( image.CvPtr, markerCornersAddress.GetPointer(), markerCornersAddress.GetDim1Length(), markerCornersAddress.GetDim2Lengths(), markerIdsVec.CvPtr, squareMarkerLengthRate, diamondCornersVec.CvPtr, diamondIdsVec.CvPtr, cameraMatrix?.CvPtr ?? IntPtr.Zero, distCoeffs?.CvPtr ?? IntPtr.Zero)); diamondCorners = diamondCornersVec.ToArray(); diamondIds = diamondIdsVec.ToArray(); GC.KeepAlive(image); if (cameraMatrix != null) { GC.KeepAlive(cameraMatrix); } if (distCoeffs != null) { GC.KeepAlive(distCoeffs); } }
/// <summary> /// Draw detected markers in image /// </summary> /// <param name="image">input/output image. It must have 1 or 3 channels. The number of channels is not altered.</param> /// <param name="corners">positions of marker corners on input image. /// For N detected markers, the dimensions of this array should be Nx4.The order of the corners should be clockwise.</param> /// <param name="ids">vector of identifiers for markers in markersCorners. Optional, if not provided, ids are not painted.</param> /// <param name="borderColor">color of marker borders. Rest of colors (text color and first corner color) /// are calculated based on this one to improve visualization.</param> public static void DrawDetectedMarkers(InputArray image, Point2f[][] corners, IEnumerable <int>?ids, Scalar borderColor) { if (image == null) { throw new ArgumentNullException(nameof(image)); } if (corners == null) { throw new ArgumentNullException(nameof(corners)); } using var cornersAddress = new ArrayAddress2 <Point2f>(corners); if (ids == null) { NativeMethods.HandleException( NativeMethods.aruco_drawDetectedMarkers( image.CvPtr, cornersAddress.GetPointer(), cornersAddress.GetDim1Length(), cornersAddress.GetDim2Lengths(), IntPtr.Zero, 0, borderColor)); } else { var idxArray = ids.ToArray(); NativeMethods.HandleException( NativeMethods.aruco_drawDetectedMarkers( image.CvPtr, cornersAddress.GetPointer(), cornersAddress.GetDim1Length(), cornersAddress.GetDim2Lengths(), idxArray, idxArray.Length, borderColor)); } GC.KeepAlive(image); }