Skip to content

Commit

Permalink
initial cuda implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
netbrain authored and deadprogram committed May 3, 2019
1 parent e298534 commit 355dd54
Show file tree
Hide file tree
Showing 14 changed files with 437 additions and 2 deletions.
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion cgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions cmd/cuda/main.go
Original file line number Diff line number Diff line change
@@ -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 changes: 1 addition & 1 deletion contrib/cgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions cuda/README.md
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions cuda/cgo.go
Original file line number Diff line number Diff line change
@@ -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 changes: 33 additions & 0 deletions cuda/cuda.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 76 additions & 0 deletions cuda/cuda.go
Original file line number Diff line number Diff line change
@@ -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 changes: 32 additions & 0 deletions cuda/cuda.h
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions cuda/cuda_test.go
Original file line number Diff line number Diff line change
@@ -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 changes: 25 additions & 0 deletions cuda/cudabgsegm.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 76 additions & 0 deletions cuda/cudabgsegm.go
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit 355dd54

Please sign in to comment.