From 84b11aeef602f4cbfa71c39b12920f6ac9e355a2 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Thu, 5 Sep 2024 10:37:55 +0200 Subject: [PATCH] cuda: add implementations for AddWeighted and CopyMakeBorder functions Signed-off-by: deadprogram --- cuda/arithm.cpp | 19 +++++++ cuda/arithm.go | 46 +++++++++++++++++ cuda/arithm.h | 2 + cuda/arithm_test.go | 120 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+) diff --git a/cuda/arithm.cpp b/cuda/arithm.cpp index 359e65bb..612b69cc 100644 --- a/cuda/arithm.cpp +++ b/cuda/arithm.cpp @@ -168,3 +168,22 @@ void GpuTranspose(GpuMat src, GpuMat dst, Stream s) { } cv::cuda::transpose(*src, *dst, *s); } + +void GpuAddWeighted(GpuMat src1, double alpha, GpuMat src2, double beta, double gamma, GpuMat dst, int dType, Stream s) { + if (s == NULL) { + cv::cuda::addWeighted(*src1, alpha, *src2, beta, gamma, *dst, dType); + return; + } + + cv::cuda::addWeighted(*src1, alpha, *src2, beta, gamma, *dst, dType, *s); +} + +void GpuCopyMakeBorder(GpuMat src, GpuMat dst, int top, int bottom, int left, int right, int borderType, Scalar value, Stream s) { + cv::Scalar cValue = cv::Scalar(value.val1, value.val2, value.val3, value.val4); + + if (s == NULL) { + cv::cuda::copyMakeBorder(*src, *dst, top, bottom, left, right, borderType, cValue); + return; + } + cv::cuda::copyMakeBorder(*src, *dst, top, bottom, left, right, borderType, cValue, *s); +} diff --git a/cuda/arithm.go b/cuda/arithm.go index b1e6b3cd..64b42b39 100644 --- a/cuda/arithm.go +++ b/cuda/arithm.go @@ -369,3 +369,49 @@ func Transpose(src GpuMat, dst *GpuMat) { func TransposeWithStream(src GpuMat, dst *GpuMat, s Stream) { C.GpuTranspose(src.p, dst.p, s.p) } + +// AddWeighted computes a weighted sum of two matrices. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d8/d34/group__cudaarithm__elem.html#ga2cd14a684ea70c6ab2a63ee90ffe6201 +func AddWeighted(src1 GpuMat, alpha float64, src2 GpuMat, beta float64, gamma float64, dst *GpuMat, dType int) { + C.GpuAddWeighted(src1.p, C.double(alpha), src2.p, C.double(beta), C.double(gamma), dst.p, C.int(dType), nil) +} + +// AddWeightedWithStream computes a weighted sum of two matrices using a Stream for concurrency. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d8/d34/group__cudaarithm__elem.html#ga2cd14a684ea70c6ab2a63ee90ffe6201 +func AddWeightedWithStream(src1 GpuMat, alpha float64, src2 GpuMat, beta float64, gamma float64, dst *GpuMat, dType int, s Stream) { + C.GpuAddWeighted(src1.p, C.double(alpha), src2.p, C.double(beta), C.double(gamma), dst.p, C.int(dType), s.p) +} + +// CopyMakeBorder forms a border around an image. +// +// For further details, please see: +// https://docs.opencv.org/master/de/d09/group__cudaarithm__core.html#ga5368db7656eacf846b40089c98053a49 +func CopyMakeBorder(src GpuMat, dst *GpuMat, top, bottom, left, right int, borderType gocv.BorderType, value gocv.Scalar) { + bv := C.struct_Scalar{ + val1: C.double(value.Val1), + val2: C.double(value.Val2), + val3: C.double(value.Val3), + val4: C.double(value.Val4), + } + + C.GpuCopyMakeBorder(src.p, dst.p, C.int(top), C.int(bottom), C.int(left), C.int(right), C.int(borderType), bv, nil) +} + +// CopyMakeBorderWithStream forms a border around an image using a Stream for concurrency. +// +// For further details, please see: +// https://docs.opencv.org/master/de/d09/group__cudaarithm__core.html#ga5368db7656eacf846b40089c98053a49 +func CopyMakeBorderWithStream(src GpuMat, dst *GpuMat, top, bottom, left, right int, borderType gocv.BorderType, value gocv.Scalar, s Stream) { + bv := C.struct_Scalar{ + val1: C.double(value.Val1), + val2: C.double(value.Val2), + val3: C.double(value.Val3), + val4: C.double(value.Val4), + } + + C.GpuCopyMakeBorder(src.p, dst.p, C.int(top), C.int(bottom), C.int(left), C.int(right), C.int(borderType), bv, s.p) +} diff --git a/cuda/arithm.h b/cuda/arithm.h index 4667bfa4..5ba4629b 100644 --- a/cuda/arithm.h +++ b/cuda/arithm.h @@ -31,6 +31,8 @@ void GpuThreshold(GpuMat src, GpuMat dst, double thresh, double maxval, int typ, void GpuFlip(GpuMat src, GpuMat dst, int flipCode, Stream s); void GpuMerge(struct GpuMats mats, GpuMat dst, Stream s); void GpuTranspose(GpuMat src, GpuMat dst, Stream s); +void GpuAddWeighted(GpuMat src1, double alpha, GpuMat src2, double beta, double gamma, GpuMat dst, int dType, Stream s); +void GpuCopyMakeBorder(GpuMat src, GpuMat dst, int top, int bottom, int left, int right, int borderType, Scalar value, Stream s); #ifdef __cplusplus } diff --git a/cuda/arithm_test.go b/cuda/arithm_test.go index 7145c05a..cd1216b0 100644 --- a/cuda/arithm_test.go +++ b/cuda/arithm_test.go @@ -595,3 +595,123 @@ func TestTransposeWithStream(t *testing.T) { t.Error("Invalid TransposeWithStream test") } } + +func TestAddWeighted(t *testing.T) { + src1 := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadGrayScale) + if src1.Empty() { + t.Error("Invalid read of Mat in AddWeighted test") + } + defer src1.Close() + + src2 := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadGrayScale) + if src2.Empty() { + t.Error("Invalid read of Mat in AddWeighted test") + } + defer src2.Close() + + var cimg1, cimg2, dimg = NewGpuMat(), NewGpuMat(), NewGpuMat() + defer cimg1.Close() + defer cimg2.Close() + defer dimg.Close() + + cimg1.Upload(src1) + cimg2.Upload(src2) + + dest := gocv.NewMat() + defer dest.Close() + + alpha, beta, gamma := 0.5, 0.5, 0.0 + AddWeighted(cimg1, alpha, cimg2, beta, gamma, &dimg, -1) + dimg.Download(&dest) + + if dest.Empty() { + t.Error("Invalid AddWeighted test") + } +} + +func TestAddWeightedWithStream(t *testing.T) { + src1 := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadGrayScale) + if src1.Empty() { + t.Error("Invalid read of Mat in AddWeighted test") + } + defer src1.Close() + + src2 := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadGrayScale) + if src2.Empty() { + t.Error("Invalid read of Mat in AddWeighted test") + } + defer src2.Close() + + var cimg1, cimg2, dimg, s = NewGpuMat(), NewGpuMat(), NewGpuMat(), NewStream() + defer cimg1.Close() + defer cimg2.Close() + defer dimg.Close() + defer s.Close() + + cimg1.UploadWithStream(src1, s) + cimg2.UploadWithStream(src2, s) + + dest := gocv.NewMat() + defer dest.Close() + + alpha, beta, gamma := 0.5, 0.5, 0.0 + AddWeightedWithStream(cimg1, alpha, cimg2, beta, gamma, &dimg, -1, s) + dimg.DownloadWithStream(&dest, s) + + s.WaitForCompletion() + + if dest.Empty() { + t.Error("Invalid AddWeightedWithStream test") + } +} + +func TestCopyMakeBorder(t *testing.T) { + src := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadGrayScale) + if src.Empty() { + t.Error("Invalid read of Mat in CopyMakeBorder test") + } + defer src.Close() + + var cimg, dimg = NewGpuMat(), NewGpuMat() + defer cimg.Close() + defer dimg.Close() + + cimg.Upload(src) + + dest := gocv.NewMat() + defer dest.Close() + + CopyMakeBorder(cimg, &dimg, 10, 10, 10, 10, gocv.BorderReflect, gocv.NewScalar(0, 0, 0, 0)) + dimg.Download(&dest) + + if dest.Empty() { + t.Error("Invalid CopyMakeBorder test") + } +} + +func TestCopyMakeBorderWithStream(t *testing.T) { + src := gocv.IMRead("../images/gocvlogo.jpg", gocv.IMReadGrayScale) + if src.Empty() { + t.Error("Invalid read of Mat in CopyMakeBorder test") + } + defer src.Close() + + var cimg, dimg, s = NewGpuMat(), NewGpuMat(), NewStream() + defer cimg.Close() + defer dimg.Close() + defer s.Close() + + cimg.UploadWithStream(src, s) + + dest := gocv.NewMat() + defer dest.Close() + + CopyMakeBorderWithStream(cimg, &dimg, 10, 10, 10, 10, gocv.BorderReflect, gocv.NewScalar(0, 0, 0, 0), s) + dimg.DownloadWithStream(&dest, s) + + s.WaitForCompletion() + + if dest.Empty() { + t.Error("Invalid CopyMakeBorderWithStream test") + } +}