/// <summary> /// /// </summary> /// <param name="featuresFinder"></param> /// <param name="images"></param> /// <param name="features"></param> /// <param name="masks"></param> public static void ComputeImageFeatures( Feature2D featuresFinder, IEnumerable <Mat> images, out ImageFeatures[] features, IEnumerable <Mat>?masks = null) { if (featuresFinder == null) { throw new ArgumentNullException(nameof(featuresFinder)); } if (images == null) { throw new ArgumentNullException(nameof(images)); } featuresFinder.ThrowIfDisposed(); var imagesArray = images as Mat[] ?? images.ToArray(); if (imagesArray.Length == 0) { throw new ArgumentException("Empty array", nameof(images)); } var descriptorsMat = new Mat[imagesArray.Length]; var keypointsVec = new VectorOfKeyPoint[imagesArray.Length]; var wImageFeatures = new WImageFeatures[imagesArray.Length]; for (int i = 0; i < imagesArray.Length; i++) { descriptorsMat[i] = new Mat(); keypointsVec[i] = new VectorOfKeyPoint(); wImageFeatures[i] = new WImageFeatures { Keypoints = keypointsVec[i].CvPtr, Descriptors = descriptorsMat[i].CvPtr }; } var imagesPointers = imagesArray.Select(i => i.CvPtr).ToArray(); var masksPointers = masks?.Select(i => i.CvPtr).ToArray(); if (masksPointers != null && imagesPointers.Length != masksPointers.Length) { throw new ArgumentException("size of images != size of masks"); } var wImageFeaturesPointers = new GCHandle[wImageFeatures.Length]; try { for (int i = 0; i < wImageFeatures.Length; i++) { wImageFeaturesPointers[i] = GCHandle.Alloc(wImageFeatures[i], GCHandleType.Pinned); } if (masksPointers == null) { NativeMethods.HandleException( NativeMethods.stitching_computeImageFeatures1_2( featuresFinder.CvPtr, imagesPointers, imagesPointers.Length, wImageFeaturesPointers.Select(gch => gch.AddrOfPinnedObject()).ToArray(), IntPtr.Zero)); } else { NativeMethods.HandleException( NativeMethods.stitching_computeImageFeatures1_1( featuresFinder.CvPtr, imagesPointers, imagesPointers.Length, wImageFeaturesPointers.Select(gch => gch.AddrOfPinnedObject()).ToArray(), masksPointers)); } } finally { for (int i = 0; i < wImageFeaturesPointers.Length; i++) { wImageFeaturesPointers[i].Free(); } } features = new ImageFeatures[wImageFeatures.Length]; for (int i = 0; i < wImageFeaturesPointers.Length; i++) { features[i] = new ImageFeatures( wImageFeatures[i].ImgIdx, wImageFeatures[i].ImgSize, keypointsVec[i].ToArray(), descriptorsMat[i]); } GC.KeepAlive(featuresFinder); GC.KeepAlive(images); GC.KeepAlive(masks); GC.KeepAlive(descriptorsMat); GC.KeepAlive(imagesPointers); }