From 67c1c0d7f596d90eb2a492450029c03fafeb8af5 Mon Sep 17 00:00:00 2001 From: shimat Date: Sun, 27 Mar 2022 16:41:37 +0900 Subject: [PATCH] fix #1402 --- src/OpenCvSharp/Cv2/Cv2_photo.cs | 142 +++++------------- .../photo/NativeMethods_photo.cs | 16 +- src/OpenCvSharpExtern/photo.h | 24 ++- test/OpenCvSharp.Tests/photo/PhotoTest.cs | 55 +++++++ 4 files changed, 118 insertions(+), 119 deletions(-) create mode 100644 test/OpenCvSharp.Tests/photo/PhotoTest.cs diff --git a/src/OpenCvSharp/Cv2/Cv2_photo.cs b/src/OpenCvSharp/Cv2/Cv2_photo.cs index 2f5e50a56..9ff1824c2 100644 --- a/src/OpenCvSharp/Cv2/Cv2_photo.cs +++ b/src/OpenCvSharp/Cv2/Cv2_photo.cs @@ -18,11 +18,11 @@ static partial class Cv2 public static void Inpaint(InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, InpaintMethod flags) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (inpaintMask == null) + if (inpaintMask is null) throw new ArgumentNullException(nameof(inpaintMask)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); inpaintMask.ThrowIfDisposed(); @@ -53,9 +53,9 @@ public static void Inpaint(InputArray src, InputArray inpaintMask, public static void FastNlMeansDenoising(InputArray src, OutputArray dst, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); dst.ThrowIfNotReady(); @@ -85,9 +85,9 @@ public static void FastNlMeansDenoisingColored(InputArray src, OutputArray dst, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); dst.ThrowIfNotReady(); @@ -115,14 +115,15 @@ public static void FastNlMeansDenoisingColored(InputArray src, OutputArray dst, /// Size in pixels of the window that is used to compute weighted average for given pixel. /// Should be odd. Affect performance linearly: greater searchWindowsSize - greater denoising time. Recommended value 21 pixels public static void FastNlMeansDenoisingMulti( - IEnumerable srcImgs, OutputArray dst, + IEnumerable srcImgs, OutputArray dst, int imgToDenoiseIndex, int temporalWindowSize, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) { - if (srcImgs == null) + if (srcImgs is null) throw new ArgumentNullException(nameof(srcImgs)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); + dst.ThrowIfNotReady(); var srcImgPtrs = srcImgs.Select(x => x.CvPtr).ToArray(); @@ -136,41 +137,6 @@ public static void FastNlMeansDenoisingMulti( GC.KeepAlive(srcImgs); } - /// - /// Modification of fastNlMeansDenoising function for images sequence where consequtive images have been captured - /// in small period of time. For example video. This version of the function is for grayscale images or for manual manipulation with colorspaces. - /// - /// Input 8-bit 1-channel, 2-channel or 3-channel images sequence. All images should have the same type and size. - /// Output image with the same size and type as srcImgs images. - /// Target image to denoise index in srcImgs sequence - /// Number of surrounding images to use for target image denoising. - /// Should be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to imgToDenoiseIndex - temporalWindowSize / 2 - /// from srcImgs will be used to denoise srcImgs[imgToDenoiseIndex] image. - /// Parameter regulating filter strength for luminance component. Bigger h value perfectly removes noise but also removes image details, - /// smaller h value preserves details but also preserves some noise - /// Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels - /// Size in pixels of the window that is used to compute weighted average for given pixel. - /// Should be odd. Affect performance linearly: greater searchWindowsSize - greater denoising time. Recommended value 21 pixels - public static void FastNlMeansDenoisingMulti( - IEnumerable srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) - { - var srcImgsAsArrays = srcImgs.Select(m => new InputArray(m)).ToArray(); - try - { - FastNlMeansDenoisingMulti(srcImgsAsArrays, dst, imgToDenoiseIndex, temporalWindowSize, - h, templateWindowSize, searchWindowSize); - } - finally - { - foreach (var img in srcImgsAsArrays) - { - img.Dispose(); - } - } - } - /// /// Modification of fastNlMeansDenoisingMulti function for colored images sequences /// @@ -187,13 +153,13 @@ public static void FastNlMeansDenoisingMulti( /// Size in pixels of the window that is used to compute weighted average for given pixel. /// Should be odd. Affect performance linearly: greater searchWindowsSize - greater denoising time. Recommended value 21 pixels public static void FastNlMeansDenoisingColoredMulti( - IEnumerable srcImgs, OutputArray dst, + IEnumerable srcImgs, OutputArray dst, int imgToDenoiseIndex, int temporalWindowSize, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21) { - if (srcImgs == null) + if (srcImgs is null) throw new ArgumentNullException(nameof(srcImgs)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); dst.ThrowIfNotReady(); var srcImgPtrs = srcImgs.Select(x => x.CvPtr).ToArray(); @@ -207,40 +173,6 @@ public static void FastNlMeansDenoisingColoredMulti( GC.KeepAlive(srcImgs); } - /// - /// Modification of fastNlMeansDenoisingMulti function for colored images sequences - /// - /// Input 8-bit 3-channel images sequence. All images should have the same type and size. - /// Output image with the same size and type as srcImgs images. - /// Target image to denoise index in srcImgs sequence - /// Number of surrounding images to use for target image denoising. Should be odd. - /// Images from imgToDenoiseIndex - temporalWindowSize / 2 to imgToDenoiseIndex - temporalWindowSize / 2 from srcImgs - /// will be used to denoise srcImgs[imgToDenoiseIndex] image. - /// Parameter regulating filter strength for luminance component. Bigger h value perfectly removes noise - /// but also removes image details, smaller h value preserves details but also preserves some noise. - /// The same as h but for color components. - /// Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels - /// Size in pixels of the window that is used to compute weighted average for given pixel. - /// Should be odd. Affect performance linearly: greater searchWindowsSize - greater denoising time. Recommended value 21 pixels - public static void FastNlMeansDenoisingColoredMulti(IEnumerable srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21) - { - var srcImgsAsArrays = srcImgs.Select(m => new InputArray(m)).ToArray(); - try - { - FastNlMeansDenoisingColoredMulti( - srcImgsAsArrays, dst, imgToDenoiseIndex, temporalWindowSize, h, hColor, templateWindowSize, searchWindowSize); - } - finally - { - foreach (var img in srcImgsAsArrays) - { - img.Dispose(); - } - } - } - /// /// Primal-dual algorithm is an algorithm for solving special types of variational problems /// (that is, finding a function to minimize some functional). As the image denoising, @@ -262,9 +194,9 @@ public static void FastNlMeansDenoisingColoredMulti(IEnumerable srcImgs, Ou public static void DenoiseTVL1( IEnumerable observations, Mat result, double lambda = 1.0, int niters = 30) { - if (observations == null) + if (observations is null) throw new ArgumentNullException(nameof(observations)); - if (result == null) + if (result is null) throw new ArgumentNullException(nameof(result)); var observationsPtrs = observations.Select(x => x.CvPtr).ToArray(); @@ -285,11 +217,11 @@ public static void DenoiseTVL1( public static void Decolor( InputArray src, OutputArray grayscale, OutputArray colorBoost) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (grayscale == null) + if (grayscale is null) throw new ArgumentNullException(nameof(grayscale)); - if (colorBoost == null) + if (colorBoost is null) throw new ArgumentNullException(nameof(colorBoost)); src.ThrowIfDisposed(); grayscale.ThrowIfNotReady(); @@ -321,11 +253,11 @@ public static void SeamlessClone( InputArray src, InputArray dst, InputArray? mask, Point p, OutputArray blend, SeamlessCloneMethods flags) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); - if (blend == null) + if (blend is null) throw new ArgumentNullException(nameof(blend)); src.ThrowIfDisposed(); dst.ThrowIfDisposed(); @@ -356,9 +288,9 @@ public static void ColorChange( InputArray src, InputArray? mask, OutputArray dst, float redMul = 1.0f, float greenMul = 1.0f, float blueMul = 1.0f) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); dst.ThrowIfNotReady(); @@ -390,9 +322,9 @@ public static void IlluminationChange( InputArray src, InputArray? mask, OutputArray dst, float alpha = 0.2f, float beta = 0.4f) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); @@ -424,9 +356,9 @@ public static void TextureFlattening( float lowThreshold = 30, float highThreshold = 45, int kernelSize = 3) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); @@ -456,9 +388,9 @@ public static void EdgePreservingFilter( EdgePreservingMethods flags = EdgePreservingMethods.RecursFilter, float sigmaS = 60, float sigmaR = 0.4f) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); @@ -483,9 +415,9 @@ public static void DetailEnhance( InputArray src, OutputArray dst, float sigmaS = 10, float sigmaR = 0.15f) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); @@ -512,11 +444,11 @@ public static void PencilSketch( InputArray src, OutputArray dst1, OutputArray dst2, float sigmaS = 60, float sigmaR = 0.07f, float shadeFactor = 0.02f) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst1 == null) + if (dst1 is null) throw new ArgumentNullException(nameof(dst1)); - if (dst2 == null) + if (dst2 is null) throw new ArgumentNullException(nameof(dst2)); src.ThrowIfDisposed(); @@ -546,9 +478,9 @@ public static void Stylization( InputArray src, OutputArray dst, float sigmaS = 60, float sigmaR = 0.45f) { - if (src == null) + if (src is null) throw new ArgumentNullException(nameof(src)); - if (dst == null) + if (dst is null) throw new ArgumentNullException(nameof(dst)); src.ThrowIfDisposed(); diff --git a/src/OpenCvSharp/Internal/PInvoke/NativeMethods/photo/NativeMethods_photo.cs b/src/OpenCvSharp/Internal/PInvoke/NativeMethods/photo/NativeMethods_photo.cs index f0f8b4c2f..ec9ed0508 100644 --- a/src/OpenCvSharp/Internal/PInvoke/NativeMethods/photo/NativeMethods_photo.cs +++ b/src/OpenCvSharp/Internal/PInvoke/NativeMethods/photo/NativeMethods_photo.cs @@ -12,21 +12,25 @@ namespace OpenCvSharp.Internal static partial class NativeMethods { [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ExceptionStatus photo_inpaint(IntPtr src, IntPtr inpaintMask, + public static extern ExceptionStatus photo_inpaint( + IntPtr src, IntPtr inpaintMask, IntPtr dst, double inpaintRadius, int flags); [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ExceptionStatus photo_fastNlMeansDenoising(IntPtr src, IntPtr dst, float h, + public static extern ExceptionStatus photo_fastNlMeansDenoising( + IntPtr src, IntPtr dst, float h, int templateWindowSize, int searchWindowSize); [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ExceptionStatus photo_fastNlMeansDenoisingColored(IntPtr src, IntPtr dst, + public static extern ExceptionStatus photo_fastNlMeansDenoisingColored( + IntPtr src, IntPtr dst, float h, float hColor, int templateWindowSize, int searchWindowSize); [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - public static extern ExceptionStatus photo_fastNlMeansDenoisingMulti(IntPtr[] srcImgs, int srcImgsLength, - IntPtr dst, int imgToDenoiseIndex, int temporalWindowSize, - float h, int templateWindowSize, int searchWindowSize); + public static extern ExceptionStatus photo_fastNlMeansDenoisingMulti( + IntPtr[] srcImgs, int srcImgsLength, + IntPtr dst, int imgToDenoiseIndex, int temporalWindowSize, + float h, int templateWindowSize, int searchWindowSize); [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] public static extern ExceptionStatus photo_fastNlMeansDenoisingColoredMulti(IntPtr[] srcImgs, int srcImgsLength, diff --git a/src/OpenCvSharpExtern/photo.h b/src/OpenCvSharpExtern/photo.h index 66469b10c..439160967 100644 --- a/src/OpenCvSharpExtern/photo.h +++ b/src/OpenCvSharpExtern/photo.h @@ -31,27 +31,35 @@ CVAPI(ExceptionStatus) photo_fastNlMeansDenoisingColored(cv::_InputArray *src, c END_WRAP } -CVAPI(ExceptionStatus) photo_fastNlMeansDenoisingMulti(cv::_InputArray ** srcImgs, int srcImgsLength, - cv::_OutputArray *dst, int imgToDenoiseIndex, int temporalWindowSize, +CVAPI(ExceptionStatus) photo_fastNlMeansDenoisingMulti(cv::Mat **srcImgs, int srcImgsLength, + cv::_OutputArray* dst, int imgToDenoiseIndex, int temporalWindowSize, float h, int templateWindowSize, int searchWindowSize) { BEGIN_WRAP - std::vector srcImgsVec(srcImgsLength); - for (int i = 0; i < srcImgsLength; i++) + + std::vector srcImgsVec; + for (int i = 0; i < srcImgsLength; i++) srcImgsVec[i] = *srcImgs[i]; - cv::fastNlMeansDenoisingMulti(srcImgsVec, *dst, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize, searchWindowSize); + + cv::fastNlMeansDenoisingMulti( + srcImgsVec, *dst, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize, searchWindowSize); + END_WRAP } -CVAPI(ExceptionStatus) photo_fastNlMeansDenoisingColoredMulti(cv::_InputArray **srcImgs, int srcImgsLength, +CVAPI(ExceptionStatus) photo_fastNlMeansDenoisingColoredMulti(cv::Mat**srcImgs, int srcImgsLength, cv::_OutputArray *dst, int imgToDenoiseIndex, int temporalWindowSize, float h, float hColor, int templateWindowSize, int searchWindowSize) { BEGIN_WRAP - std::vector srcImgsVec(srcImgsLength); + + std::vector srcImgsVec(srcImgsLength); for (int i = 0; i < srcImgsLength; i++) srcImgsVec[i] = *srcImgs[i]; - cv::fastNlMeansDenoisingColoredMulti(srcImgsVec, *dst, imgToDenoiseIndex, temporalWindowSize, h, hColor, templateWindowSize, searchWindowSize); + + cv::fastNlMeansDenoisingColoredMulti( + srcImgsVec, *dst, imgToDenoiseIndex, temporalWindowSize, h, hColor, templateWindowSize, searchWindowSize); + END_WRAP } diff --git a/test/OpenCvSharp.Tests/photo/PhotoTest.cs b/test/OpenCvSharp.Tests/photo/PhotoTest.cs new file mode 100644 index 000000000..f639a6a73 --- /dev/null +++ b/test/OpenCvSharp.Tests/photo/PhotoTest.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace OpenCvSharp.Tests.Photo +{ + public class PhotoTest + { + [Fact] + public void Inpaint() + { + using var src = new Mat("_data/image/mandrill.png", ImreadModes.Color); + using var dst = new Mat(); + using var mask = new Mat(src.Size(), MatType.CV_8UC1, Scalar.All(0)); + + mask.Rectangle(new Rect(65, 15, 130, 30), Scalar.All(255), -1); + + Cv2.Inpaint(src, mask, dst, 2, InpaintMethod.Telea); + + if (Debugger.IsAttached) + Window.ShowImages(src, mask, dst); + } + + [Fact] + public void FastNlMeansDenoising() + { + using var src = new Mat("_data/image/multipage_p1.tif", ImreadModes.Grayscale); + using var dst = new Mat(); + + Cv2.FastNlMeansDenoising(src, dst, 3, 3, 7); + + if (Debugger.IsAttached) + Window.ShowImages(src, dst); + } + + /* + [Fact] + public void FastNlMeansDenoisingMulti() + { + using var src1 = new Mat("_data/image/tsukuba_left.png", ImreadModes.Grayscale); + using var src2 = new Mat("_data/image/tsukuba_right.png", ImreadModes.Grayscale); + using var src3 = new Mat("_data/image/tsukuba_right.png", ImreadModes.Grayscale); + using var dst = new Mat(); + + Cv2.FastNlMeansDenoisingMulti(new[] { src1, src2, src3 }, dst, 1, 3, 3, 3, 7); + + if (Debugger.IsAttached) + Window.ShowImages(src1, src2, dst); + }*/ + } +}