From 73f802638d801580f93fe6da1cd4cc52a09106e5 Mon Sep 17 00:00:00 2001 From: Canming Huang Date: Wed, 26 May 2021 14:32:04 -0400 Subject: [PATCH] Fixed issue #158. Removed FlipType.None --- Emgu.CV.Cuda/CudaInvoke.cs | 11 +- Emgu.CV/Core/Image.cs | 169 +++++++++++++------------- Emgu.CV/Imgproc/ConvolutionKernelF.cs | 7 +- Emgu.CV/PInvoke/CvEnum/FlipType.cs | 9 +- Emgu.CV/PInvoke/CvInvokeCore.cs | 17 +-- Emgu.CV/Videoio/VideoCapture.cs | 84 ++++++++++--- 6 files changed, 161 insertions(+), 136 deletions(-) diff --git a/Emgu.CV.Cuda/CudaInvoke.cs b/Emgu.CV.Cuda/CudaInvoke.cs index 812f3ee32..9d4b0a31b 100644 --- a/Emgu.CV.Cuda/CudaInvoke.cs +++ b/Emgu.CV.Cuda/CudaInvoke.cs @@ -903,19 +903,12 @@ namespace Emgu.CV.Cuda /// Use a Stream to call the function asynchronously (non-blocking) or null to call the function synchronously (blocking). public static void Flip(IInputArray src, IOutputArray dst, CvEnum.FlipType flipType, Stream stream = null) { - int flipMode = - //-1 indicates vertical and horizontal flip - flipType == (Emgu.CV.CvEnum.FlipType.Horizontal | Emgu.CV.CvEnum.FlipType.Vertical) ? -1 : - //1 indicates horizontal flip only - flipType == Emgu.CV.CvEnum.FlipType.Horizontal ? 1 : - //0 indicates vertical flip only - 0; using (InputArray iaSrc = src.GetInputArray()) using (OutputArray oaDst = dst.GetOutputArray()) - cudaFlip(iaSrc, oaDst, flipMode, stream); + cudaFlip(iaSrc, oaDst, flipType, stream); } [DllImport(CvInvoke.ExternCudaLibrary, CallingConvention = CvInvoke.CvCallingConvention)] - private static extern void cudaFlip(IntPtr src, IntPtr dst, int flipMode, IntPtr stream); + private static extern void cudaFlip(IntPtr src, IntPtr dst, CvEnum.FlipType flipMode, IntPtr stream); #region Logical operators diff --git a/Emgu.CV/Core/Image.cs b/Emgu.CV/Core/Image.cs index d0355cb6a..abab71206 100644 --- a/Emgu.CV/Core/Image.cs +++ b/Emgu.CV/Core/Image.cs @@ -246,9 +246,9 @@ namespace Emgu.CV } } } -#endregion + #endregion -#region Implement ISerializable interface + #region Implement ISerializable interface /// /// Constructor used to deserialize runtime serialized object /// @@ -281,9 +281,9 @@ namespace Emgu.CV info.AddValue("Roi", ROI); } } -#endregion + #endregion -#region Image Properties + #region Image Properties /// /// The IplImage structure @@ -424,9 +424,9 @@ namespace Emgu.CV res.MCvScalar = CvInvoke.Sum(this); return res; } -#endregion + #endregion -#region Coping and Filling + #region Coping and Filling /// /// Set every pixel of the image to the specific color /// @@ -540,11 +540,11 @@ namespace Emgu.CV CvInvoke.cvSetImageCOI(Ptr, 0); //clear COI for current image ROI = Rectangle.Empty; // clear ROI for current image -#region create a clone of the current image with the same COI and ROI + #region create a clone of the current image with the same COI and ROI Image res = Copy(); CvInvoke.cvSetImageCOI(res.Ptr, coi); res.ROI = roi; -#endregion + #endregion CvInvoke.cvSetImageCOI(Ptr, coi); //reset the COI for the current image ROI = roi; // reset the ROI for the current image @@ -568,10 +568,10 @@ namespace Emgu.CV return subRect; } -#endregion + #endregion -#region Drawing functions + #region Drawing functions /// Draw an Rectangle of the specific color and thickness /// The rectangle to be drawn /// The color of the rectangle @@ -813,9 +813,9 @@ namespace Emgu.CV } } -#endregion + #endregion -#region Hough line and circles + #region Hough line and circles /// /// Apply Probabilistic Hough transform to find line segments. /// The current image must be a binary image (eg. the edges as a result of the Canny edge detector) @@ -880,9 +880,9 @@ namespace Emgu.CV return CvInvoke.HoughCircles(img, CvEnum.HoughModes.Gradient, dp, minDist, cannyThresh[channel], accumulatorThresh[channel], minRadius, maxRadius); }); } -#endregion + #endregion -#region Indexer + #region Indexer /// /// Get or Set the specific channel of the current image. /// For Get operation, a copy of the specific channel is returned. @@ -940,9 +940,9 @@ namespace Emgu.CV this[location.Y, location.X] = value; } } -#endregion + #endregion -#region utilities + #region utilities /// /// Return parameters based on ROI /// @@ -1029,9 +1029,9 @@ namespace Emgu.CV } } } -#endregion + #endregion -#region Gradient, Edges and Features + #region Gradient, Edges and Features /// /// Calculates the image derivative by convolving the image with the appropriate kernel /// The Sobel operators combine Gaussian smoothing and differentiation so the result is more or less robust to the noise. Most often, the function is called with (xorder=1, yorder=0, aperture_size=3) or (xorder=0, yorder=1, aperture_size=3) to calculate first x- or y- image derivative. @@ -1119,9 +1119,9 @@ namespace Emgu.CV }); } -#endregion + #endregion -#region Matching + #region Matching /// /// The function slides through image, compares overlapped patches of size wxh with templ using the specified method and return the comparison results /// @@ -1134,10 +1134,10 @@ namespace Emgu.CV CvInvoke.MatchTemplate(this, template, res, method); return res; } -#endregion + #endregion -#region Logic -#region And Methods + #region Logic + #region And Methods /// Perform an elementwise AND operation with another image and return the result /// The second image for the AND operation /// The result of the AND operation @@ -1182,9 +1182,9 @@ namespace Emgu.CV } return res; } -#endregion + #endregion -#region Or Methods + #region Or Methods /// Perform an elementwise OR operation with another image and return the result /// The second image for the OR operation /// The result of the OR operation @@ -1224,9 +1224,9 @@ namespace Emgu.CV } return res; } -#endregion + #endregion -#region Xor Methods + #region Xor Methods /// Perform an elementwise XOR operation with another image and return the result /// The second image for the XOR operation /// The result of the XOR operation @@ -1274,7 +1274,7 @@ namespace Emgu.CV } return res; } -#endregion + #endregion /// /// Compute the complement image @@ -1286,9 +1286,9 @@ namespace Emgu.CV CvInvoke.BitwiseNot(this, res, null); return res; } -#endregion + #endregion -#region Comparison + #region Comparison /// Find the elementwise maximum value /// The second image for the Max operation /// An image where each pixel is the maximum of this image and the parameter image @@ -1468,9 +1468,9 @@ namespace Emgu.CV } } } -#endregion + #endregion -#region Segmentation + #region Segmentation /// /// Use grabcut to perform background foreground segmentation. /// @@ -1488,10 +1488,10 @@ namespace Emgu.CV } return mask; } -#endregion + #endregion -#region Arithmatic -#region Subtraction methods + #region Arithmatic + #region Subtraction methods /// Elementwise subtract another image from the current image /// The second image to be subtracted from the current image /// The result of elementwise subtracting img2 from the current image @@ -1553,9 +1553,9 @@ namespace Emgu.CV } return res; } -#endregion + #endregion -#region Addition methods + #region Addition methods /// Elementwise add another image with the current image /// The image to be added to the current image /// The result of elementwise adding img2 to the current image @@ -1588,9 +1588,9 @@ namespace Emgu.CV } return res; } -#endregion + #endregion -#region Multiplication methods + #region Multiplication methods /// Elementwise multiply another image with the current image and the /// The image to be elementwise multiplied to the current image /// The scale to be multiplied @@ -1620,7 +1620,7 @@ namespace Emgu.CV CvInvoke.cvConvertScale(Ptr, res.Ptr, scale, 0.0); return res; } -#endregion + #endregion /// /// Accumulate to the current image using the specific mask @@ -1704,9 +1704,9 @@ namespace Emgu.CV } return res; } -#endregion + #endregion -#region Math Functions + #region Math Functions /// /// Raises every element of input array to p /// dst(I)=src(I)^p, if p is integer @@ -1747,9 +1747,9 @@ namespace Emgu.CV CvInvoke.Log(this, res); return res; } -#endregion + #endregion -#region Sampling, Interpolation and Geometrical Transforms + #region Sampling, Interpolation and Geometrical Transforms /* /// Sample the pixel values on the specific line segment /// The line to obtain samples @@ -1982,9 +1982,9 @@ namespace Emgu.CV return imgPolar; } -#endregion + #endregion -#region Image color and depth conversion + #region Image color and depth conversion /// Convert the current image to the specific color and depth /// The type of color to be converted to /// The type of pixel depth to be converted to @@ -2028,7 +2028,7 @@ namespace Emgu.CV if (typeof(TColor) == typeof(TSrcColor)) { -#region same color + #region same color if (typeof(TDepth) == typeof(TSrcDepth)) { //same depth srcImage.Mat.CopyTo(this); @@ -2067,11 +2067,11 @@ namespace Emgu.CV } } } -#endregion + #endregion } else { -#region different color + #region different color if (typeof(TDepth) == typeof(TSrcDepth)) { //same depth CvInvoke.CvtColor(srcImage, this, typeof(TSrcColor), typeof(TColor)); @@ -2080,7 +2080,7 @@ namespace Emgu.CV { //different depth if (typeof(TSrcDepth) == typeof(Byte)) { //Do color conversion first, then depth conversion - using (Image< TColor, TSrcDepth > tmp = srcImage.Convert()) + using (Image tmp = srcImage.Convert()) { this.ConvertFrom(tmp); } @@ -2088,14 +2088,14 @@ namespace Emgu.CV else { //Do depth conversion first, then color conversion using (Image tmp = srcImage.Convert()) //convert depth - //using (Mat tmp = new CV.Mat()) + //using (Mat tmp = new CV.Mat()) { //srcImage.Mat.ConvertTo(tmp, CvInvoke.GetDepthType(typeof(TDepth), CvInvoke.CvtColor(tmp, this, typeof(TSrcColor), typeof(TColor)); } } } -#endregion + #endregion } } @@ -2123,7 +2123,7 @@ namespace Emgu.CV int srcImageNumberOfChannels = iaSrcImage.GetChannels(); if (NumberOfChannels == srcImageNumberOfChannels) { -#region same color + #region same color DepthType srcImageDepth = iaSrcImage.GetDepth(); if (CvInvoke.GetDepthType(typeof(TDepth)) == srcImageDepth) @@ -2169,7 +2169,7 @@ namespace Emgu.CV } } -#endregion + #endregion } else { @@ -2182,7 +2182,7 @@ namespace Emgu.CV ? typeof(Bgr) : typeof(Bgra); -#region different color + #region different color DepthType srcImageDepth = iaSrcImage.GetDepth(); if (CvInvoke.GetDepthType(typeof(TDepth)) == srcImageDepth) { @@ -2202,7 +2202,7 @@ namespace Emgu.CV } } -#endregion + #endregion } } } @@ -2224,9 +2224,9 @@ namespace Emgu.CV return res; } -#endregion + #endregion -#region Pyramids + #region Pyramids /// /// Performs downsampling step of Gaussian pyramid decomposition. /// First it convolves this image with the specified filter and then downsamples the image @@ -2272,9 +2272,9 @@ namespace Emgu.CV return pyr; } -#endregion + #endregion -#region Special Image Transforms + #region Special Image Transforms /// Use inpaint to recover the intensity of the pixels which location defined by on this image /// The inpainting mask. Non-zero pixels indicate the area that needs to be inpainted /// The radius of circular neighborhood of each point inpainted that is considered by the algorithm @@ -2285,9 +2285,9 @@ namespace Emgu.CV CvInvoke.Inpaint(this, mask, res, radius, CvEnum.InpaintType.Telea); return res; } -#endregion + #endregion -#region Morphological Operations + #region Morphological Operations /// /// Perform advanced morphological transformations using erosion and dilation as basic operations. /// @@ -2371,9 +2371,9 @@ namespace Emgu.CV { CvInvoke.Dilate(this, this, null, new Point(-1, -1), iterations, CvEnum.BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue); } -#endregion + #endregion -#region generic operations + #region generic operations /// /// perform an generic action based on each element of the image /// @@ -2679,9 +2679,9 @@ namespace Emgu.CV return res; } -#endregion + #endregion -#region Implment UnmanagedObject + #region Implment UnmanagedObject /// /// Release all unmanaged memory associate with the image /// @@ -2705,9 +2705,9 @@ namespace Emgu.CV _array = null; } -#endregion + #endregion -#region Operator overload + #region Operator overload /// /// Perform an element wise AND operation on the two images @@ -3007,9 +3007,9 @@ namespace Emgu.CV return res; } -#endregion + #endregion -#region Filters + #region Filters /// /// Summation over a pixel param1 x param2 neighborhood with subsequent scaling by 1/(param1 x param2) /// @@ -3064,7 +3064,7 @@ namespace Emgu.CV return res; } -#region Gaussian Smooth + #region Gaussian Smooth /// Perform Gaussian Smoothing in the current image and return the result /// The size of the Gaussian kernel ( x ) /// The smoothed image @@ -3186,9 +3186,9 @@ namespace Emgu.CV titledSum = new Image(Width + 1, Height + 1); CvInvoke.Integral(this, sum, squareSum, titledSum, CvEnum.DepthType.Cv64F); } -#endregion + #endregion -#region Threshold methods + #region Threshold methods /// /// Transforms grayscale image to binary image. /// Threshold calculated individually for each pixel. @@ -3336,10 +3336,10 @@ namespace Emgu.CV { ThresholdBase(this, threshold, maxValue, CvEnum.ThresholdType.BinaryInv); } -#endregion -#endregion + #endregion + #endregion -#region Statistic + #region Statistic /// /// Calculates the average value and standard deviation of array elements, independently for each channel /// @@ -3401,17 +3401,15 @@ namespace Emgu.CV { Mat.MinMax(out minValues, out maxValues, out minLocations, out maxLocations); } -#endregion + #endregion -#region Image Flipping + #region Image Flipping /// Return a flipped copy of the current image /// The type of the flipping /// The flipped copy of this image public Image Flip(CvEnum.FlipType flipType) { - if (flipType == Emgu.CV.CvEnum.FlipType.None) return Copy(); - Image res = CopyBlank(); CvInvoke.Flip(this, res, flipType); return res; @@ -3423,17 +3421,14 @@ namespace Emgu.CV [ExposableMethod(Exposable = true, Category = "Transform")] public void _Flip(CvEnum.FlipType flipType) { - if (flipType != Emgu.CV.CvEnum.FlipType.None) - { - CvInvoke.Flip( + CvInvoke.Flip( this, this, flipType); - } } -#endregion + #endregion -#region various + #region various /// /// Concate the current image with another image vertically. @@ -3622,7 +3617,7 @@ namespace Emgu.CV } } } -#endregion + #endregion /// /// This function load the image data from Mat diff --git a/Emgu.CV/Imgproc/ConvolutionKernelF.cs b/Emgu.CV/Imgproc/ConvolutionKernelF.cs index 0dc630fd9..93117ade2 100644 --- a/Emgu.CV/Imgproc/ConvolutionKernelF.cs +++ b/Emgu.CV/Imgproc/ConvolutionKernelF.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; using System.Drawing; +using Emgu.CV.CvEnum; namespace Emgu.CV { @@ -71,15 +72,15 @@ namespace Emgu.CV /// Get a flipped copy of the convolution kernel /// The type of the flipping - /// The flipped copy of this image + /// The flipped copy of this kernel public ConvolutionKernelF Flip(CvEnum.FlipType flipType) { ConvolutionKernelF res = new ConvolutionKernelF(Height, Width); CvInvoke.Flip(this, res, flipType); res.Center = new System.Drawing.Point( - (Center.X == -1 ? -1 : ((flipType & Emgu.CV.CvEnum.FlipType.Horizontal) == Emgu.CV.CvEnum.FlipType.Horizontal ? Width - Center.X - 1 : Center.X)), - (Center.Y == -1 ? -1 : ((flipType & Emgu.CV.CvEnum.FlipType.Vertical) == Emgu.CV.CvEnum.FlipType.Vertical ? Height - Center.Y - 1 : Center.Y))); + (Center.X == -1 ? -1 : (flipType == FlipType.Both || flipType == Emgu.CV.CvEnum.FlipType.Horizontal) ? Width - Center.X - 1 : Center.X), + (Center.Y == -1 ? -1 : (flipType == FlipType.Both || flipType == Emgu.CV.CvEnum.FlipType.Vertical) ? Height - Center.Y - 1 : Center.Y)); return res; } diff --git a/Emgu.CV/PInvoke/CvEnum/FlipType.cs b/Emgu.CV/PInvoke/CvEnum/FlipType.cs index cc7914027..aaf88a649 100644 --- a/Emgu.CV/PInvoke/CvEnum/FlipType.cs +++ b/Emgu.CV/PInvoke/CvEnum/FlipType.cs @@ -9,21 +9,20 @@ namespace Emgu.CV.CvEnum /// /// Enumeration used by cvFlip /// - [Flags] public enum FlipType { /// - /// No flipping + /// Vertical flipping of the image to switch between top-left and bottom-left image origin. /// - None = 0, + Vertical = 0, /// /// Flip horizontally /// Horizontal = 1, /// - /// Flip vertically + /// Flip both vertically and horizontally /// - Vertical = 2 + Both = -1 } } diff --git a/Emgu.CV/PInvoke/CvInvokeCore.cs b/Emgu.CV/PInvoke/CvInvokeCore.cs index ae96b630b..22a2bccb0 100644 --- a/Emgu.CV/PInvoke/CvInvokeCore.cs +++ b/Emgu.CV/PInvoke/CvInvokeCore.cs @@ -1455,27 +1455,20 @@ namespace Emgu.CV /// Specifies how to flip the array. public static void Flip(IInputArray src, IOutputArray dst, CvEnum.FlipType flipType) { - int flipMode = - //-1 indicates vertical and horizontal flip - flipType == (Emgu.CV.CvEnum.FlipType.Horizontal | Emgu.CV.CvEnum.FlipType.Vertical) ? -1 : - //1 indicates horizontal flip only - flipType == Emgu.CV.CvEnum.FlipType.Horizontal ? 1 : - //0 indicates vertical flip only - 0; using (InputArray iaSrc = src.GetInputArray()) using (OutputArray oaDst = dst.GetOutputArray()) - cveFlip(iaSrc, oaDst, flipMode); + cveFlip(iaSrc, oaDst, flipType); } [DllImport(ExternLibrary, CallingConvention = CvInvoke.CvCallingConvention)] - private static extern void cveFlip(IntPtr src, IntPtr dst, int flipMode); + private static extern void cveFlip(IntPtr src, IntPtr dst, CvEnum.FlipType flipMode); /// /// Rotates a 2D array in multiples of 90 degrees. /// - /// input array. - /// output array of the same type as src. The size is the same with ROTATE_180, and the rows and cols are switched for ROTATE_90 and ROTATE_270. - /// an enum to specify how to rotate the array + /// Input array. + /// Output array of the same type as src. The size is the same with ROTATE_180, and the rows and cols are switched for ROTATE_90 and ROTATE_270. + /// A flag to specify how to rotate the array public static void Rotate(IInputArray src, IOutputArray dst, RotateFlags rotateCode) { using (InputArray iaSrc = src.GetInputArray()) diff --git a/Emgu.CV/Videoio/VideoCapture.cs b/Emgu.CV/Videoio/VideoCapture.cs index dfd0f744c..874044dc7 100644 --- a/Emgu.CV/Videoio/VideoCapture.cs +++ b/Emgu.CV/Videoio/VideoCapture.cs @@ -9,6 +9,7 @@ //#define TEST_CAPTURE using System; +using System.Diagnostics; #if WITH_SERVICE_MODEL using System.ServiceModel; #endif @@ -189,7 +190,7 @@ namespace Emgu.CV /// /// the type of flipping /// - private CvEnum.FlipType _flipType = Emgu.CV.CvEnum.FlipType.None; + private CvEnum.FlipType? _flipType = null; /// /// The type of capture source @@ -224,9 +225,9 @@ namespace Emgu.CV } /// - /// Get and set the flip type + /// Get and set the flip type. If null, no flipping will be done. /// - public CvEnum.FlipType FlipType + public CvEnum.FlipType? FlipType { get { @@ -245,12 +246,35 @@ namespace Emgu.CV { get { - return (_flipType & Emgu.CV.CvEnum.FlipType.Horizontal) == Emgu.CV.CvEnum.FlipType.Horizontal; + if (_flipType == null) + return false; + return (_flipType.Value == CvEnum.FlipType.Horizontal) || (_flipType.Value == CvEnum.FlipType.Both); } set { - if (value != FlipHorizontal) - _flipType ^= Emgu.CV.CvEnum.FlipType.Horizontal; + if (_flipType == null) + { + if (value) + _flipType = CvEnum.FlipType.Horizontal; + } + else + { + switch (_flipType.Value) + { + case CvEnum.FlipType.Both: + if (!value) + _flipType = CvEnum.FlipType.Vertical; + break; + case CvEnum.FlipType.Horizontal: + if (!value) + _flipType = null; + break; + case CvEnum.FlipType.Vertical: + if (value) + _flipType = CvEnum.FlipType.Both; + break; + } + } } } @@ -261,12 +285,36 @@ namespace Emgu.CV { get { - return (_flipType & Emgu.CV.CvEnum.FlipType.Vertical) == Emgu.CV.CvEnum.FlipType.Vertical; + if (_flipType == null) + return false; + return (_flipType.Value == CvEnum.FlipType.Vertical) || (_flipType.Value == CvEnum.FlipType.Both); } set { - if (value != FlipVertical) - _flipType ^= Emgu.CV.CvEnum.FlipType.Vertical; + if (_flipType == null) + { + if (value) + _flipType = CvEnum.FlipType.Vertical; + } + else + { + switch (FlipType.Value) + { + case CvEnum.FlipType.Vertical: + if (!value) + _flipType = null; + break; + case CvEnum.FlipType.Horizontal: + if (value) + _flipType = CvEnum.FlipType.Both; + break; + case CvEnum.FlipType.Both: + if (!value) + _flipType = CvEnum.FlipType.Horizontal; + break; + } + + } } } @@ -466,6 +514,7 @@ namespace Emgu.CV { if (eh != null && eh.HandleException(e)) return; + Trace.WriteLine(e.StackTrace); throw new Exception("Capture error", e); } finally @@ -536,20 +585,15 @@ namespace Emgu.CV /// False if no frames has been grabbed public virtual bool Retrieve(IOutputArray image, int flag = 0) { + bool success; using (OutputArray oaImage = image.GetOutputArray()) { - if (FlipType == CvEnum.FlipType.None) - { - return CvInvoke.cveVideoCaptureRetrieve(Ptr, oaImage, flag); - } - else - { - bool success = CvInvoke.cveVideoCaptureRetrieve(Ptr, oaImage, flag); - if (success) - CvInvoke.Flip(image, image, FlipType); - return success; - } + success = CvInvoke.cveVideoCaptureRetrieve(Ptr, oaImage, flag); } + if (success && (FlipType != null)) + CvInvoke.Flip(image, image, FlipType.Value); + + return success; } ///