hybridgroup / gocv

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

DetectMultiScale panic when used concurrently #373

Open zhlangsas opened 5 years ago

zhlangsas commented 5 years ago

DetectMultiScale panic when used concurrently

Description

When running cascade detection concurrently in goroutines I receive a variety of panics and segmentation faults.

Steps to Reproduce

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "image"
    "os"
    "path/filepath"
    "sync"

    "gocv.io/x/gocv"

    _ "image/jpeg"
    _ "image/png"
)

type request struct {
    Image     string
    Task      string
    Detect    bool
    Recognize bool
}

func main() {
    classifier := gocv.NewCascadeClassifier()
    defer classifier.Close()

    modelPath := "./haarcascade_frontalface_default.xml"
    if !classifier.Load(modelPath) {
        panic(fmt.Errorf("Error loading cascade file: %v", modelPath))
    }

    baseDir := "./faces"

    files, _ := filepath.Glob(baseDir + "/*")
    fmt.Println(files)

    imgs := [][]byte{}
    for _, file := range files {
        imgFile, err := os.Open(file)
        if err != nil {
            panic(err)
        }
        defer imgFile.Close()

        fInfo, err := imgFile.Stat()
        if err != nil {
            panic(err)
        }
        size := fInfo.Size()
        buf := make([]byte, size)

        reader := bufio.NewReader(imgFile)
        _, err = reader.Read(buf)
        if err != nil {
            panic(err)
        }

        imgs = append(imgs, buf)
    }

    fmt.Println(len(imgs))
    fmt.Println(imgs[0][:10])

    var wg sync.WaitGroup
    for _, imgBytes := range imgs {
        wg.Add(1)
        go func(imgBytes []byte) {
            img, _, err := image.Decode(bytes.NewReader(imgBytes))
            if err != nil {
                panic(err)
            }

            mat, err := gocv.ImageToMatRGB(img)
            if err != nil {
                panic(err)
            }

            rects := classifier.DetectMultiScale(mat)

            fmt.Println(rects)

            wg.Done()
        }(imgBytes)
    }

    wg.Wait()
    fmt.Println("Done")
}
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector
SIGABRT: abort
PC=0x7fff64802e3e m=7 sigcode=0

goroutine 0 [idle]:
runtime: unknown pc 0x7fff64802e3e
stack: frame={sp:0x700005db6c78, fp:0x0} stack=[0x700005d38290,0x700005db7e90)
0000700005db6b78:  0000000000000001  000000000b218060
0000700005db6b88:  000000000b210088  0000700005db6bb0
0000700005db6b98:  000000000b1d8d78  00007fff6270e7aa
0000700005db6ba8:  0000700005db6be0  0000700005db6bf0
0000700005db6bb8:  000000000b1d3672  0000000000000000
0000700005db6bc8:  0000000032aaaba2  0000000000000000
0000700005db6bd8:  0000700005db6d10  0000000000000000
0000700005db6be8:  0000000032aaaba2  0000000000000000
0000700005db6bf8:  0000000000000000  0000000000000000
0000700005db6c08:  0000000000000000  0000000000000000
0000700005db6c18:  0000000000000000  0000000000000000
0000700005db6c28:  0000000000000003  0000000000000000
0000700005db6c38:  0000000000000000  0000000000000000
0000700005db6c48:  0000000000000000  00007fff9d6d7240
0000700005db6c58:  00007fff9d6d6ca0  00007fff6473e522
0000700005db6c68:  0000000000000000  0000700005db6cb0
0000700005db6c78: <00007fff64941150  0000700005db8000
0000700005db6c88:  0000700005db6cc8  0000000000000008
0000700005db6c98:  0000000000000030  00007fff6275b4d4
0000700005db6ca8:  00007fff9d6d79a0  0000700005db6ce0
0000700005db6cb8:  00007fff6475f312  0000000000000008
0000700005db6cc8:  00000000ffffffdf  ffffffff6275b4d4
0000700005db6cd8:  0000700005db6de0  0000700005db6e10
0000700005db6ce8:  00007fff6273af8f  0000003000000020
0000700005db6cf8:  0000700005db6e20  0000700005db6d30
0000700005db6d08:  0000000000000001  0000003000000020
0000700005db6d18:  0000700005db6e20  0000700005db6d30
0000700005db6d28:  0000000000000000  0000000000000009
0000700005db6d38:  00007fff6275b55c  0000700005db6e20
0000700005db6d48:  000000000cd362c8  00007fff9cff2058
0000700005db6d58:  0000700005db5d40  00007fff63ad9ef0
0000700005db6d68:  00007fff63ac3db2  0000000000000000
runtime: unknown pc 0x7fff64802e3e
stack: frame={sp:0x700005db6c78, fp:0x0} stack=[0x700005d38290,0x700005db7e90)
0000700005db6b78:  0000000000000001  000000000b218060
0000700005db6b88:  000000000b210088  0000700005db6bb0
0000700005db6b98:  000000000b1d8d78  00007fff6270e7aa
0000700005db6ba8:  0000700005db6be0  0000700005db6bf0
0000700005db6bb8:  000000000b1d3672  0000000000000000
0000700005db6bc8:  0000000032aaaba2  0000000000000000
0000700005db6bd8:  0000700005db6d10  0000000000000000
0000700005db6be8:  0000000032aaaba2  0000000000000000
0000700005db6bf8:  0000000000000000  0000000000000000
0000700005db6c08:  0000000000000000  0000000000000000
0000700005db6c18:  0000000000000000  0000000000000000
0000700005db6c28:  0000000000000003  0000000000000000
0000700005db6c38:  0000000000000000  0000000000000000
0000700005db6c48:  0000000000000000  00007fff9d6d7240
0000700005db6c58:  00007fff9d6d6ca0  00007fff6473e522
0000700005db6c68:  0000000000000000  0000700005db6cb0
0000700005db6c78: <00007fff64941150  0000700005db8000
0000700005db6c88:  0000700005db6cc8  0000000000000008
0000700005db6c98:  0000000000000030  00007fff6275b4d4
0000700005db6ca8:  00007fff9d6d79a0  0000700005db6ce0
0000700005db6cb8:  00007fff6475f312  0000000000000008
0000700005db6cc8:  00000000ffffffdf  ffffffff6275b4d4
0000700005db6cd8:  0000700005db6de0  0000700005db6e10
0000700005db6ce8:  00007fff6273af8f  0000003000000020
0000700005db6cf8:  0000700005db6e20  0000700005db6d30
0000700005db6d08:  0000000000000001  0000003000000020
0000700005db6d18:  0000700005db6e20  0000700005db6d30
0000700005db6d28:  0000000000000000  0000000000000009
0000700005db6d38:  00007fff6275b55c  0000700005db6e20
0000700005db6d48:  000000000cd362c8  00007fff9cff2058
0000700005db6d58:  0000700005db5d40  00007fff63ad9ef0
0000700005db6d68:  00007fff63ac3db2  0000000000000000

goroutine 43 [syscall]:
runtime.cgocall(0x40be3e0, 0xc000879eb0, 0x10)
        /usr/local/Cellar/go/1.11.1/libexec/src/runtime/cgocall.go:128 +0x5e fp=0xc000879e80 sp=0xc000879e48 pc=0x400605e
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv._Cfunc_CascadeClassifier_DetectMultiScale(0xce00020, 0xcd355e0, 0x0, 0x0)
        _cgo_gotypes.go:890 +0x4d fp=0xc000879eb0 sp=0xc000879e80 pc=0x40a30ed
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale.func1(0xce00020, 0xcd355e0, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x94 fp=0xc000879ef8 sp=0xc000879eb0 pc=0x40a3fd4
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale(0xc0000aa070, 0xcd355e0, 0x0, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x4d fp=0xc000879f40 sp=0xc000879ef8 pc=0x40a3cdd
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc00006e000, 0x1ede, 0x1ede)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:80 +0xec fp=0xc000879fb8 sp=0xc000879f40 pc=0x40ba6ac
runtime.goexit()
        /usr/local/Cellar/go/1.11.1/libexec/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc000879fc0 sp=0xc000879fb8 pc=0x4054f31
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc0000a4048)
        /usr/local/Cellar/go/1.11.1/libexec/src/runtime/sema.go:56 +0x39
sync.(*WaitGroup).Wait(0xc0000a4040)
        /usr/local/Cellar/go/1.11.1/libexec/src/sync/waitgroup.go:130 +0x64
main.main()
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:88 +0x3f3

goroutine 36 [runnable]:
compress/flate.(*decompressor).huffSym(0xc000884600, 0xc000884628, 0x8, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:707 +0x24d
compress/flate.(*decompressor).huffmanBlock(0xc000884600)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:494 +0xe9
compress/flate.(*decompressor).Read(0xc000884600, 0xc001bb99aa, 0x91f, 0x91f, 0x1aa, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:347 +0x77
compress/zlib.(*reader).Read(0xc000c3a000, 0xc001bb99aa, 0x91f, 0x91f, 0x1aa, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/zlib/reader.go:94 +0x76
io.ReadAtLeast(0xfa3faa8, 0xc000c3a000, 0xc001bb9800, 0xac9, 0xac9, 0xac9, 0xac9, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:310 +0x88
io.ReadFull(0xfa3faa8, 0xc000c3a000, 0xc001bb9800, 0xac9, 0xac9, 0xac9, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:329 +0x58
image/png.(*decoder).readImagePass(0xc000874000, 0xfa3faa8, 0xc000c3a000, 0x0, 0xc000c3a000, 0x0, 0xc000874078, 0x4, 0x2fc)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:508 +0x572
image/png.(*decoder).decode(0xc000874000, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:371 +0x566
image/png.(*decoder).parseIDAT(0xc000874000, 0x4000, 0x410a828, 0x4)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:845 +0x36
image/png.(*decoder).parseChunk(0xc000874000, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:905 +0x3cd
image/png.Decode(0x4123240, 0xc00085c000, 0xc00085c000, 0x4123240, 0xc00085c000, 0x8)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:964 +0x139
image.Decode(0x4123260, 0xc000844000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/format.go:84 +0x101
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc0000da000, 0x94fd9, 0x94fd9)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:70 +0x8b
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 37 [runnable]:
compress/flate.(*huffmanDecoder).init(0xc000b1d328, 0xc000c36a80, 0x10a, 0x13c, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:178 +0x319
compress/flate.(*decompressor).readHuffman(0xc000b1d300, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:459 +0x51b
compress/flate.(*decompressor).nextBlock(0xc000b1d300)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:322 +0x117
compress/flate.(*decompressor).Read(0xc000b1d300, 0xc000ea8000, 0xb01, 0xb01, 0x0, 0x203000, 0x203000)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:347 +0x77
compress/zlib.(*reader).Read(0xc000c3a0a0, 0xc000ea8000, 0xb01, 0xb01, 0xb01, 0xc000ea8c00, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/zlib/reader.go:94 +0x76
io.ReadAtLeast(0xfa3faa8, 0xc000c3a0a0, 0xc000ea8000, 0xb01, 0xb01, 0xb01, 0x40e2240, 0x1, 0xc000ea8c00)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:310 +0x88
io.ReadFull(0xfa3faa8, 0xc000c3a0a0, 0xc000ea8000, 0xb01, 0xb01, 0xb01, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:329 +0x58
image/png.(*decoder).readImagePass(0xc00084a400, 0xfa3faa8, 0xc000c3a0a0, 0x0, 0xc000c3a000, 0x0, 0xc00084a478, 0x4, 0x2fc)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:508 +0x572
image/png.(*decoder).decode(0xc00084a400, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:371 +0x566
image/png.(*decoder).parseIDAT(0xc00084a400, 0x4000, 0x410a828, 0x4)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:845 +0x36
image/png.(*decoder).parseChunk(0xc00084a400, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:905 +0x3cd
image/png.Decode(0x4123240, 0xc0008cc000, 0xc0008cc000, 0x4123240, 0xc0008cc000, 0x8)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:964 +0x139
image.Decode(0x4123260, 0xc0008a4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/format.go:84 +0x101
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc000172000, 0xd8262, 0xd8262)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:70 +0x8b
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 38 [runnable]:
compress/flate.(*decompressor).huffSym(0xc000b1c000, 0xc000b1c028, 0x4, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:707 +0x24d
compress/flate.(*decompressor).huffmanBlock(0xc000b1c000)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:494 +0xe9
compress/flate.(*decompressor).Read(0xc000b1c000, 0xc001bb94a9, 0x218, 0x218, 0x8a9, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:347 +0x77
compress/zlib.(*reader).Read(0xc0008ce000, 0xc001bb94a9, 0x218, 0x218, 0x8a9, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/zlib/reader.go:94 +0x76
io.ReadAtLeast(0xfa3faa8, 0xc0008ce000, 0xc001bb8c00, 0xac1, 0xac1, 0xac1, 0xac1, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:310 +0x88
io.ReadFull(0xfa3faa8, 0xc0008ce000, 0xc001bb8c00, 0xac1, 0xac1, 0xac1, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:329 +0x58
image/png.(*decoder).readImagePass(0xc000840000, 0xfa3faa8, 0xc0008ce000, 0x0, 0xc0008ce000, 0x0, 0xc000840078, 0x4, 0x2fc)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:508 +0x572
image/png.(*decoder).decode(0xc000840000, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:371 +0x566
image/png.(*decoder).parseIDAT(0xc000840000, 0x4000, 0x410a828, 0x4)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:845 +0x36
image/png.(*decoder).parseChunk(0xc000840000, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:905 +0x3cd
image/png.Decode(0x4123240, 0xc000828000, 0xc000828000, 0x4123240, 0xc000828000, 0x8)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:964 +0x139
image.Decode(0x4123260, 0xc0000d4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/format.go:84 +0x101
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc00024c000, 0xad953, 0xad953)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:70 +0x8b
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 39 [runnable]:
image.NewNRGBA(...)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/image.go:365
image/png.(*decoder).readImagePass(0xc00084c000, 0xfa3faa8, 0xc000b22000, 0x0, 0xc000b22000, 0x0, 0xc00084c078, 0x4, 0x2fc)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:466 +0x333d
image/png.(*decoder).decode(0xc00084c000, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:371 +0x566
image/png.(*decoder).parseIDAT(0xc00084c000, 0x4000, 0x410a828, 0x4)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:845 +0x36
image/png.(*decoder).parseChunk(0xc00084c000, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:905 +0x3cd
image/png.Decode(0x4123240, 0xc00083c000, 0xc00083c000, 0x4123240, 0xc00083c000, 0x8)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:964 +0x139
image.Decode(0x4123260, 0xc000836000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/format.go:84 +0x101
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc0002fc000, 0x6ce02, 0x6ce02)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:70 +0x8b
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 40 [runnable]:
compress/flate.(*decompressor).huffSym(0xc0008a6000, 0xc0008a6028, 0x5, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:707 +0x24d
compress/flate.(*decompressor).huffmanBlock(0xc0008a6000)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:494 +0xe9
compress/flate.(*decompressor).Read(0xc0008a6000, 0xc0000d163f, 0x25a, 0x25a, 0x9bf, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/flate/inflate.go:347 +0x77
compress/zlib.(*reader).Read(0xc00085a050, 0xc0000d163f, 0x25a, 0x25a, 0x9bf, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/compress/zlib/reader.go:94 +0x76
io.ReadAtLeast(0xfa3faa8, 0xc00085a050, 0xc0000d0c80, 0xc19, 0xc19, 0xc19, 0xc19, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:310 +0x88
io.ReadFull(0xfa3faa8, 0xc00085a050, 0xc0000d0c80, 0xc19, 0xc19, 0xc19, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:329 +0x58
image/png.(*decoder).readImagePass(0xc000722800, 0xfa3faa8, 0xc00085a050, 0x0, 0xc00085a000, 0x0, 0xc000722878, 0x4, 0x2fc)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:508 +0x572
image/png.(*decoder).decode(0xc000722800, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:371 +0x566
image/png.(*decoder).parseIDAT(0xc000722800, 0x4000, 0x410a828, 0x4)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:845 +0x36
image/png.(*decoder).parseChunk(0xc000722800, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:905 +0x3cd
image/png.Decode(0x4123240, 0xc000070120, 0xc000070120, 0x4123240, 0xc000070120, 0x8)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:964 +0x139
image.Decode(0x4123260, 0xc0000ca030, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/format.go:84 +0x101
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc00036a000, 0xcc23d, 0xcc23d)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:70 +0x8b
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 41 [runnable]:
io.ReadFull(0xfa3faa8, 0xc00085a000, 0xc001bc3a80, 0x19a9, 0x19a9, 0x19a9, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:328 +0x8e
image/png.(*decoder).readImagePass(0xc000722400, 0xfa3faa8, 0xc00085a000, 0x0, 0xc00085a000, 0x0, 0xc000722478, 0x4, 0x2fc)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:508 +0x572
image/png.(*decoder).decode(0xc000722400, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:371 +0x566
image/png.(*decoder).parseIDAT(0xc000722400, 0x4000, 0x410a828, 0x4)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:845 +0x36
image/png.(*decoder).parseChunk(0xc000722400, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:905 +0x3cd
image/png.Decode(0x4123240, 0xc000070060, 0xc000070060, 0x4123240, 0xc000070060, 0x8)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:964 +0x139
image.Decode(0x4123260, 0xc0000ca000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/format.go:84 +0x101
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc00043a000, 0x2ca3ac, 0x2ca3ac)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:70 +0x8b
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 42 [runnable]:
io.ReadFull(0xfa3faa8, 0xc000846050, 0xc0000c3200, 0x8b1, 0x8b1, 0x8b1, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/io/io.go:328 +0x8e
image/png.(*decoder).readImagePass(0xc00004dc00, 0xfa3faa8, 0xc000846050, 0x0, 0xc000846000, 0x0, 0xc00004dc78, 0x4, 0x2fc)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:508 +0x572
image/png.(*decoder).decode(0xc00004dc00, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:371 +0x566
image/png.(*decoder).parseIDAT(0xc00004dc00, 0x4000, 0x410a828, 0x4)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:845 +0x36
image/png.(*decoder).parseChunk(0xc00004dc00, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:905 +0x3cd
image/png.Decode(0x4123240, 0xc0000c0120, 0xc0000c0120, 0x4123240, 0xc0000c0120, 0x8)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:964 +0x139
image.Decode(0x4123260, 0xc0000bc030, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/format.go:84 +0x101
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc000742000, 0x3f5fb, 0x3f5fb)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:70 +0x8b
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 44 [runnable]:
image.NewNRGBA(...)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/image.go:365
image/png.(*decoder).readImagePass(0xc00004d800, 0xfa3faa8, 0xc000846000, 0x0, 0xc000846000, 0x0, 0xc00004d878, 0x4, 0x2fc)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:466 +0x333d
image/png.(*decoder).decode(0xc00004d800, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:371 +0x566
image/png.(*decoder).parseIDAT(0xc00004d800, 0x4000, 0x410a828, 0x4)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:845 +0x36
image/png.(*decoder).parseChunk(0xc00004d800, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:905 +0x3cd
image/png.Decode(0x4123240, 0xc0000c0000, 0xc0000c0000, 0x4123240, 0xc0000c0000, 0x8)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/png/reader.go:964 +0x139
image.Decode(0x4123260, 0xc0000bc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/local/Cellar/go/1.11.1/libexec/src/image/format.go:84 +0x101
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc000782000, 0x766b8, 0x766b8)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:70 +0x8b
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 45 [runnable]:
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv._Cfunc_CascadeClassifier_DetectMultiScale(0xce00020, 0x11d00000, 0xfb00c90, 0x1)
        _cgo_gotypes.go:890 +0x4d
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale.func1(0xce00020, 0x11d00000, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x94
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale(0xc0000aa070, 0x11d00000, 0x0, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x4d
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc0007fa000, 0xb2d8, 0xb2d8)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:80 +0xec
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 46 [runnable]:
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv._Cfunc_CascadeClassifier_DetectMultiScale(0xce00020, 0x11800610, 0xce00080, 0x1)
        _cgo_gotypes.go:890 +0x4d
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale.func1(0xce00020, 0x11800610, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x94
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale(0xc0000aa070, 0x11800610, 0x0, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x4d
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc000806000, 0x9ae7, 0x9ae7)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:80 +0xec
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 47 [runnable]:
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv._Cfunc_CascadeClassifier_DetectMultiScale(0xce00020, 0x11800000, 0xce01370, 0x1)
        _cgo_gotypes.go:890 +0x4d
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale.func1(0xce00020, 0x11800000, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x94
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale(0xc0000aa070, 0x11800000, 0x0, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x4d
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc000810000, 0xb079, 0xb079)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:80 +0xec
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

goroutine 48 [runnable]:
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv._Cfunc_CascadeClassifier_DetectMultiScale(0xce00020, 0xfc00000, 0x148002f0, 0x1)
        _cgo_gotypes.go:890 +0x4d
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale.func1(0xce00020, 0xfc00000, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x94
fe.sas.com/face-recognition/vendor/gocv.io/x/gocv.(*CascadeClassifier).DetectMultiScale(0xc0000aa070, 0xfc00000, 0x0, 0x0, 0x0)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/vendor/gocv.io/x/gocv/objdetect.go:52 +0x4d
main.main.func1(0xc0000aa070, 0xc0000a4040, 0xc00081c000, 0xbefb, 0xbefb)
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:80 +0xec
created by main.main
        /Users/zhlang/go/src/fe.sas.com/face-recognition/load-testing/local/main.go:69 +0x3cc

rax    0x0
rbx    0x700005db8000
rcx    0x700005db6c78
rdx    0x0
rdi    0x1003
rsi    0x6
rbp    0x700005db6cb0
rsp    0x700005db6c78
r8     0x700005db6b40
r9     0x700005db6d10
r10    0x0
r11    0x206
r12    0x1003
r13    0x30
r14    0x6
r15    0x2d
rip    0x7fff64802e3e
rflags 0x206
cs     0x7
fs     0x0
gs     0x0
exit status 2

Your Environment

deadprogram commented 5 years ago

Hello @zhlangsas you should know that as far as I know none of the OpenCV algorithms are re-entrant.

This applies to the CascadeClassifier. The solution is to create a new instance of the algorithm per goroutine. You would remove this code from your main function:

classifier := gocv.NewCascadeClassifier()
defer classifier.Close()

modelPath := "./haarcascade_frontalface_default.xml"
if !classifier.Load(modelPath) {
    panic(fmt.Errorf("Error loading cascade file: %v", modelPath))
}

Then replace your go routine code with something like this (untested) code:

for _, imgBytes := range imgs {
    wg.Add(1)
    go func(imgBytes []byte) {
                classifier := gocv.NewCascadeClassifier()
            defer classifier.Close()

            modelPath := "./haarcascade_frontalface_default.xml"
            if !classifier.Load(modelPath) {
                panic(fmt.Errorf("Error loading cascade file: %v", modelPath))
            }

        img, _, err := image.Decode(bytes.NewReader(imgBytes))
        if err != nil {
            panic(err)
        }

        mat, err := gocv.ImageToMatRGB(img)
        if err != nil {
            panic(err)
        }

        rects := classifier.DetectMultiScale(mat)

        fmt.Println(rects)

        wg.Done()
    }(imgBytes)
}

Hope that helps!

zak905 commented 5 years ago

@deadprogram is there a way to clone the CascadeClassifier instance instead of having to load from disk each time ? I am experiencing the same here. I tried copying the instance into another variable still getting the same issue.

zak905 commented 5 years ago

Also, it's seems like calling classifier.Load(path) causes a memory leak even if classifier.Close() is called. I can provide a code sample if needed.

zak905 commented 5 years ago

@deadprogram what do you think?

deadprogram commented 5 years ago

Yes, please provide a code sample. Certainly looks like it should free the classifier on Close().

https://github.com/hybridgroup/gocv/blob/0d9b22a6450a7d81761a4b763f58fb99e962ab47/objdetect.cpp#L10

Thanks!

zak905 commented 5 years ago

Here is a code sample: https://github.com/zak905/gocv-classifiers-memory-leak-demo

I also added instructions on how to test.

deadprogram commented 5 years ago

Just on a brief lookover of that code, seems like imageMat never gets freed:

imageMat, _ := gocv.IMDecode(imageBytes, gocv.IMReadUnchanged)

You might want to try

imageMat, _ := gocv.IMDecode(imageBytes, gocv.IMReadUnchanged)
defer imageMat.Close()

Let me know if that helps.

zak905 commented 5 years ago

@deadprogram thanks for checking. With your change it's not leaking memory. In my code, I have some leak even if I close the mat. I must be looking at wrong piece of code.

zak905 commented 5 years ago

It turns out gocv.HoughCirclesWithParams takes forever, and does not terminate if given large images (I tried with two right now), event with different parameters (I tried with various minDistance and radius values). This may be related directly to the behavior of OpenCV, it would be nice if there is a timeout. Is this a good idea for a PR ? we could use a channel / goroutine and if C.HoughCirclesWithParams or C.HoughCircles goes beyond some timeout return an error or an empty mat.

Here is an example of an image that causes that https://s3-eu-west-1.amazonaws.com/gwidgets/large_image.jpg it's possible to reproduce by using the image in this test https://github.com/hybridgroup/gocv/blob/master/imgproc_test.go#L648

zak905 commented 5 years ago

It turns out, it's not possible to interrupt a cgo call directly, even if I use a channel + select statements, the actual call will still be running and will still be consuming cpu and memory in the background.

zak905 commented 5 years ago

The only solution I found is creating a separate executable : calling it directly using cmd package, and in case it takes more than a certain amount of time, killing it.

zak905 commented 5 years ago

More findings: using the same picture with OpenCV 3, does not take forever and does return.