我正在使用OpenCV binding library for Go并尝试异步检测10张图片中的对象,但不断获取this panic。仅检测4张图像永远不会失败。
var wg sync.WaitGroup
for j := 0; j < 10; j++ {
wg.Add(1)
go func(i int) {
image := opencv.LoadImage(strconv.Itoa(i) + ".jpg")
defer image.Release()
faces := cascade.DetectObjects(image)
fmt.Println((len(faces) > 0))
wg.Done()
}(j)
}
wg.Wait()
我是OpenCV和Go的新手,并试图找出问题所在。我猜测有些资源正在耗尽但是哪一个。
答案 0 :(得分:13)
每次调用DetectObjects时,OpenCV的底层实现都会构建一个分类器树并将它们存储在cascade
中。你可以在https://github.com/Itseez/opencv/blob/master/modules/objdetect/src/haar.cpp line 2002
您的原始代码只有一个级联作为全局。每个新的常规调用DetectObjects
使用相同的根级联。每个新图像都会释放旧内存并重新构建一个新树,最终它们会踩踏彼此的内存使用并导致取消引用0,从而导致恐慌。
在goroutine中移动级联的分配为每个DetectObject
调用分配一个新的,并且它们不共享任何内存。
它从未发生在4张图像上,但在5张图像上失败的事实是计算的本质。幸运的是有4张图片,从未见过这个问题。你总是在5张图片上看到问题,因为每次都发生了完全相同的事情(无论并发性)。
多次重复同一图像不会导致重建级联树。如果图像没有改变,为什么要工作......在OpenCV中优化处理多个图像帧。
答案 1 :(得分:4)
问题似乎是将级联作为全局变量。
一旦我搬了
cascade := opencv.LoadHaarClassifierCascade("haarcascade_frontalface_alt.xml")
进入goroutine一切都很好。
答案 2 :(得分:2)
您没有处理零image
image := opencv.LoadImage(strconv.Itoa(i) + ".jpg")
if image == nil {
// handle error
}