From 9b4d1b01778c44b1f03b5d4487e66ab4574ec4f4 Mon Sep 17 00:00:00 2001 From: diegohce Date: Fri, 27 Sep 2024 16:44:43 -0300 Subject: [PATCH] added cuda create lookuptable and cuda split func --- ROADMAP.md | 6 +-- cuda/arithm.cpp | 37 ++++++++++++++ cuda/arithm.go | 114 +++++++++++++++++++++++++++++++++++++++++++- cuda/arithm.h | 14 ++++++ cuda/arithm_test.go | 94 ++++++++++++++++++++++++++++++++++++ 5 files changed, 261 insertions(+), 4 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 017f397c..11cc478c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -203,9 +203,9 @@ Your pull requests will be greatly appreciated! - [X] **core** - [ ] **cudaarithm. Operations on Matrices - WORK STARTED** The following functions still need implementation: - - [ ] **core - WORK STARTED** The following functions still need implementation: - - [ ] [cv::cuda::createLookUpTable](https://docs.opencv.org/master/de/d09/group__cudaarithm__core.html#ga2d9d9780dea8c5cd85d3c19b7e01979c) - - [ ] [cv::cuda::split](https://docs.opencv.org/master/de/d09/group__cudaarithm__core.html#gabe5013d55d4ff586b20393913726179e) + - [X] **core - WORK STARTED** The following functions still need implementation: + - [X] [cv::cuda::createLookUpTable](https://docs.opencv.org/master/de/d09/group__cudaarithm__core.html#ga2d9d9780dea8c5cd85d3c19b7e01979c) + - [X] [cv::cuda::split](https://docs.opencv.org/master/de/d09/group__cudaarithm__core.html#gabe5013d55d4ff586b20393913726179e) - [ ] **per-element operations - WORK STARTED** The following functions still need implementation: - [ ] [cv::cuda::cartToPolar](https://docs.opencv.org/master/d8/d34/group__cudaarithm__elem.html#ga82210c7d1c1d42e616e554bf75a53480) diff --git a/cuda/arithm.cpp b/cuda/arithm.cpp index 612b69cc..e009cbce 100644 --- a/cuda/arithm.cpp +++ b/cuda/arithm.cpp @@ -187,3 +187,40 @@ void GpuCopyMakeBorder(GpuMat src, GpuMat dst, int top, int bottom, int left, in } cv::cuda::copyMakeBorder(*src, *dst, top, bottom, left, right, borderType, cValue, *s); } + +LookUpTable Cuda_Create_LookUpTable(GpuMat lut){ + return new cv::Ptr(cv::cuda::createLookUpTable(*lut)); +} + +void Cuda_LookUpTable_Close(LookUpTable lt) { + delete lt; +} + +bool Cuda_LookUpTable_Empty(LookUpTable lut) { + return lut->empty(); +} + +void Cuda_LookUpTable_Transform(LookUpTable lt, GpuMat src, GpuMat dst, Stream s) { + cv::Ptr< cv::cuda::LookUpTable> p = cv::Ptr< cv::cuda::LookUpTable>(*lt); + + if(s == NULL) { + p->transform(*src, *dst); + } else { + p->transform(*src, *dst, *s); + } +} + +void Cuda_Split(GpuMat src, GpuMats dst, Stream s) { + std::vector< cv::cuda::GpuMat > dstv; + + for(int i = 0; i < dst.length; i++) { + dstv.push_back(*(dst.mats[i])); + } + + if(s == NULL){ + cv::cuda::split(*src, dstv); + } else { + cv::cuda::split(*src, dstv, *s); + } + +} \ No newline at end of file diff --git a/cuda/arithm.go b/cuda/arithm.go index 64b42b39..2f4858da 100644 --- a/cuda/arithm.go +++ b/cuda/arithm.go @@ -8,7 +8,11 @@ package cuda */ import "C" -import "gocv.io/x/gocv" +import ( + "unsafe" + + "gocv.io/x/gocv" +) // Abs computes an absolute value of each matrix element. // @@ -415,3 +419,111 @@ func CopyMakeBorderWithStream(src GpuMat, dst *GpuMat, top, bottom, left, right C.GpuCopyMakeBorder(src.p, dst.p, C.int(top), C.int(bottom), C.int(left), C.int(right), C.int(borderType), bv, s.p) } + +type LookUpTable struct { + p C.LookUpTable +} + +// NewLookUpTable Creates implementation for cuda::LookUpTable . +// +// lut Look-up table of 256 elements. It is a continuous CV_8U matrix. +// +// For further details, please see: +// https://docs.opencv.org/4.x/de/d09/group__cudaarithm__core.html#gaa75254a07dcf7996b4b5a68d383847f8 +func NewLookUpTable(lut GpuMat) LookUpTable { + return LookUpTable{p: C.Cuda_Create_LookUpTable(lut.p)} +} + +// Close releases LookUpTable resources. +func (lt *LookUpTable) Close() { + C.Cuda_LookUpTable_Close(lt.p) +} + +// Transform Transforms the source matrix into the destination +// matrix using the given look-up table: dst(I) = lut(src(I)) . +// +// src: Source matrix. CV_8UC1 and CV_8UC3 matrices are supported for now. +// +// dst: Destination matrix. +// +// For further details, please see: +// https://docs.opencv.org/4.x/df/d29/classcv_1_1cuda_1_1LookUpTable.html#afdbcbd3047f847451892f3b18cd018de +func (lt *LookUpTable) Transform(src GpuMat, dst *GpuMat) { + C.Cuda_LookUpTable_Transform(lt.p, src.p, dst.p, nil) +} + +// Empty Returns true if the Algorithm is empty +// (e.g. in the very beginning or after unsuccessful read. +// +// For further details, please see: +// https://docs.opencv.org/4.x/d3/d46/classcv_1_1Algorithm.html#a827c8b2781ed17574805f373e6054ff1 +func (lt *LookUpTable) Empty() bool { + b := C.Cuda_LookUpTable_Empty(lt.p) + + return bool(b) +} + +// TransformWithStream Transforms the source matrix into the destination +// matrix using the given look-up table: dst(I) = lut(src(I)) . +// +// src: Source matrix. CV_8UC1 and CV_8UC3 matrices are supported for now. +// +// dst: Destination matrix. +// +// stream: Stream for the asynchronous version. +// +// For further details, please see: +// https://docs.opencv.org/4.x/df/d29/classcv_1_1cuda_1_1LookUpTable.html#afdbcbd3047f847451892f3b18cd018de +func (lt *LookUpTable) TransformWithStream(src GpuMat, dst *GpuMat, s Stream) { + C.Cuda_LookUpTable_Transform(lt.p, src.p, dst.p, s.p) +} + +// Split Copies each plane of a multi-channel matrix into an array. +// +// src: Source matrix. +// +// dst: Destination array/vector of single-channel matrices. +// +// For further details, please see: +// https://docs.opencv.org/4.x/de/d09/group__cudaarithm__core.html#gaf1714e7a9ea0719c29bf378beaf5f99d +func Split(src GpuMat, dst []GpuMat) { + + dstv := make([]C.GpuMat, len(dst)) + + for i := range dst { + dstv[i] = dst[i].p + } + + c_dstv := C.GpuMats{ + mats: unsafe.SliceData(dstv), + length: C.int(len(dstv)), + } + + C.Cuda_Split(src.p, c_dstv, nil) +} + +// SplitWithStream Copies each plane of a multi-channel matrix into an array. +// +// src: Source matrix. +// +// dst: Destination array/vector of single-channel matrices. +// +// stream: Stream for the asynchronous version. +// +// For further details, please see: +// https://docs.opencv.org/4.x/de/d09/group__cudaarithm__core.html#gaf1714e7a9ea0719c29bf378beaf5f99d +func SplitWithStream(src GpuMat, dst []GpuMat, s Stream) { + + dstv := make([]C.GpuMat, len(dst)) + + for i := range dst { + dstv[i] = dst[i].p + } + + c_dstv := C.GpuMats{ + mats: unsafe.SliceData(dstv), + length: C.int(len(dstv)), + } + + C.Cuda_Split(src.p, c_dstv, s.p) +} diff --git a/cuda/arithm.h b/cuda/arithm.h index 5ba4629b..3fa00536 100644 --- a/cuda/arithm.h +++ b/cuda/arithm.h @@ -11,6 +11,12 @@ extern "C" { #endif #include "cuda.h" +#ifdef __cplusplus +typedef cv::Ptr< cv::cuda::LookUpTable >* LookUpTable; +#else +typedef void* LookUpTable; +#endif + void GpuAbs(GpuMat src, GpuMat dst, Stream s); void GpuAbsDiff(GpuMat src1, GpuMat src2, GpuMat dst, Stream s); void GpuAdd(GpuMat src1, GpuMat src2, GpuMat dst, Stream s); @@ -34,6 +40,14 @@ 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); +//LookUpTable +LookUpTable Cuda_Create_LookUpTable(GpuMat lut); +void Cuda_LookUpTable_Close(LookUpTable lt); +void Cuda_LookUpTable_Transform(LookUpTable lt, GpuMat src, GpuMat dst, Stream s); + +bool Cuda_LookUpTable_Empty(LookUpTable lut); + +void Cuda_Split(GpuMat src, GpuMats dst, Stream s); #ifdef __cplusplus } #endif diff --git a/cuda/arithm_test.go b/cuda/arithm_test.go index cd1216b0..e84d07f0 100644 --- a/cuda/arithm_test.go +++ b/cuda/arithm_test.go @@ -715,3 +715,97 @@ func TestCopyMakeBorderWithStream(t *testing.T) { t.Error("Invalid CopyMakeBorderWithStream test") } } + +func TestNewLookUpTable(t *testing.T) { + + m := NewGpuMatWithSize(1, 256, gocv.MatTypeCV8U) + defer m.Close() + + lt := NewLookUpTable(m) + defer lt.Close() + +} + +func TestLookUpTableEmpty(t *testing.T) { + m := NewGpuMatWithSize(1, 256, gocv.MatTypeCV8U) + defer m.Close() + + lt := NewLookUpTable(m) + defer lt.Close() + + lt.Empty() +} + +func TestTransform(t *testing.T) { + + src := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC3) + defer src.Close() + + dst := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC3) + defer dst.Close() + + m := NewGpuMatWithSize(1, 256, gocv.MatTypeCV8U) + defer m.Close() + + lt := NewLookUpTable(m) + defer lt.Close() + + lt.Transform(src, &dst) +} + +func TestTransformWithStream(t *testing.T) { + + src := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC3) + defer src.Close() + + dst := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC3) + defer dst.Close() + + m := NewGpuMatWithSize(1, 256, gocv.MatTypeCV8U) + defer m.Close() + + lt := NewLookUpTable(m) + defer lt.Close() + + s := NewStream() + defer s.Close() + + lt.TransformWithStream(src, &dst, s) + s.WaitForCompletion() +} + +func TestSplit(t *testing.T) { + + m := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC2) + defer m.Close() + + m0 := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC1) + defer m0.Close() + + m1 := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC1) + defer m1.Close() + + mats := []GpuMat{m0, m1} + + Split(m, mats) +} + +func TestSplitWithStream(t *testing.T) { + + m := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC2) + defer m.Close() + + m0 := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC1) + defer m0.Close() + + m1 := NewGpuMatWithSize(256, 256, gocv.MatTypeCV8UC1) + defer m1.Close() + + mats := []GpuMat{m0, m1} + + s := NewStream() + defer s.Close() + + SplitWithStream(m, mats, s) + s.WaitForCompletion() +}