diff --git a/.circleci/config.yml b/.circleci/config.yml
index 29c772c73..dbce45322 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -126,9 +126,22 @@ jobs:
LD_LIBRARY_PATH=. dotnet test OpenCvSharp.Tests.csproj -c Release -f netcoreapp3.0 --runtime ubuntu.16.04-x64 --logger "trx;LogFileName=test-results.trx"
ls
ls TestResults
+ cat /root/project/test/OpenCvSharp.Tests/TestResults/test-results.trx
+
+ - run:
+ name: .trx to JUnit
+ when: always
+ command: |
+ dotnet tool install -g trx2junit
+ export PATH="$PATH:/root/.dotnet/tools"
+ trx2junit /root/project/test/OpenCvSharp.Tests/TestResults/*.trx
- store_test_results:
- path: /root/project/test/OpenCvSharp.Tests/TestResults/test-results.trx
+ path: /root/project/test/OpenCvSharp.Tests/TestResults/
+
+ - store_artifacts:
+ path: /root/project/test/OpenCvSharp.Tests/TestResults/
+ destination: TestResults
- save_cache:
key: heavy_test_files_rev3
diff --git a/OpenCvSharp.sln b/OpenCvSharp.sln
index daf7fa69b..9ef12c826 100644
--- a/OpenCvSharp.sln
+++ b/OpenCvSharp.sln
@@ -36,6 +36,10 @@ Global
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
+ FxCop|Any CPU = FxCop|Any CPU
+ FxCop|ARM = FxCop|ARM
+ FxCop|x64 = FxCop|x64
+ FxCop|x86 = FxCop|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
@@ -54,6 +58,14 @@ Global
{EB310923-197F-4E20-B123-3A3E7F1D5069}.Debug|x64.Build.0 = Debug|Any CPU
{EB310923-197F-4E20-B123-3A3E7F1D5069}.Debug|x86.ActiveCfg = Debug|Any CPU
{EB310923-197F-4E20-B123-3A3E7F1D5069}.Debug|x86.Build.0 = Debug|Any CPU
+ {EB310923-197F-4E20-B123-3A3E7F1D5069}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
+ {EB310923-197F-4E20-B123-3A3E7F1D5069}.FxCop|Any CPU.Build.0 = Release|Any CPU
+ {EB310923-197F-4E20-B123-3A3E7F1D5069}.FxCop|ARM.ActiveCfg = Release|Any CPU
+ {EB310923-197F-4E20-B123-3A3E7F1D5069}.FxCop|ARM.Build.0 = Release|Any CPU
+ {EB310923-197F-4E20-B123-3A3E7F1D5069}.FxCop|x64.ActiveCfg = FxCop|Any CPU
+ {EB310923-197F-4E20-B123-3A3E7F1D5069}.FxCop|x64.Build.0 = FxCop|Any CPU
+ {EB310923-197F-4E20-B123-3A3E7F1D5069}.FxCop|x86.ActiveCfg = FxCop|Any CPU
+ {EB310923-197F-4E20-B123-3A3E7F1D5069}.FxCop|x86.Build.0 = FxCop|Any CPU
{EB310923-197F-4E20-B123-3A3E7F1D5069}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB310923-197F-4E20-B123-3A3E7F1D5069}.Release|Any CPU.Build.0 = Release|Any CPU
{EB310923-197F-4E20-B123-3A3E7F1D5069}.Release|ARM.ActiveCfg = Release|Any CPU
@@ -78,6 +90,14 @@ Global
{FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.Debug|x64.Build.0 = Debug|Any CPU
{FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.Debug|x86.ActiveCfg = Debug|Any CPU
{FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.Debug|x86.Build.0 = Debug|Any CPU
+ {FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
+ {FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.FxCop|Any CPU.Build.0 = Release|Any CPU
+ {FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.FxCop|ARM.ActiveCfg = Release|Any CPU
+ {FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.FxCop|ARM.Build.0 = Release|Any CPU
+ {FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.FxCop|x64.ActiveCfg = Release|Any CPU
+ {FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.FxCop|x64.Build.0 = Release|Any CPU
+ {FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.FxCop|x86.ActiveCfg = Release|Any CPU
+ {FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.FxCop|x86.Build.0 = Release|Any CPU
{FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.Release|Any CPU.Build.0 = Release|Any CPU
{FFBBCF99-97F0-4F81-AAF6-8D851A8E1D2E}.Release|ARM.ActiveCfg = Release|Any CPU
@@ -102,6 +122,14 @@ Global
{82AFDA65-515E-4EC0-A415-77D8A6711508}.Debug|x64.Build.0 = Debug|Any CPU
{82AFDA65-515E-4EC0-A415-77D8A6711508}.Debug|x86.ActiveCfg = Debug|Any CPU
{82AFDA65-515E-4EC0-A415-77D8A6711508}.Debug|x86.Build.0 = Debug|Any CPU
+ {82AFDA65-515E-4EC0-A415-77D8A6711508}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
+ {82AFDA65-515E-4EC0-A415-77D8A6711508}.FxCop|Any CPU.Build.0 = Release|Any CPU
+ {82AFDA65-515E-4EC0-A415-77D8A6711508}.FxCop|ARM.ActiveCfg = Release|Any CPU
+ {82AFDA65-515E-4EC0-A415-77D8A6711508}.FxCop|ARM.Build.0 = Release|Any CPU
+ {82AFDA65-515E-4EC0-A415-77D8A6711508}.FxCop|x64.ActiveCfg = Release|Any CPU
+ {82AFDA65-515E-4EC0-A415-77D8A6711508}.FxCop|x64.Build.0 = Release|Any CPU
+ {82AFDA65-515E-4EC0-A415-77D8A6711508}.FxCop|x86.ActiveCfg = Release|Any CPU
+ {82AFDA65-515E-4EC0-A415-77D8A6711508}.FxCop|x86.Build.0 = Release|Any CPU
{82AFDA65-515E-4EC0-A415-77D8A6711508}.Release|Any CPU.ActiveCfg = Release|Any CPU
{82AFDA65-515E-4EC0-A415-77D8A6711508}.Release|Any CPU.Build.0 = Release|Any CPU
{82AFDA65-515E-4EC0-A415-77D8A6711508}.Release|ARM.ActiveCfg = Release|Any CPU
@@ -126,6 +154,14 @@ Global
{B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.Debug|x64.Build.0 = Debug|Any CPU
{B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.Debug|x86.ActiveCfg = Debug|Any CPU
{B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.Debug|x86.Build.0 = Debug|Any CPU
+ {B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
+ {B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.FxCop|Any CPU.Build.0 = Release|Any CPU
+ {B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.FxCop|ARM.ActiveCfg = Release|Any CPU
+ {B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.FxCop|ARM.Build.0 = Release|Any CPU
+ {B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.FxCop|x64.ActiveCfg = Release|Any CPU
+ {B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.FxCop|x64.Build.0 = Release|Any CPU
+ {B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.FxCop|x86.ActiveCfg = Release|Any CPU
+ {B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.FxCop|x86.Build.0 = Release|Any CPU
{B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.Release|Any CPU.Build.0 = Release|Any CPU
{B4B78BB2-1B7C-4CF2-BC72-43789EEDCE00}.Release|ARM.ActiveCfg = Release|Any CPU
@@ -146,6 +182,13 @@ Global
{8E7279F8-F801-4672-B42F-1ED2C68B16A4}.Debug|ARM.ActiveCfg = Debug|Win32
{8E7279F8-F801-4672-B42F-1ED2C68B16A4}.Debug|x64.ActiveCfg = Debug|x64
{8E7279F8-F801-4672-B42F-1ED2C68B16A4}.Debug|x86.ActiveCfg = Debug|Win32
+ {8E7279F8-F801-4672-B42F-1ED2C68B16A4}.FxCop|Any CPU.ActiveCfg = Release|x64
+ {8E7279F8-F801-4672-B42F-1ED2C68B16A4}.FxCop|Any CPU.Build.0 = Release|x64
+ {8E7279F8-F801-4672-B42F-1ED2C68B16A4}.FxCop|ARM.ActiveCfg = Release|Win32
+ {8E7279F8-F801-4672-B42F-1ED2C68B16A4}.FxCop|x64.ActiveCfg = Release|x64
+ {8E7279F8-F801-4672-B42F-1ED2C68B16A4}.FxCop|x64.Build.0 = Release|x64
+ {8E7279F8-F801-4672-B42F-1ED2C68B16A4}.FxCop|x86.ActiveCfg = Release|Win32
+ {8E7279F8-F801-4672-B42F-1ED2C68B16A4}.FxCop|x86.Build.0 = Release|Win32
{8E7279F8-F801-4672-B42F-1ED2C68B16A4}.Release|Any CPU.ActiveCfg = Release|x64
{8E7279F8-F801-4672-B42F-1ED2C68B16A4}.Release|Any CPU.Build.0 = Release|x64
{8E7279F8-F801-4672-B42F-1ED2C68B16A4}.Release|ARM.ActiveCfg = Release|Win32
@@ -169,6 +212,14 @@ Global
{4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.Debug|x64.Build.0 = Debug|Any CPU
{4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.Debug|x86.ActiveCfg = Debug|Any CPU
{4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.Debug|x86.Build.0 = Debug|Any CPU
+ {4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
+ {4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.FxCop|Any CPU.Build.0 = Release|Any CPU
+ {4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.FxCop|ARM.ActiveCfg = Release|Any CPU
+ {4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.FxCop|ARM.Build.0 = Release|Any CPU
+ {4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.FxCop|x64.ActiveCfg = Release|Any CPU
+ {4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.FxCop|x64.Build.0 = Release|Any CPU
+ {4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.FxCop|x86.ActiveCfg = Release|Any CPU
+ {4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.FxCop|x86.Build.0 = Release|Any CPU
{4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.Release|Any CPU.Build.0 = Release|Any CPU
{4232CB4A-DFE3-46CA-9503-C5F1798BAED3}.Release|ARM.ActiveCfg = Release|Any CPU
@@ -193,6 +244,14 @@ Global
{E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.Debug|x64.Build.0 = Debug|Any CPU
{E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.Debug|x86.ActiveCfg = Debug|Any CPU
{E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.Debug|x86.Build.0 = Debug|Any CPU
+ {E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
+ {E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.FxCop|Any CPU.Build.0 = Release|Any CPU
+ {E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.FxCop|ARM.ActiveCfg = Release|Any CPU
+ {E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.FxCop|ARM.Build.0 = Release|Any CPU
+ {E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.FxCop|x64.ActiveCfg = Release|Any CPU
+ {E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.FxCop|x64.Build.0 = Release|Any CPU
+ {E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.FxCop|x86.ActiveCfg = Release|Any CPU
+ {E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.FxCop|x86.Build.0 = Release|Any CPU
{E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.Release|Any CPU.Build.0 = Release|Any CPU
{E2C8C528-B7C7-40AF-BB7F-1147A41E2E23}.Release|ARM.ActiveCfg = Release|Any CPU
@@ -217,6 +276,14 @@ Global
{CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.Debug|x64.Build.0 = Debug|Any CPU
{CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.Debug|x86.ActiveCfg = Debug|Any CPU
{CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.Debug|x86.Build.0 = Debug|Any CPU
+ {CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
+ {CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.FxCop|Any CPU.Build.0 = Release|Any CPU
+ {CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.FxCop|ARM.ActiveCfg = Release|Any CPU
+ {CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.FxCop|ARM.Build.0 = Release|Any CPU
+ {CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.FxCop|x64.ActiveCfg = Release|Any CPU
+ {CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.FxCop|x64.Build.0 = Release|Any CPU
+ {CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.FxCop|x86.ActiveCfg = Release|Any CPU
+ {CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.FxCop|x86.Build.0 = Release|Any CPU
{CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.Release|Any CPU.Build.0 = Release|Any CPU
{CC19F9A5-01A7-4BDF-B34C-CF56F46A474A}.Release|ARM.ActiveCfg = Release|Any CPU
@@ -240,6 +307,13 @@ Global
{BD5471E5-7B55-5192-8DA4-042B66AF71AE}.Debug|x64.Build.0 = Debug|x64
{BD5471E5-7B55-5192-8DA4-042B66AF71AE}.Debug|x86.ActiveCfg = Debug|Win32
{BD5471E5-7B55-5192-8DA4-042B66AF71AE}.Debug|x86.Build.0 = Debug|Win32
+ {BD5471E5-7B55-5192-8DA4-042B66AF71AE}.FxCop|Any CPU.ActiveCfg = Release|Win32
+ {BD5471E5-7B55-5192-8DA4-042B66AF71AE}.FxCop|ARM.ActiveCfg = Release|ARM
+ {BD5471E5-7B55-5192-8DA4-042B66AF71AE}.FxCop|ARM.Build.0 = Release|ARM
+ {BD5471E5-7B55-5192-8DA4-042B66AF71AE}.FxCop|x64.ActiveCfg = Release|x64
+ {BD5471E5-7B55-5192-8DA4-042B66AF71AE}.FxCop|x64.Build.0 = Release|x64
+ {BD5471E5-7B55-5192-8DA4-042B66AF71AE}.FxCop|x86.ActiveCfg = Release|Win32
+ {BD5471E5-7B55-5192-8DA4-042B66AF71AE}.FxCop|x86.Build.0 = Release|Win32
{BD5471E5-7B55-5192-8DA4-042B66AF71AE}.Release|Any CPU.ActiveCfg = Release|Win32
{BD5471E5-7B55-5192-8DA4-042B66AF71AE}.Release|ARM.ActiveCfg = Release|ARM
{BD5471E5-7B55-5192-8DA4-042B66AF71AE}.Release|ARM.Build.0 = Release|ARM
diff --git a/OpenCvSharp.sln.DotSettings b/OpenCvSharp.sln.DotSettings
index f43529724..15089eca3 100644
--- a/OpenCvSharp.sln.DotSettings
+++ b/OpenCvSharp.sln.DotSettings
@@ -51,6 +51,7 @@
True
True
True
+ True
True
True
diff --git a/src/OpenCvSharp.Extensions/CvExtensions.cs b/src/OpenCvSharp.Extensions/CvExtensions.cs
index 510d61561..ab377e58a 100644
--- a/src/OpenCvSharp.Extensions/CvExtensions.cs
+++ b/src/OpenCvSharp.Extensions/CvExtensions.cs
@@ -62,7 +62,7 @@ public static class CvExtensions
if (minLineLength <= 0)
throw new ArgumentOutOfRangeException(nameof(minLineLength));
if (thetaMax < thetaMin)
- throw new ArgumentException();
+ throw new ArgumentException("thetaMax < thetaMin");
if (thetaMax > Math.PI)
throw new ArgumentOutOfRangeException(nameof(thetaMax), "thetaMax <= pi");
if (thetaMin < 0)
diff --git a/src/OpenCvSharp/OpenCvSharp.csproj b/src/OpenCvSharp/OpenCvSharp.csproj
index d3c2c5476..93c5d09a5 100644
--- a/src/OpenCvSharp/OpenCvSharp.csproj
+++ b/src/OpenCvSharp/OpenCvSharp.csproj
@@ -12,12 +12,12 @@
false
false
false
- Debug;Release;Release-JP
+ Debug;Release;Release-JP;FxCop
8
enable
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/OpenCvSharp/PInvoke/NativeMethods/NativeMethods_imgcodecs.cs b/src/OpenCvSharp/PInvoke/NativeMethods/NativeMethods_imgcodecs.cs
index 377cf6578..f00e8b847 100644
--- a/src/OpenCvSharp/PInvoke/NativeMethods/NativeMethods_imgcodecs.cs
+++ b/src/OpenCvSharp/PInvoke/NativeMethods/NativeMethods_imgcodecs.cs
@@ -8,15 +8,15 @@ namespace OpenCvSharp
{
static partial class NativeMethods
{
- [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true, CharSet = CharSet.Ansi)]
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true)]
public static extern ExceptionStatus imgcodecs_imread(
[MarshalAs(StringUnmanagedType)] string filename, int flags, out IntPtr returnValue);
- [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true, CharSet = CharSet.Ansi)]
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true)]
public static extern ExceptionStatus imgcodecs_imreadmulti(
[MarshalAs(StringUnmanagedType)] string filename, IntPtr mats, int flags, out int returnValue);
- [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true, CharSet = CharSet.Ansi)]
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true)]
public static extern ExceptionStatus imgcodecs_imwrite(
[MarshalAs(StringUnmanagedType)] string filename, IntPtr img, [In] int[] @params, int paramsLength, out int returnValue);
@@ -36,15 +36,15 @@ static partial class NativeMethods
public static extern ExceptionStatus imgcodecs_imdecode_InputArray(
IntPtr buf, int flags, out IntPtr returnValue);
- [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true, CharSet = CharSet.Ansi)]
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true)]
public static extern ExceptionStatus imgcodecs_imencode_vector(
[MarshalAs(StringUnmanagedType)] string ext, IntPtr img, IntPtr buf, [In] int[] @params, int paramsLength, out int returnValue);
- [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true, CharSet = CharSet.Ansi)]
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true)]
public static extern ExceptionStatus imgcodecs_haveImageReader(
[MarshalAs(StringUnmanagedType)] string fileName, out int returnValue);
- [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true, CharSet = CharSet.Ansi)]
+ [Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true, ExactSpelling = true)]
public static extern ExceptionStatus imgcodecs_haveImageWriter(
[MarshalAs(StringUnmanagedType)] string fileName, out int returnValue);
}
diff --git a/src/OpenCvSharp/PInvoke/NativeMethods/dnn/NativeMethods_dnn.cs b/src/OpenCvSharp/PInvoke/NativeMethods/dnn/NativeMethods_dnn.cs
index f0a0f9fcd..25c9c016a 100644
--- a/src/OpenCvSharp/PInvoke/NativeMethods/dnn/NativeMethods_dnn.cs
+++ b/src/OpenCvSharp/PInvoke/NativeMethods/dnn/NativeMethods_dnn.cs
@@ -14,40 +14,40 @@ static partial class NativeMethods
{
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readNetFromDarknet(
- [MarshalAs(UnmanagedType.LPStr)] string cfgFile, [MarshalAs(UnmanagedType.LPStr)] string? darknetModel, out IntPtr returnValue);
+ [MarshalAs(StringUnmanagedType)] string cfgFile, [MarshalAs(UnmanagedType.LPStr)] string? darknetModel, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readNetFromCaffe(
- [MarshalAs(UnmanagedType.LPStr)] string prototxt, [MarshalAs(UnmanagedType.LPStr)] string? caffeModel, out IntPtr returnValue);
+ [MarshalAs(StringUnmanagedType)] string prototxt, [MarshalAs(UnmanagedType.LPStr)] string? caffeModel, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readNetFromTensorflow(
- [MarshalAs(UnmanagedType.LPStr)] string model, [MarshalAs(UnmanagedType.LPStr)] string? config, out IntPtr returnValue);
+ [MarshalAs(StringUnmanagedType)] string model, [MarshalAs(UnmanagedType.LPStr)] string? config, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readNetFromTorch(
- [MarshalAs(UnmanagedType.LPStr)] string model, int isBinary, out IntPtr returnValue);
+ [MarshalAs(StringUnmanagedType)] string model, int isBinary, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readNet(
- [MarshalAs(UnmanagedType.LPStr)] string model, [MarshalAs(UnmanagedType.LPStr)] string config, [MarshalAs(UnmanagedType.LPStr)] string framework,
+ [MarshalAs(StringUnmanagedType)] string model, [MarshalAs(UnmanagedType.LPStr)] string config, [MarshalAs(UnmanagedType.LPStr)] string framework,
out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readTorchBlob(
- [MarshalAs(UnmanagedType.LPStr)] string filename, int isBinary, out IntPtr returnValue);
+ [MarshalAs(StringUnmanagedType)] string filename, int isBinary, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readNetFromModelOptimizer(
- [MarshalAs(UnmanagedType.LPStr)] string xml, [MarshalAs(UnmanagedType.LPStr)] string bin, out IntPtr returnValue);
+ [MarshalAs(StringUnmanagedType)] string xml, [MarshalAs(UnmanagedType.LPStr)] string bin, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readNetFromONNX(
- [MarshalAs(UnmanagedType.LPStr)] string onnxFile, out IntPtr returnValue);
+ [MarshalAs(StringUnmanagedType)] string onnxFile, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_readTensorFromONNX(
- [MarshalAs(UnmanagedType.LPStr)] string path, out IntPtr returnValue);
+ [MarshalAs(StringUnmanagedType)] string path, out IntPtr returnValue);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
@@ -60,11 +60,11 @@ static partial class NativeMethods
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_shrinkCaffeModel(
- [MarshalAs(UnmanagedType.LPStr)] string src, [MarshalAs(UnmanagedType.LPStr)] string dst);
+ [MarshalAs(StringUnmanagedType)] string src, [MarshalAs(UnmanagedType.LPStr)] string dst);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_writeTextGraph(
- [MarshalAs(UnmanagedType.LPStr)] string model, [MarshalAs(UnmanagedType.LPStr)] string output);
+ [MarshalAs(StringUnmanagedType)] string model, [MarshalAs(UnmanagedType.LPStr)] string output);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern ExceptionStatus dnn_NMSBoxes_Rect(
diff --git a/test/OpenCvSharp.Tests/OpenCvSharp.Tests.csproj b/test/OpenCvSharp.Tests/OpenCvSharp.Tests.csproj
index 1e7c4af69..53d968afe 100644
--- a/test/OpenCvSharp.Tests/OpenCvSharp.Tests.csproj
+++ b/test/OpenCvSharp.Tests/OpenCvSharp.Tests.csproj
@@ -45,6 +45,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
+
all
@@ -53,6 +54,10 @@
+
+
+
+
$(DefineConstants);DOTNET_FRAMEWORK;
diff --git a/test/OpenCvSharp.Tests/TestBase.cs b/test/OpenCvSharp.Tests/TestBase.cs
index c218ec3a1..1bf7109b9 100644
--- a/test/OpenCvSharp.Tests/TestBase.cs
+++ b/test/OpenCvSharp.Tests/TestBase.cs
@@ -22,7 +22,13 @@ static TestBase()
{
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
- httpClient = new HttpClient
+ ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
+
+ var handler = new HttpClientHandler
+ {
+ ServerCertificateCustomValidationCallback = delegate { return true; }
+ };
+ httpClient = new HttpClient(handler)
{
Timeout = TimeSpan.FromMinutes(5)
};
@@ -95,8 +101,8 @@ protected static byte[] DownloadBytes(Uri uri)
{
using var client = new MyWebClient();
return client.DownloadData(uri);
- //var response = (await httpClient.GetAsync(url)).EnsureSuccessStatusCode();
- //return await response.Content.ReadAsByteArrayAsync();
+ //var response = (httpClient.GetAsync(uri).Result).EnsureSuccessStatusCode();
+ //return response.Content.ReadAsByteArrayAsync().Result;
}
private static byte[] DownloadAndCacheBytes(Uri uri, string fileName)
diff --git a/test/OpenCvSharp.Tests/_data/image/abbey_road.jpg b/test/OpenCvSharp.Tests/_data/image/abbey_road.jpg
new file mode 100644
index 000000000..76068d229
Binary files /dev/null and b/test/OpenCvSharp.Tests/_data/image/abbey_road.jpg differ
diff --git a/test/OpenCvSharp.Tests/dnn/CaffeTest.cs b/test/OpenCvSharp.Tests/dnn/CaffeTest.cs
index 8a4f064a9..9697a0485 100644
--- a/test/OpenCvSharp.Tests/dnn/CaffeTest.cs
+++ b/test/OpenCvSharp.Tests/dnn/CaffeTest.cs
@@ -8,9 +8,16 @@
namespace OpenCvSharp.Tests.Dnn
{
public class CaffeTest : TestBase
- {
+ {
+ private static readonly object lockObj = new object();
+
private readonly ITestOutputHelper testOutputHelper;
+ public CaffeTest(ITestOutputHelper testOutputHelper)
+ {
+ this.testOutputHelper = testOutputHelper;
+ }
+
// https://docs.opencv.org/3.3.0/d5/de7/tutorial_dnn_googlenet.html
[Fact]
public void LoadCaffeModel()
@@ -47,6 +54,11 @@ public void LoadCaffeModel()
Assert.Equal(812, classId);
}
+ ///
+ /// Download model file
+ ///
+ ///
+ ///
private static void PrepareModel(Uri uri, string fileName)
{
lock (lockObj)
@@ -58,12 +70,6 @@ private static void PrepareModel(Uri uri, string fileName)
}
}
}
- private static readonly object lockObj = new object();
-
- public CaffeTest(ITestOutputHelper testOutputHelper)
- {
- this.testOutputHelper = testOutputHelper;
- }
///
/// Find best class for the blob (i. e. class with maximal probability)
diff --git a/test/OpenCvSharp.Tests/dnn/EastTextDetectionTest.cs b/test/OpenCvSharp.Tests/dnn/EastTextDetectionTest.cs
new file mode 100644
index 000000000..3d6e0d8de
--- /dev/null
+++ b/test/OpenCvSharp.Tests/dnn/EastTextDetectionTest.cs
@@ -0,0 +1,238 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using ICSharpCode.SharpZipLib.GZip;
+using ICSharpCode.SharpZipLib.Tar;
+using OpenCvSharp.Dnn;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace OpenCvSharp.Tests.Dnn
+{
+ ///
+ /// https://github.com/opencv/opencv/blob/master/samples/dnn/text_detection.cpp
+ ///
+ ///
+ ///
+ public class EastTextDetectionTest : TestBase
+ {
+ // https://github.com/opencv/opencv_extra/blob/322b475403899abc2411c4fbf68318afa77d3191/testdata/dnn/download_models.py#L302
+ const string ModelUrl = "https://www.dropbox.com/s/r2ingd0l3zt8hxs/frozen_east_text_detection.tar.gz?dl=1";
+ const string LocalRawModelPath = "_data/model/frozen_east_text_detection.tar.gz";
+ const string LocalModelPath = "_data/model/frozen_east_text_detection.pb";
+
+ private static readonly object lockObj = new object();
+
+ private readonly ITestOutputHelper testOutputHelper;
+
+ ///
+ /// Download model file
+ ///
+ ///
+ public EastTextDetectionTest(ITestOutputHelper testOutputHelper)
+ {
+ this.testOutputHelper = testOutputHelper ?? throw new ArgumentNullException(nameof(testOutputHelper));
+
+ testOutputHelper.WriteLine("Downloading EAST Model...");
+ PrepareModel(new Uri(ModelUrl), LocalRawModelPath);
+ testOutputHelper.WriteLine("Done");
+ Assert.True(File.Exists(LocalRawModelPath), $"'{LocalRawModelPath}' not found");
+
+ if (!File.Exists(LocalModelPath))
+ {
+ var modelDirectory = Path.GetDirectoryName(LocalRawModelPath)!;
+ ExtractTarGz(LocalRawModelPath, modelDirectory);
+ }
+
+ var fileInfo = new FileInfo(LocalModelPath);
+ Assert.True(fileInfo.Exists, $"'{LocalModelPath}' not found");
+ Assert.True(fileInfo.Length > 90 * 1024 * 1024, $"Too small data ('{fileInfo.Length}' bytes)");
+ }
+
+ ///
+ /// Download model file if it does not exist on local disk
+ ///
+ ///
+ ///
+ private static void PrepareModel(Uri uri, string fileName)
+ {
+ lock (lockObj)
+ {
+ if (!File.Exists(fileName))
+ {
+ var contents = DownloadBytes(uri);
+ File.WriteAllBytes(fileName, contents);
+ }
+ }
+ }
+
+ ///
+ /// Simple full extract from a TGZ
+ /// https://github.com/icsharpcode/SharpZipLib/wiki/GZip-and-Tar-Samples
+ ///
+ ///
+ ///
+ private static void ExtractTarGz(string inputFile, string dstFolder)
+ {
+ using var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read);
+ using var gzipStream = new GZipInputStream(inputStream);
+ using var tarArchive = TarArchive.CreateInputTarArchive(gzipStream);
+ tarArchive.ExtractContents(dstFolder);
+ }
+
+ [Fact]
+ public void Load()
+ {
+ Assert.True(File.Exists(LocalModelPath), $"'{LocalModelPath}' not found");
+
+ using var net = CvDnn.ReadNet(LocalModelPath);
+ }
+
+ [Fact]
+ public void NotSupportedUnicodeFileName()
+ {
+ Assert.True(File.Exists(LocalModelPath), $"'{LocalModelPath}' not found");
+
+ var unicodeFileName = Path.Combine(Path.GetDirectoryName(LocalModelPath)!, "🤣🍀.pb");
+ if (!File.Exists(unicodeFileName))
+ {
+ File.Copy(LocalModelPath, unicodeFileName, true);
+ }
+
+ // Check that ArgumentException(unicode unmappable char) does not occur.
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ var ex = Assert.Throws(() =>
+ {
+ using var net = CvDnn.ReadNet(unicodeFileName);
+ });
+ Assert.StartsWith("FAILED: fs.is_open(). Can't open", ex.Message, StringComparison.InvariantCulture);
+ Assert.Equal("cv::dnn::ReadProtoFromBinaryFile", ex.FuncName);
+ }
+ else
+ {
+ // No error
+ }
+ }
+
+ ///
+ /// detect text from image.
+ ///
+ ///
+ /// Name of the image file.
+ /// The loader factory.
+ /// Scanned text.
+ [Theory]
+ [InlineData("_data/image/abbey_road.jpg")]
+ public void DetectAllText(string fileName)
+ {
+ const int InputWidth = 320;
+ const int InputHeight = 320;
+ const float ConfThreshold = 0.5f;
+ const float NmsThreshold = 0.4f;
+
+ // Load network.
+ using (Net net = CvDnn.ReadNet(Path.GetFullPath(LocalModelPath)))
+ using (Mat img = new Mat(fileName))
+
+ // Prepare input image
+ using (var blob = CvDnn.BlobFromImage(img, 1.0, new Size(InputWidth, InputHeight), new Scalar(123.68, 116.78, 103.94), true, false))
+ {
+ // Forward Pass
+ // Now that we have prepared the input, we will pass it through the network. There are two outputs of the network.
+ // One specifies the geometry of the Text-box and the other specifies the confidence score of the detected box.
+ // These are given by the layers :
+ // feature_fusion/concat_3
+ // feature_fusion/Conv_7/Sigmoid
+ var outputBlobNames = new string[] { "feature_fusion/Conv_7/Sigmoid", "feature_fusion/concat_3" };
+ var outputBlobs = outputBlobNames.Select(_ => new Mat()).ToArray();
+
+ net.SetInput(blob);
+ net.Forward(outputBlobs, outputBlobNames);
+ Mat scores = outputBlobs[0];
+ Mat geometry = outputBlobs[1];
+
+ // Decode predicted bounding boxes (decode the positions of the text boxes along with their orientation)
+ Decode(scores, geometry, ConfThreshold, out var boxes, out var confidences);
+
+ // Apply non-maximum suppression procedure for filtering out the false positives and get the final predictions
+ CvDnn.NMSBoxes(boxes, confidences, ConfThreshold, NmsThreshold, out var indices);
+
+ // Render detections.
+ Point2f ratio = new Point2f((float)img.Cols / InputWidth, (float)img.Rows / InputHeight);
+ for (var i = 0; i < indices.Length; ++i)
+ {
+ RotatedRect box = boxes[indices[i]];
+
+ Point2f[] vertices = box.Points();
+
+ for (int j = 0; j < 4; ++j)
+ {
+ vertices[j].X *= ratio.X;
+ vertices[j].Y *= ratio.Y;
+ }
+
+ for (int j = 0; j < 4; ++j)
+ {
+ Cv2.Line(img, (int)vertices[j].X, (int)vertices[j].Y, (int)vertices[(j + 1) % 4].X, (int)vertices[(j + 1) % 4].Y, new Scalar(0, 255, 0), 3);
+ }
+ }
+
+ ShowImagesWhenDebugMode(img);
+ }
+ }
+
+ private unsafe void Decode(Mat scores, Mat geometry, float confThreshold, out IList boxes, out IList confidences)
+ {
+ boxes = new List();
+ confidences = new List();
+
+ if ((scores == null || scores.Dims != 4 || scores.Size(0) != 1 || scores.Size(1) != 1) ||
+ (geometry == null || geometry.Dims != 4 || geometry.Size(0) != 1 || geometry.Size(1) != 5) ||
+ (scores.Size(2) != geometry.Size(2) || scores.Size(3) != geometry.Size(3)))
+ {
+ return;
+ }
+
+ int height = scores.Size(2);
+ int width = scores.Size(3);
+
+ for (int y = 0; y < height; ++y)
+ {
+ var scoresData = new ReadOnlySpan((void*)scores.Ptr(0, 0, y), height);
+ var x0Data = new ReadOnlySpan((void*)geometry.Ptr(0, 0, y), height);
+ var x1Data = new ReadOnlySpan((void*)geometry.Ptr(0, 1, y), height);
+ var x2Data = new ReadOnlySpan((void*)geometry.Ptr(0, 2, y), height);
+ var x3Data = new ReadOnlySpan((void*)geometry.Ptr(0, 3, y), height);
+ var anglesData = new ReadOnlySpan((void*)geometry.Ptr(0, 4, y), height);
+
+ for (int x = 0; x < width; ++x)
+ {
+ var score = scoresData[x];
+ if (score >= confThreshold)
+ {
+ float offsetX = x * 4.0f;
+ float offsetY = y * 4.0f;
+ float angle = anglesData[x];
+ float cosA = (float)Math.Cos(angle);
+ float sinA = (float)Math.Sin(angle);
+ float x0 = x0Data[x];
+ float x1 = x1Data[x];
+ float x2 = x2Data[x];
+ float x3 = x3Data[x];
+ float h = x0 + x2;
+ float w = x1 + x3;
+ Point2f offset = new Point2f(offsetX + (cosA * x1) + (sinA * x2), offsetY - (sinA * x1) + (cosA * x2));
+ Point2f p1 = new Point2f((-sinA * h) + offset.X, (-cosA * h) + offset.Y);
+ Point2f p3 = new Point2f((-cosA * w) + offset.X, (sinA * w) + offset.Y);
+ RotatedRect r = new RotatedRect(new Point2f(0.5f * (p1.X + p3.X), 0.5f * (p1.Y + p3.Y)), new Size2f(w, h), (float)(-angle * 180.0f / Math.PI));
+ boxes.Add(r);
+ confidences.Add(score);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/OpenCvSharp.Tests/imgcodecs/ImgCodecsTest.cs b/test/OpenCvSharp.Tests/imgcodecs/ImgCodecsTest.cs
index e4b2b7679..430a48295 100644
--- a/test/OpenCvSharp.Tests/imgcodecs/ImgCodecsTest.cs
+++ b/test/OpenCvSharp.Tests/imgcodecs/ImgCodecsTest.cs
@@ -50,27 +50,31 @@ public void ImReadDoesNotSupportGif()
[Fact]
public void ImReadUnicodeFileName()
{
- // TODO
- if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- return;
+ // https://github.com/opencv/opencv/issues/4242
const string fileName = "_data/image/imread♥♡😀😄.png";
+ const string fileNameTemp = "_data/image/imread_test_image.png";
// Check whether the path is valid
+ // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
Path.GetFullPath(fileName);
{
using var bitmap = new Bitmap(10, 10, PixelFormat.Format24bppRgb);
using var graphics = Graphics.FromImage(bitmap);
graphics.Clear(Color.Red);
- bitmap.Save(fileName, ImageFormat.Png);
+ bitmap.Save(fileNameTemp, ImageFormat.Png);
}
+ File.Move(fileNameTemp, fileName);
Assert.True(File.Exists(fileName), $"File '{fileName}' not found");
using var image = Cv2.ImRead(fileName, ImreadModes.Color);
Assert.NotNull(image);
- Assert.True(image.Empty());
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ Assert.True(image.Empty()); // TODO
+ else
+ Assert.False(image.Empty());
}
[Theory]
@@ -94,12 +98,19 @@ public void ImWrite(string ext)
}
}
- [Fact(Skip = "no output")]
+ //[Fact(Skip = "no output")]
+ [Fact]
public void ImWriteUnicodeFileName()
{
+ // https://github.com/opencv/opencv/issues/4242
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ return; // TODO
+
const string fileName = "_data/image/imwrite♥♡😀😄.png";
// Check whether the path is valid
+ // ReSharper disable once ReturnValueOfPureMethodIsNotUsed
Path.GetFullPath(fileName);
using (var mat = new Mat(10, 20, MatType.CV_8UC3, Scalar.Blue))
@@ -110,7 +121,9 @@ public void ImWriteUnicodeFileName()
// TODO fail
Assert.True(File.Exists(fileName), $"File '{fileName}' not found");
- using (var bitmap = new Bitmap(fileName))
+ const string asciiFileName = "_data/image/imwrite_unicode_test.png";
+ File.Move(fileName, asciiFileName);
+ using (var bitmap = new Bitmap(asciiFileName))
{
Assert.Equal(10, bitmap.Height);
Assert.Equal(20, bitmap.Width);
diff --git a/test/OpenCvSharp.Tests/quality/QualityGMSDTest.cs b/test/OpenCvSharp.Tests/quality/QualityGMSDTest.cs
index 9d9e9839a..b46c6cf7d 100644
--- a/test/OpenCvSharp.Tests/quality/QualityGMSDTest.cs
+++ b/test/OpenCvSharp.Tests/quality/QualityGMSDTest.cs
@@ -17,7 +17,7 @@ public void Compute()
var value = psnr.Compute(targetImage);
Assert.Equal(0.0616, value[0], 4);
Assert.Equal(0.0711, value[1], 4);
- Assert.Equal(0.05983, value[2], 6);
+ Assert.Equal(0.05983, value[2], 5);
}
}
@@ -32,7 +32,7 @@ public void StaticCompute()
var value = QualityGMSD.Compute(refImage, targetImage, null);
Assert.Equal(0.0616, value[0], 4);
Assert.Equal(0.0711, value[1], 4);
- Assert.Equal(0.05983, value[2], 6);
+ Assert.Equal(0.05983, value[2], 5);
}
}
}