mirror of
https://github.com/hybridgroup/gocv
synced 2025-08-25 08:41:04 +08:00
initial cuda implementation
This commit is contained in:
13
Makefile
13
Makefile
@@ -84,6 +84,16 @@ build_nonfree:
|
||||
$(MAKE) preinstall
|
||||
cd -
|
||||
|
||||
# Build OpenCV with cuda.
|
||||
build_cuda:
|
||||
cd $(TMP_DIR)opencv/opencv-$(OPENCV_VERSION)
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -j $(shell nproc --all) -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_EXTRA_MODULES_PATH=$(TMP_DIR)opencv/opencv_contrib-$(OPENCV_VERSION)/modules -D BUILD_DOCS=OFF -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_opencv_java=NO -D BUILD_opencv_python=NO -D BUILD_opencv_python2=NO -D BUILD_opencv_python3=NO -D WITH_JASPER=OFF -DOPENCV_GENERATE_PKGCONFIG=ON -DWITH_CUDA=ON -DENABLE_FAST_MATH=1 -DCUDA_FAST_MATH=1 -DWITH_CUBLAS=1 -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda/ -DBUILD_opencv_cudacodec=OFF ..
|
||||
$(MAKE) -j $(shell nproc --all)
|
||||
$(MAKE) preinstall
|
||||
cd -
|
||||
|
||||
# Cleanup temporary build files.
|
||||
clean:
|
||||
rm -rf $(TMP_DIR)opencv
|
||||
@@ -94,6 +104,9 @@ install: deps download build sudo_install clean verify
|
||||
# Do everything on Raspbian.
|
||||
install_raspi: deps download build_raspi sudo_install clean verify
|
||||
|
||||
# Do everything with cuda.
|
||||
install_cuda: deps download build_cuda sudo_install clean verify
|
||||
|
||||
# Install system wide.
|
||||
sudo_install:
|
||||
cd $(TMP_DIR)opencv/opencv-$(OPENCV_VERSION)/build
|
||||
|
||||
2
cgo.go
2
cgo.go
@@ -2,7 +2,7 @@
|
||||
|
||||
package gocv
|
||||
|
||||
// Changes here should be mirrored in contrib/cgo.go.
|
||||
// Changes here should be mirrored in contrib/cgo.go and cuda/cgo.go.
|
||||
|
||||
/*
|
||||
#cgo !windows pkg-config: opencv4
|
||||
|
||||
28
cmd/cuda/main.go
Normal file
28
cmd/cuda/main.go
Normal file
@@ -0,0 +1,28 @@
|
||||
// What it does:
|
||||
//
|
||||
// This program outputs the current OpenCV library version and CUDA version the console.
|
||||
//
|
||||
// How to run:
|
||||
//
|
||||
// go run ./cmd/cuda/main.go
|
||||
//
|
||||
// +build example
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gocv.io/x/gocv"
|
||||
"gocv.io/x/gocv/cuda"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("gocv version: %s\n", gocv.Version())
|
||||
fmt.Println("cuda information:")
|
||||
devices := cuda.GetCudaEnabledDeviceCount()
|
||||
for i := 0; i < devices; i++ {
|
||||
fmt.Print(" ")
|
||||
cuda.PrintShortCudaDeviceInfo(i)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
package contrib
|
||||
|
||||
// Changes here should be mirrored in gocv/cgo.go.
|
||||
// Changes here should be mirrored in gocv/cgo.go and cuda/cgo.go
|
||||
|
||||
/*
|
||||
#cgo !windows pkg-config: opencv4
|
||||
|
||||
24
cuda/README.md
Normal file
24
cuda/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Cuda (Experimental)
|
||||
|
||||
In order to use the cuda package, the cuda toolkit from nvidia needs to be installed on the host system.
|
||||
|
||||
Please see https://docs.nvidia.com/cuda/index.html for more information.
|
||||
|
||||
Furthermore opencv must be compiled with cuda support.
|
||||
|
||||
## Compiling opencv with cuda
|
||||
|
||||
For now we have included the make target `install_cuda` that compiles opencv with cuda. (For more details on the compilation process please see the `Makefile`)
|
||||
|
||||
Simply issue the command `make install_cuda` and you should be good to go.
|
||||
|
||||
Then finally verify that it is all working
|
||||
|
||||
cd $GOPATH/src/gocv.io/x/gocv
|
||||
go run ./cmd/cuda/main.go
|
||||
|
||||
You should see something along the lines of:
|
||||
|
||||
gocv version: 0.19.0
|
||||
cuda information:
|
||||
Device 0: "GeForce MX150" 2003Mb, sm_61, Driver/Runtime ver.10.0/10.0
|
||||
13
cuda/cgo.go
Normal file
13
cuda/cgo.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// +build !customenv,!openvino
|
||||
|
||||
package cuda
|
||||
|
||||
// Changes here should be mirrored in gocv/cgo.go and contrib/cgo.go.
|
||||
|
||||
/*
|
||||
#cgo !windows pkg-config: opencv4
|
||||
#cgo CXXFLAGS: --std=c++11
|
||||
#cgo windows CPPFLAGS: -IC:/opencv/build/install/include
|
||||
#cgo windows LDFLAGS: -LC:/opencv/build/install/x64/mingw/lib -lopencv_core401 -lopencv_face401 -lopencv_videoio401 -lopencv_imgproc401 -lopencv_highgui401 -lopencv_imgcodecs401 -lopencv_objdetect401 -lopencv_features2d401 -lopencv_video401 -lopencv_dnn401 -lopencv_xfeatures2d401 -lopencv_plot401 -lopencv_tracking401 -lopencv_img_hash401 -lopencv_calib3d401
|
||||
*/
|
||||
import "C"
|
||||
33
cuda/cuda.cpp
Normal file
33
cuda/cuda.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "cuda.h"
|
||||
|
||||
GpuMat GpuMat_New() {
|
||||
return new cv::cuda::GpuMat();
|
||||
}
|
||||
|
||||
void GpuMat_Upload(GpuMat m,Mat data){
|
||||
m->upload(*data);
|
||||
}
|
||||
|
||||
void GpuMat_Download(GpuMat m,Mat dst){
|
||||
m->download(*dst);
|
||||
}
|
||||
|
||||
int GpuMat_Empty(GpuMat m){
|
||||
return m->empty();
|
||||
}
|
||||
|
||||
void GpuMat_Close(GpuMat m){
|
||||
delete m;
|
||||
}
|
||||
|
||||
void PrintCudaDeviceInfo(int device){
|
||||
cv::cuda::printCudaDeviceInfo(device);
|
||||
}
|
||||
|
||||
void PrintShortCudaDeviceInfo(int device){
|
||||
cv::cuda::printShortCudaDeviceInfo(device);
|
||||
}
|
||||
|
||||
int GetCudaEnabledDeviceCount(){
|
||||
return cv::cuda::getCudaEnabledDeviceCount();
|
||||
}
|
||||
76
cuda/cuda.go
Normal file
76
cuda/cuda.go
Normal file
@@ -0,0 +1,76 @@
|
||||
// Package cuda is the GoCV wrapper around OpenCV cuda.
|
||||
//
|
||||
// For further details, please see:
|
||||
// https://github.com/opencv/c
|
||||
//
|
||||
// import "gocv.io/x/gocv/cuda"
|
||||
package cuda
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include "cuda.h"
|
||||
*/
|
||||
import "C"
|
||||
import "gocv.io/x/gocv"
|
||||
|
||||
// GpuMat is the GPU version of a Mat
|
||||
//
|
||||
// For further details, please see:
|
||||
// https://docs.opencv.org/master/d0/d60/classcv_1_1cuda_1_1GpuMat.html
|
||||
type GpuMat struct {
|
||||
p C.GpuMat
|
||||
}
|
||||
|
||||
// Upload performs data upload to GpuMat (Blocking call)
|
||||
//
|
||||
// For further details, please see:
|
||||
// https://docs.opencv.org/master/d0/d60/classcv_1_1cuda_1_1GpuMat.html#a00ef5bfe18d14623dcf578a35e40a46b
|
||||
//
|
||||
func (g *GpuMat) Upload(data gocv.Mat) {
|
||||
C.GpuMat_Upload(g.p, C.Mat(data.Ptr()))
|
||||
}
|
||||
|
||||
// Download performs data download from GpuMat (Blocking call)
|
||||
//
|
||||
// For further details, please see:
|
||||
// https://docs.opencv.org/master/d0/d60/classcv_1_1cuda_1_1GpuMat.html#a027e74e4364ddfd9687b58aa5db8d4e8
|
||||
func (g *GpuMat) Download(dst *gocv.Mat) {
|
||||
C.GpuMat_Download(g.p, C.Mat(dst.Ptr()))
|
||||
}
|
||||
|
||||
// Empty returns true if GpuMat is empty
|
||||
func (g *GpuMat) Empty() bool {
|
||||
return C.GpuMat_Empty(g.p) != 0
|
||||
}
|
||||
|
||||
// Close the GpuMat object
|
||||
func (g *GpuMat) Close() error {
|
||||
C.GpuMat_Close(g.p)
|
||||
g.p = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewGpuMat Returns a new empty GpuMat
|
||||
func NewGpuMat() GpuMat {
|
||||
return newGpuMat(C.GpuMat_New())
|
||||
}
|
||||
|
||||
func newGpuMat(p C.GpuMat) GpuMat {
|
||||
return GpuMat{p: p}
|
||||
}
|
||||
|
||||
// PrintCudaDeviceInfo prints extensive cuda device information
|
||||
func PrintCudaDeviceInfo(device int) {
|
||||
C.PrintCudaDeviceInfo(C.int(device))
|
||||
}
|
||||
|
||||
// PrintShortCudaDeviceInfo prints a small amount of cuda device information
|
||||
func PrintShortCudaDeviceInfo(device int) {
|
||||
C.PrintShortCudaDeviceInfo(C.int(device))
|
||||
}
|
||||
|
||||
// GetCudaEnabledDeviceCount returns the number of cuda enabled devices on the
|
||||
// system
|
||||
func GetCudaEnabledDeviceCount() int {
|
||||
return int(C.GetCudaEnabledDeviceCount())
|
||||
}
|
||||
32
cuda/cuda.h
Normal file
32
cuda/cuda.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef _OPENCV3_CUDA_H_
|
||||
#define _OPENCV3_CUDA_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/core/cuda.hpp>
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
typedef cv::cuda::GpuMat* GpuMat;
|
||||
#else
|
||||
typedef void* GpuMat;
|
||||
#endif
|
||||
|
||||
GpuMat GpuMat_New();
|
||||
void GpuMat_Upload(GpuMat m,Mat data);
|
||||
void GpuMat_Download(GpuMat m,Mat dst);
|
||||
void GpuMat_Close(GpuMat m);
|
||||
int GpuMat_Empty(GpuMat m);
|
||||
|
||||
void PrintCudaDeviceInfo(int device);
|
||||
void PrintShortCudaDeviceInfo(int device);
|
||||
int GetCudaEnabledDeviceCount();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_OPENCV3_CUDA_H_
|
||||
20
cuda/cuda_test.go
Normal file
20
cuda/cuda_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package cuda
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewGpuMat(t *testing.T) {
|
||||
mat := NewGpuMat()
|
||||
defer mat.Close()
|
||||
|
||||
if !mat.Empty() {
|
||||
t.Error("New Mat should be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCudaEnabledDeviceCount(t *testing.T) {
|
||||
if GetCudaEnabledDeviceCount() < 1 {
|
||||
t.Fatal("expected atleast one cuda enabled device")
|
||||
}
|
||||
}
|
||||
25
cuda/cudabgsegm.cpp
Normal file
25
cuda/cudabgsegm.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "cudabgsegm.h"
|
||||
|
||||
CudaBackgroundSubtractorMOG2 CudaBackgroundSubtractorMOG2_Create() {
|
||||
return new cv::Ptr<cv::cuda::BackgroundSubtractorMOG2>(cv::cuda::createBackgroundSubtractorMOG2());
|
||||
}
|
||||
|
||||
void CudaBackgroundSubtractorMOG2_Close(CudaBackgroundSubtractorMOG2 b) {
|
||||
delete b;
|
||||
}
|
||||
|
||||
void CudaBackgroundSubtractorMOG2_Apply(CudaBackgroundSubtractorMOG2 b, GpuMat src, GpuMat dst) {
|
||||
(*b)->apply(*src, *dst);
|
||||
}
|
||||
|
||||
CudaBackgroundSubtractorMOG CudaBackgroundSubtractorMOG_Create() {
|
||||
return new cv::Ptr<cv::cuda::BackgroundSubtractorMOG>(cv::cuda::createBackgroundSubtractorMOG());
|
||||
}
|
||||
|
||||
void CudaBackgroundSubtractorMOG_Close(CudaBackgroundSubtractorMOG b) {
|
||||
delete b;
|
||||
}
|
||||
|
||||
void CudaBackgroundSubtractorMOG_Apply(CudaBackgroundSubtractorMOG b, GpuMat src, GpuMat dst) {
|
||||
(*b)->apply(*src, *dst);
|
||||
}
|
||||
76
cuda/cudabgsegm.go
Normal file
76
cuda/cudabgsegm.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package cuda
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include "cudabgsegm.h"
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
// BackgroundSubtractorMOG2 is a wrapper around the cv::cuda::BackgroundSubtractorMOG2.
|
||||
type BackgroundSubtractorMOG2 struct {
|
||||
// C.BackgroundSubtractorMOG2
|
||||
p unsafe.Pointer
|
||||
}
|
||||
|
||||
// BackgroundSubtractorMOG is a wrapper around the cv::cuda::BackgroundSubtractorMOG.
|
||||
type BackgroundSubtractorMOG struct {
|
||||
// C.BackgroundSubtractorMOG
|
||||
p unsafe.Pointer
|
||||
}
|
||||
|
||||
// NewBackgroundSubtractorMOG2 returns a new BackgroundSubtractor algorithm
|
||||
// of type MOG2. MOG2 is a Gaussian Mixture-based Background/Foreground
|
||||
// Segmentation Algorithm.
|
||||
//
|
||||
// For further details, please see:
|
||||
// https://docs.opencv.org/master/dc/d3d/cudabgsegm_8hpp.html
|
||||
//
|
||||
func NewBackgroundSubtractorMOG2() BackgroundSubtractorMOG2 {
|
||||
return BackgroundSubtractorMOG2{p: unsafe.Pointer(C.CudaBackgroundSubtractorMOG2_Create())}
|
||||
}
|
||||
|
||||
// Close BackgroundSubtractorMOG2.
|
||||
func (b *BackgroundSubtractorMOG2) Close() error {
|
||||
C.CudaBackgroundSubtractorMOG2_Close((C.CudaBackgroundSubtractorMOG2)(b.p))
|
||||
b.p = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply computes a foreground mask using the current BackgroundSubtractorMOG2.
|
||||
//
|
||||
// For further details, please see:
|
||||
// https://docs.opencv.org/master/df/d23/classcv_1_1cuda_1_1BackgroundSubtractorMOG2.html#a92408f07bf1268c1b778cb186b3113b0
|
||||
//
|
||||
func (b *BackgroundSubtractorMOG2) Apply(src GpuMat, dst *GpuMat) {
|
||||
C.CudaBackgroundSubtractorMOG2_Apply((C.CudaBackgroundSubtractorMOG2)(b.p), src.p, dst.p)
|
||||
return
|
||||
}
|
||||
|
||||
// NewBackgroundSubtractorMOG returns a new BackgroundSubtractor algorithm
|
||||
// of type MOG. MOG is a Gaussian Mixture-based Background/Foreground
|
||||
// Segmentation Algorithm.
|
||||
//
|
||||
// For further details, please see:
|
||||
// https://docs.opencv.org/master/dc/d3d/cudabgsegm_8hpp.html
|
||||
//
|
||||
func NewBackgroundSubtractorMOG() BackgroundSubtractorMOG {
|
||||
return BackgroundSubtractorMOG{p: unsafe.Pointer(C.CudaBackgroundSubtractorMOG_Create())}
|
||||
}
|
||||
|
||||
// Close BackgroundSubtractorMOG.
|
||||
func (b *BackgroundSubtractorMOG) Close() error {
|
||||
C.CudaBackgroundSubtractorMOG_Close((C.CudaBackgroundSubtractorMOG)(b.p))
|
||||
b.p = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Apply computes a foreground mask using the current BackgroundSubtractorMOG.
|
||||
//
|
||||
// For further details, please see:
|
||||
// https://docs.opencv.org/master/d1/dfe/classcv_1_1cuda_1_1BackgroundSubtractorMOG.html#a8f52d2f7abd1c77c84243efc53972cbf
|
||||
//
|
||||
func (b *BackgroundSubtractorMOG) Apply(src GpuMat, dst *GpuMat) {
|
||||
C.CudaBackgroundSubtractorMOG_Apply((C.CudaBackgroundSubtractorMOG)(b.p), src.p, dst.p)
|
||||
return
|
||||
}
|
||||
33
cuda/cudabgsegm.h
Normal file
33
cuda/cudabgsegm.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef _OPENCV3_CUDABGSEGM_H_
|
||||
#define _OPENCV3_CUDABGSEGM_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../core.h"
|
||||
#include "cuda.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
typedef cv::Ptr<cv::cuda::BackgroundSubtractorMOG2>* CudaBackgroundSubtractorMOG2;
|
||||
typedef cv::Ptr<cv::cuda::BackgroundSubtractorMOG>* CudaBackgroundSubtractorMOG;
|
||||
#else
|
||||
typedef void* CudaBackgroundSubtractorMOG2;
|
||||
typedef void* CudaBackgroundSubtractorMOG;
|
||||
#endif
|
||||
|
||||
CudaBackgroundSubtractorMOG2 CudaBackgroundSubtractorMOG2_Create();
|
||||
void CudaBackgroundSubtractorMOG2_Close(CudaBackgroundSubtractorMOG2 b);
|
||||
void CudaBackgroundSubtractorMOG2_Apply(CudaBackgroundSubtractorMOG2 b, GpuMat src, GpuMat dst);
|
||||
|
||||
CudaBackgroundSubtractorMOG CudaBackgroundSubtractorMOG_Create();
|
||||
void CudaBackgroundSubtractorMOG_Close(CudaBackgroundSubtractorMOG b);
|
||||
void CudaBackgroundSubtractorMOG_Apply(CudaBackgroundSubtractorMOG b, GpuMat src, GpuMat dst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_OPENCV3_CUDABGSEGM_H_
|
||||
62
cuda/cudabgsegm_test.go
Normal file
62
cuda/cudabgsegm_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package cuda
|
||||
|
||||
import (
|
||||
"gocv.io/x/gocv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCudaMOG2(t *testing.T) {
|
||||
img := gocv.IMRead("../images/face.jpg", gocv.IMReadColor)
|
||||
if img.Empty() {
|
||||
t.Error("Invalid Mat in CudaMOG2 test")
|
||||
}
|
||||
defer img.Close()
|
||||
|
||||
var cimg, dimg = NewGpuMat(), NewGpuMat()
|
||||
defer cimg.Close()
|
||||
defer dimg.Close()
|
||||
|
||||
cimg.Upload(img)
|
||||
|
||||
dst := gocv.NewMat()
|
||||
defer dst.Close()
|
||||
|
||||
mog2 := NewBackgroundSubtractorMOG2()
|
||||
defer mog2.Close()
|
||||
|
||||
mog2.Apply(cimg, &dimg)
|
||||
|
||||
dimg.Download(&dst)
|
||||
|
||||
if dst.Empty() {
|
||||
t.Error("Error in TestCudaMOG2 test")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCudaMOG(t *testing.T) {
|
||||
img := gocv.IMRead("../images/face.jpg", gocv.IMReadColor)
|
||||
if img.Empty() {
|
||||
t.Error("Invalid Mat in CudaMOG test")
|
||||
}
|
||||
defer img.Close()
|
||||
|
||||
var cimg, dimg = NewGpuMat(), NewGpuMat()
|
||||
defer cimg.Close()
|
||||
defer dimg.Close()
|
||||
|
||||
cimg.Upload(img)
|
||||
|
||||
dst := gocv.NewMat()
|
||||
defer dst.Close()
|
||||
|
||||
mog2 := NewBackgroundSubtractorMOG()
|
||||
defer mog2.Close()
|
||||
|
||||
mog2.Apply(cimg, &dimg)
|
||||
|
||||
dimg.Download(&dst)
|
||||
|
||||
if dst.Empty() {
|
||||
t.Error("Error in TestCudaMOG test")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user