Skip to content

Commit

Permalink
Wrap reduceArgMin and reduceArgMax (#1524)
Browse files Browse the repository at this point in the history
* Wrap reduceArgMin and reduceArgMax

(cherry picked from commit 01f9e24)

* Mark boolean P/Invoke argument with MarshalAs and adapt unit tests

* Fix unit test assertions
  • Loading branch information
uvbkq committed Jan 27, 2023
1 parent 9b5c701 commit cb48695
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/OpenCvSharp/Cv2/Cv2_core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,56 @@ public static double PSNR(InputArray src1, InputArray src2, double r = 255.0)
GC.KeepAlive(mask);
}

/// <summary>
/// Finds indices of max elements along provided axis
/// </summary>
/// <param name="src">Input single-channel array</param>
/// <param name="dst">Output array of type CV_32SC1 with the same dimensionality as src,
/// except for axis being reduced - it should be set to 1.</param>
/// <param name="axis">Axis to reduce along</param>
/// <param name="lastIndex">Whether to get the index of first or last occurrence of max</param>
public static void ReduceArgMax(InputArray src, OutputArray dst, int axis, bool lastIndex = false)
{
if (src == null)
throw new ArgumentNullException(nameof(src));
if (dst == null)
throw new ArgumentNullException(nameof(dst));
src.ThrowIfDisposed();
dst.ThrowIfNotReady();

NativeMethods.HandleException(
NativeMethods.core_reduceArgMax(src.CvPtr, dst.CvPtr, axis, lastIndex));

dst.Fix();
GC.KeepAlive(src);
GC.KeepAlive(dst);
}

/// <summary>
/// Finds indices of min elements along provided axis
/// </summary>
/// <param name="src">Input single-channel array</param>
/// <param name="dst">Output array of type CV_32SC1 with the same dimensionality as src,
/// except for axis being reduced - it should be set to 1.</param>
/// <param name="axis">Axis to reduce along</param>
/// <param name="lastIndex">Whether to get the index of first or last occurrence of min</param>
public static void ReduceArgMin(InputArray src, OutputArray dst, int axis, bool lastIndex = false)
{
if (src == null)
throw new ArgumentNullException(nameof(src));
if (dst == null)
throw new ArgumentNullException(nameof(dst));
src.ThrowIfDisposed();
dst.ThrowIfNotReady();

NativeMethods.HandleException(
NativeMethods.core_reduceArgMin(src.CvPtr, dst.CvPtr, axis, lastIndex));

dst.Fix();
GC.KeepAlive(src);
GC.KeepAlive(dst);
}

/// <summary>
/// finds global minimum and maximum array elements and returns their values and their locations
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ static partial class NativeMethods
public static extern ExceptionStatus core_normalize(IntPtr src, IntPtr dst, double alpha, double beta,
int normType, int dtype, IntPtr mask);

[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus core_reduceArgMax(IntPtr src, IntPtr dst, int axis, [MarshalAs(UnmanagedType.U1)] bool lastIndex);

[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus core_reduceArgMin(IntPtr src, IntPtr dst, int axis, [MarshalAs(UnmanagedType.U1)] bool lastIndex);

[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern ExceptionStatus core_minMaxLoc1(IntPtr src, out double minVal, out double maxVal);
[Pure, DllImport(DllExtern, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
Expand Down
14 changes: 14 additions & 0 deletions src/OpenCvSharpExtern/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,20 @@ CVAPI(ExceptionStatus) core_normalize(
END_WRAP
}

CVAPI(ExceptionStatus) core_reduceArgMax(cv::_InputArray* src, cv::_OutputArray* dst, int axis, bool lastIndex)
{
BEGIN_WRAP
cv::reduceArgMax(*src, *dst, axis, lastIndex);
END_WRAP
}

CVAPI(ExceptionStatus) core_reduceArgMin(cv::_InputArray* src, cv::_OutputArray* dst, int axis, bool lastIndex)
{
BEGIN_WRAP
cv::reduceArgMin(*src, *dst, axis, lastIndex);
END_WRAP
}

CVAPI(ExceptionStatus) core_minMaxLoc1(cv::_InputArray* src, double* minVal, double* maxVal)
{
BEGIN_WRAP
Expand Down
32 changes: 32 additions & 0 deletions test/OpenCvSharp.Tests/core/CoreTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -437,4 +437,36 @@ public void NormVecd()
var norm = Cv2.Norm(vec, NormTypes.L1);
Assert.Equal(3.3333, norm, 9);
}

[Fact]
public void ReduceArgMax()
{
using var src = new Mat(2, 2, MatType.CV_8UC1, new byte[] { 1, 2, 1, 4 });
using var dst = new Mat();

Cv2.ReduceArgMax(src, dst, axis: 0, lastIndex: true);

Assert.Equal(MatType.CV_32SC1, dst.Type());
Assert.Equal(1, dst.Rows);
Assert.Equal(2, dst.Cols);

Assert.Equal(1, dst.At<int>(0, 0)); // max along 1st column [1; 1], taking the last occurence
Assert.Equal(1, dst.At<int>(0, 1)); // max along 2nd column [2; 4]
}

[Fact]
public void ReduceArgMin()
{
using var src = new Mat(2, 2, MatType.CV_8UC1, new byte[] { 2, 1, 4, 4 });
using var dst = new Mat();

Cv2.ReduceArgMin(src, dst, axis: 1, lastIndex: false);

Assert.Equal(MatType.CV_32SC1, dst.Type());
Assert.Equal(2, dst.Rows);
Assert.Equal(1, dst.Cols);

Assert.Equal(1, dst.At<int>(0, 0)); // min along 1st row [2, 1]
Assert.Equal(0, dst.At<int>(1, 0)); // min along 2nd row [4, 4], taking the first occurence
}
}

0 comments on commit cb48695

Please sign in to comment.