Ejemplo n.º 1
0
        /// <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&lt;std::vector&lt;cv::Point2f&gt;&gt;). 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&lt;Vec4i&gt;). 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);
        }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
0
        /// <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);
        }
Ejemplo n.º 5
0
        /// <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&lt;std::vector&lt;cv::Point2f&gt;&gt;).</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);
            }
        }
Ejemplo n.º 6
0
        /// <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());
        }
Ejemplo n.º 7
0
        /// <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&lt;std::vector&lt;cv::Point2f&gt;&gt; ).
        /// 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&lt;cv::Vec3d&gt;).
        /// Each element in rvecs corresponds to the specific marker in imgPoints.</param>
        /// <param name="tvec">array of output translation vectors (e.g. std::vector&lt;cv::Vec3d&gt;).
        /// 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();
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Converts std::vector to managed array
        /// </summary>
        /// <returns></returns>
        public Point[][] ToArray()
        {
            var size1 = GetSize1();

            if (size1 == 0)
            {
                return(Array.Empty <Point[]>());
            }
            var size2 = GetSize2();

            var ret = new Point[size1][];

            for (var i = 0; i < size1; i++)
            {
                ret[i] = new Point[size2[i]];
            }

            using var retPtr = new ArrayAddress2 <Point>(ret);
            NativeMethods.vector_vector_Point_copy(ptr, retPtr.GetPointer());
            GC.KeepAlive(this);
            return(ret);
        }
Ejemplo n.º 9
0
        /// <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());
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Converts std::vector to managed array
        /// </summary>
        /// <returns></returns>
        public DMatch[][] ToArray()
        {
            var size1 = Size1;

            if (size1 == 0)
            {
                return(Array.Empty <DMatch[]>());
            }
            var size2 = Size2;

            var ret = new DMatch[size1][];

            for (var i = 0; i < size1; i++)
            {
                ret[i] = new DMatch[size2[i]];
            }
            using (var retPtr = new ArrayAddress2 <DMatch>(ret))
            {
                NativeMethods.vector_vector_DMatch_copy(ptr, retPtr.GetPointer());
                GC.KeepAlive(this);
            }
            return(ret);
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Draws the found matches of keypoints from two images.
        /// </summary>
        /// <param name="img1">First source image.</param>
        /// <param name="keypoints1">Keypoints from the first source image.</param>
        /// <param name="img2">Second source image.</param>
        /// <param name="keypoints2">Keypoints from the second source image.</param>
        /// <param name="matches1To2">Matches from the first image to the second one, which means that keypoints1[i]
        /// has a corresponding point in keypoints2[matches[i]] .</param>
        /// <param name="outImg">Output image. Its content depends on the flags value defining what is drawn in the
        /// output image. See possible flags bit values below.</param>
        /// <param name="matchColor">Color of matches (lines and connected keypoints). If matchColor==Scalar::all(-1),
        /// the color is generated randomly.</param>
        /// <param name="singlePointColor">Color of single keypoints (circles), which means that keypoints do not
        /// have the matches. If singlePointColor==Scalar::all(-1) , the color is generated randomly.</param>
        /// <param name="matchesMask">Mask determining which matches are drawn. If the mask is empty, all matches are drawn.</param>
        /// <param name="flags">Flags setting drawing features. Possible flags bit values are defined by DrawMatchesFlags.</param>
        public static void DrawMatchesKnn(
            Mat img1,
            IEnumerable <KeyPoint> keypoints1,
            Mat img2,
            IEnumerable <KeyPoint> keypoints2,
            IEnumerable <IEnumerable <DMatch> > matches1To2,
            Mat outImg,
            Scalar?matchColor       = null,
            Scalar?singlePointColor = null,
            IEnumerable <IEnumerable <byte> >?matchesMask = null,
            DrawMatchesFlags flags = DrawMatchesFlags.Default)
        {
            if (img1 == null)
            {
                throw new ArgumentNullException(nameof(img1));
            }
            if (img2 == null)
            {
                throw new ArgumentNullException(nameof(img2));
            }
            if (outImg == null)
            {
                throw new ArgumentNullException(nameof(outImg));
            }
            if (keypoints1 == null)
            {
                throw new ArgumentNullException(nameof(keypoints1));
            }
            if (keypoints2 == null)
            {
                throw new ArgumentNullException(nameof(keypoints2));
            }
            if (matches1To2 == null)
            {
                throw new ArgumentNullException(nameof(matches1To2));
            }
            img1.ThrowIfDisposed();
            img2.ThrowIfDisposed();
            outImg.ThrowIfDisposed();

            var keypoints1Array   = keypoints1.CastOrToArray();
            var keypoints2Array   = keypoints2.CastOrToArray();
            var matches1To2Array  = matches1To2.Select(m => m.ToArray()).ToArray();
            var matches1To2Size1  = matches1To2Array.Length;
            var matches1To2Size2  = matches1To2Array.Select(dm => dm.Length).ToArray();
            var matchColor0       = matchColor.GetValueOrDefault(Scalar.All(-1));
            var singlePointColor0 = singlePointColor.GetValueOrDefault(Scalar.All(-1));

            using var matches1To2Ptr = new ArrayAddress2 <DMatch>(matches1To2Array);
            if (matchesMask == null)
            {
                NativeMethods.HandleException(
                    NativeMethods.features2d_drawMatchesKnn(
                        img1.CvPtr, keypoints1Array, keypoints1Array.Length,
                        img2.CvPtr, keypoints2Array, keypoints2Array.Length,
                        matches1To2Ptr.GetPointer(), matches1To2Size1, matches1To2Size2,
                        outImg.CvPtr, matchColor0, singlePointColor0,
                        null, 0, null, (int)flags));
            }
            else
            {
                var matchesMaskArray = matchesMask.Select(m => m.ToArray()).ToArray();
                var matchesMaskSize1 = matches1To2Array.Length;
                var matchesMaskSize2 = matchesMaskArray.Select(dm => dm.Length).ToArray();
                using var matchesMaskPtr = new ArrayAddress2 <byte>(matchesMaskArray);
                NativeMethods.HandleException(
                    NativeMethods.features2d_drawMatchesKnn(
                        img1.CvPtr, keypoints1Array, keypoints1Array.Length,
                        img2.CvPtr, keypoints2Array, keypoints2Array.Length,
                        matches1To2Ptr.GetPointer(), matches1To2Size1, matches1To2Size2,
                        outImg.CvPtr, matchColor0, singlePointColor0,
                        matchesMaskPtr.GetPointer(), matchesMaskSize1, matchesMaskSize2, (int)flags));
            }
            GC.KeepAlive(img1);
            GC.KeepAlive(img2);
            GC.KeepAlive(outImg);
        }