diff --git a/core.cpp b/core.cpp index 7c9f141f..8a2e287a 100644 --- a/core.cpp +++ b/core.cpp @@ -654,7 +654,14 @@ void Mat_Min(Mat src1, Mat src2, Mat dst) { } void Mat_MinMaxIdx(Mat m, double* minVal, double* maxVal, int* minIdx, int* maxIdx) { - cv::minMaxIdx(*m, minVal, maxVal, minIdx, maxIdx); + int cMinIdx[m->dims]; + int cMaxIdx[m->dims]; + cv::minMaxIdx(*m, minVal, maxVal, cMinIdx, cMaxIdx); + + for(unsigned int a = 0; a < sizeof(cMinIdx)/sizeof(cMinIdx[0]); a++) { + minIdx[a] = cMinIdx[a]; + maxIdx[a] = cMaxIdx[a]; + } } void Mat_MinMaxLoc(Mat m, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc) { diff --git a/core.go b/core.go index 70ebd302..d87a4121 100644 --- a/core.go +++ b/core.go @@ -1512,15 +1512,37 @@ func Min(src1, src2 Mat, dst *Mat) { // // For further details, please see: // https://docs.opencv.org/master/d2/de8/group__core__array.html#ga7622c466c628a75d9ed008b42250a73f -func MinMaxIdx(input Mat) (minVal, maxVal float32, minIdx, maxIdx int) { +func MinMaxIdx(input Mat) (minVal, maxVal float32, minIdx, maxIdx []int) { var cMinVal C.double var cMaxVal C.double - var cMinIdx C.int - var cMaxIdx C.int - C.Mat_MinMaxIdx(input.p, &cMinVal, &cMaxVal, &cMinIdx, &cMaxIdx) + dims := len(input.Size()) + cMinIdx := (*C.int)(C.malloc(C.size_t(C.sizeof_int * dims))) + cMaxIdx := (*C.int)(C.malloc(C.size_t(C.sizeof_int * dims))) + defer C.free(unsafe.Pointer(cMinIdx)) + defer C.free(unsafe.Pointer(cMaxIdx)) - return float32(cMinVal), float32(cMaxVal), int(minIdx), int(maxIdx) + C.Mat_MinMaxIdx(input.p, &cMinVal, &cMaxVal, cMinIdx, cMaxIdx) + + h := &reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(cMinIdx)), + Len: dims, + Cap: dims, + } + minIndex := *(*[]C.int)(unsafe.Pointer(h)) + + h = &reflect.SliceHeader{ + Data: uintptr(unsafe.Pointer(cMaxIdx)), + Len: dims, + Cap: dims, + } + maxIndex := *(*[]C.int)(unsafe.Pointer(h)) + + for i := 0; i < dims; i++ { + minIdx = append(minIdx, int(minIndex[i])) + maxIdx = append(maxIdx, int(maxIndex[i])) + } + return float32(cMinVal), float32(cMaxVal), minIdx, maxIdx } // MinMaxLoc finds the global minimum and maximum in an array. diff --git a/core_test.go b/core_test.go index cce5d3ff..d4b70252 100644 --- a/core_test.go +++ b/core_test.go @@ -2574,14 +2574,59 @@ func TestMatMinMaxIdx(t *testing.T) { src.SetFloatAt(3, 3, 17) src.SetFloatAt(4, 4, 16) - minVal, maxVal, _, _ := MinMaxIdx(src) - + minVal, maxVal, minIdx, maxIdx := MinMaxIdx(src) if minVal != 0 { t.Error("TestMatMinMaxIdx minVal should be 0.") } if maxVal != 17 { t.Errorf("TestMatMinMaxIdx maxVal should be 17, was %f", maxVal) } + if minIdx[0] != 0 || minIdx[1] != 0 { + t.Errorf("TestMatMinMaxIdx minIdx should be [0,0], was [%d,%d]", minIdx[0], minIdx[1]) + } + if maxIdx[0] != 3 || maxIdx[1] != 3 { + t.Errorf("TestMatMinMaxIdx maxIdx should be [3,3], was [%d,%d]", maxIdx[0], maxIdx[1]) + } +} + +func TestMatMinMaxIdx3d(t *testing.T) { + src := NewMatWithSizes([]int{3,3,3}, MatTypeCV32F) + defer src.Close() + + for x := 0; x < 3; x++ { + for y := 0; y < 3; y++ { + for z := 0; z < 3; z++ { + src.SetFloatAt3(x, y, z, 0) + } + } + } + + src.SetFloatAt3(2, 1, 2, 2) + + minVal, maxVal, minIdx, maxIdx := MinMaxIdx(src) + if len(minIdx) != 3 { + t.Errorf("minIdx should have 3 dimensions. %d found", len(minIdx)) + } + + if len(maxIdx) != 3 { + t.Errorf("maxIdx should have 3 dimensions. %d found", len(maxIdx)) + } + + if minVal != 0 { + t.Errorf("TestMatMinMaxIdx3d minVal expected 0, got %f", minVal) + } + if maxVal != 2 { + t.Errorf("TestMatMinMaxIdx3d maxVal should be 2, was %f", maxVal) + } + + + if maxIdx[0] != 2 || maxIdx[1] != 1 || maxIdx[2] != 2 { + t.Errorf("TestMatMinMaxIdx3d maxIdx should be [2,1,2], was [%d,%d,%d]", maxIdx[0], maxIdx[1], maxIdx[2]) + } + + if minIdx[0] != 0 || minIdx[1] != 0 || minIdx[2] != 0 { + t.Errorf("TestMatMinMaxIdx3d minIdx should be [0,0,0], was [%d,%d,%d]", minIdx[0], minIdx[1], minIdx[2]) + } } func TestMixChannels(t *testing.T) {