hybridgroup / gocv

Go package for computer vision using OpenCV 4 and beyond. Includes support for DNN, CUDA, and OpenCV Contrib.
https://gocv.io
Other
6.54k stars 862 forks source link

Memory leak when using OpenVino #598

Open yutkin opened 4 years ago

yutkin commented 4 years ago

Tried to use OpenVino as a backend type. All works fine except a memory leak:

Screenshot 2020-01-24 at 21 00 57

Code that leaks: I'm reading an image in an infinite loop and doing "forward" on it.

package main

import (
    "fmt"
    "gocv.io/x/gocv"
    "image"
    "time"
)

func main() {
    net := gocv.ReadNet("face-detection-retail-0005.bin", "face-detection-retail-0005.xml")

    if net.Empty() {
        fmt.Println("Error reading network model")
        return
    }

    net.SetPreferableBackend(gocv.NetBackendOpenVINO)
    net.SetPreferableTarget(gocv.NetTargetCPU)

    defer net.Close()

    for {
        img := gocv.IMRead("photo.jpg", gocv.IMReadColor)
        blob := gocv.BlobFromImage(img, 1, image.Pt(300, 300), gocv.Scalar{},false, false)

        net.SetInput(blob, "")

        t1 := time.Now()

        prob := net.Forward("")

        fmt.Println("Inference time:", time.Since(t1))

        for i := 0; i < prob.Total(); i += 7 {
            confidence := prob.GetFloatAt(0, i+2)
            if confidence > 0.5 {
                _ = int(prob.GetFloatAt(0, i+3) * float32(img.Cols()))
                _ = int(prob.GetFloatAt(0, i+4) * float32(img.Rows()))
                _ = int(prob.GetFloatAt(0, i+5) * float32(img.Cols()))
                _ = int(prob.GetFloatAt(0, i+6) * float32(img.Rows()))
            }
        }
        blob.Close()
        prob.Close()
        img.Close()
    }
}

go version go1.13.5 linux/amd64 gocv commit: 2d8275b67baa022d6abeda69508821f6b1db015c

yutkin commented 4 years ago

Also, has a leak on OpenCV backend:

package main

import (
    "go.uber.org/zap"
    "gocv.io/x/gocv"
    "image"
    "net/http"
    _ "net/http/pprof"
    "time"
)

var (
    logger *zap.SugaredLogger
)

const threshold = 0.7

func getFaces(prob *gocv.Mat, w, h float32) [][]int {
    result := make([][]int, 0)

    for i := 0; i < prob.Total(); i += 7 {
        confidence := prob.GetFloatAt(0, i+2)
        if confidence > threshold {
            x_min := int(prob.GetFloatAt(0, i+3) * w)
            y_min := int(prob.GetFloatAt(0, i+4) * h)
            x_max := int(prob.GetFloatAt(0, i+5) * w)
            y_max := int(prob.GetFloatAt(0, i+6) * h)
            result = append(result, []int{x_min, y_min, x_max, y_max})
        }
    }

    return result
}

func findFacesOnImage(path string, net *gocv.Net) {
    img := gocv.IMRead(path, gocv.IMReadColor)
    defer img.Close()

    if img.Empty() {
        logger.Errorw("Image is empty. Fail to open", "imagePath", path)
        return
    }

    blob := gocv.BlobFromImage(img, 1, image.Pt(300, 300), gocv.Scalar{}, false, false)
    defer blob.Close()

    net.SetInput(blob, "")

    t1 := time.Now()

    prob := net.Forward("")
    defer prob.Close()

    faces := getFaces(&prob, float32(img.Cols()), float32(img.Rows()))

    logger.Infow("Inference", "time", time.Since(t1), "faces", faces)
}

func main() {
    go func() {
        logger.Infow("Listen result", http.ListenAndServe("0.0.0.0:8200", nil))
    }()

    l, _ := zap.NewProduction()
    logger = l.Sugar()

    net := gocv.ReadNet("face-detection-retail-0044.caffemodel", "deploy.prototxt")

    if net.Empty() {
        logger.Infow("Error reading network model")
    }

    net.SetPreferableBackend(gocv.NetBackendOpenCV)
    net.SetPreferableTarget(gocv.NetTargetCPU)

    defer net.Close()

    for {
        findFacesOnImage("./photo.jpg", &net)
    }
}

Dockerfile:

FROM denismakogon/gocv-alpine:4.0.1-buildstage as build-stage

WORKDIR /opt

RUN curl -Lo deploy.prototxt https://raw.githubusercontent.com/opencv/training_toolbox_caffe/63ccbbc328f0c1f414f459c284293b3929b09339/models/face_detection/deploy.prototxt && \
    curl -Lo face-detection-retail-0044.caffemodel https://github.com/opencv/training_toolbox_caffe/raw/63ccbbc328f0c1f414f459c284293b3929b09339/models/face_detection/face-detection-retail-0044.caffemodel

RUN go get -u github.com/golang/dep/cmd/dep

WORKDIR $GOPATH/src/nsfw

COPY vendor ./vendor

COPY main.go ./
COPY Gopkg.lock ./
COPY Gopkg.toml ./

RUN dep ensure

RUN go install

FROM denismakogon/gocv-alpine:4.0.1-runtime

WORKDIR /app

COPY --from=build-stage /go/bin/nsfw .
COPY --from=build-stage /opt/deploy.prototxt .
COPY --from=build-stage /opt/face-detection-retail-0044.caffemodel .
COPY photo.jpg ./

CMD ["./nsfw"]

image

dpanic commented 1 year ago

I have same problem on letest gocv