Skip to content

Commit

Permalink
imgproc: add EMD()
Browse files Browse the repository at this point in the history
Signed-off-by: deadprogram <[email protected]>
  • Loading branch information
deadprogram committed Oct 19, 2023
1 parent 2c0b2b9 commit 70f4a77
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 2 deletions.
3 changes: 1 addition & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ Your pull requests will be greatly appreciated!
- [ ] ColorMaps in OpenCV
- [ ] Planar Subdivision
- [ ] **Histograms - WORK STARTED** The following functions still need implementation:
- [ ] [EMD](https://docs.opencv.org/master/d6/dc7/group__imgproc__hist.html#ga902b8e60cc7075c8947345489221e0e0)
- [ ] [wrapperEMD](https://docs.opencv.org/master/d6/dc7/group__imgproc__hist.html#ga31fdda0864e64ca6b9de252a2611758b)
- [X] [EMD](https://docs.opencv.org/master/d6/dc7/group__imgproc__hist.html#ga902b8e60cc7075c8947345489221e0e0)

- [ ] **Structural Analysis and Shape Descriptors - WORK STARTED** The following functions still need implementation:
- [ ] [fitEllipse](https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#gaf259efaad93098103d6c27b9e4900ffa)
Expand Down
4 changes: 4 additions & 0 deletions imgproc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ double CompareHist(Mat hist1, Mat hist2, int method) {
return cv::compareHist(*hist1, *hist2, method);
}

float EMD(Mat sig1, Mat sig2, int distType) {
return cv::EMD(*sig1, *sig2, distType);
}

struct RotatedRect FitEllipse(PointVector pts)
{
cv::RotatedRect bRect = cv::fitEllipse(*pts);
Expand Down
8 changes: 8 additions & 0 deletions imgproc.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ func CompareHist(hist1 Mat, hist2 Mat, method HistCompMethod) float32 {
return float32(C.CompareHist(hist1.p, hist2.p, C.int(method)))
}

// EMD Computes the "minimal work" distance between two weighted point configurations.
//
// For further details, please see:
// https://docs.opencv.org/4.x/d6/dc7/group__imgproc__hist.html#ga902b8e60cc7075c8947345489221e0e0
func EMD(signature1, signature2 Mat, typ DistanceTypes) float32 {
return float32(C.EMD(signature1.p, signature2.p, C.int(typ)))
}

// ClipLine clips the line against the image rectangle.
// For further details, please see:
// https://docs.opencv.org/master/d6/d6e/group__imgproc__draw.html#gaf483cb46ad6b049bc35ec67052ef1c2c
Expand Down
1 change: 1 addition & 0 deletions imgproc.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void EqualizeHist(Mat src, Mat dst);
void CalcHist(struct Mats mats, IntVector chans, Mat mask, Mat hist, IntVector sz, FloatVector rng, bool acc);
void CalcBackProject(struct Mats mats, IntVector chans, Mat hist, Mat backProject, FloatVector rng, bool uniform);
double CompareHist(Mat hist1, Mat hist2, int method);
float EMD(Mat sig1, Mat sig2, int distType);
void ConvexHull(PointVector points, Mat hull, bool clockwise, bool returnPoints);
void ConvexityDefects(PointVector points, Mat hull, Mat result);
void BilateralFilter(Mat src, Mat dst, int d, double sc, double ss);
Expand Down
46 changes: 46 additions & 0 deletions imgproc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,52 @@ func TestCompareHist(t *testing.T) {

}

func TestEMD(t *testing.T) {
img := IMRead("images/face-detect.jpg", IMReadUnchanged)
if img.Empty() {
t.Error("Invalid read of Mat in CompareHist test")
}
defer img.Close()

hist1 := NewMat()
defer hist1.Close()

hist2 := NewMat()
defer hist2.Close()

mask := NewMat()
defer mask.Close()

CalcHist([]Mat{img}, []int{0, 1}, mask, &hist1, []int{30, 32}, []float64{0.0, 180.0, 0.0, 255.0}, false)
CalcHist([]Mat{img}, []int{0, 1}, mask, &hist2, []int{30, 32}, []float64{0.0, 180.0, 0.0, 255.0}, false)

sig1 := NewMatWithSize(30*32, 3, MatTypeCV32FC1)
defer sig1.Close()

sig2 := NewMatWithSize(30*32, 3, MatTypeCV32FC1)
defer sig2.Close()

for h := 0; h < 30; h++ {
for s := 0; s < 32; s++ {
val := hist1.GetFloatAt(h, s)
sig1.SetFloatAt(h*32+s, 0, val)
sig1.SetFloatAt(h*32+s, 1, float32(h))
sig1.SetFloatAt(h*32+s, 2, float32(s))

val = hist2.GetFloatAt(h, s)
sig2.SetFloatAt(h*32+s, 0, val)
sig2.SetFloatAt(h*32+s, 1, float32(h))
sig2.SetFloatAt(h*32+s, 2, float32(s))
}
}

sim := EMD(sig1, sig2, DistL2)
if (1-sim)*100 < 99.9 {
t.Error("Invalid EMD test", (1-sim)*100)
}

}

func TestDrawing(t *testing.T) {
img := NewMatWithSize(150, 150, MatTypeCV8U)
if img.Empty() {
Expand Down

0 comments on commit 70f4a77

Please sign in to comment.