Golang 异步人脸检测

huangapple go评论78阅读模式
英文:

Golang async face detection

问题

我正在使用一个Go语言的OpenCV绑定库(https://github.com/lazywei/go-opencv),并尝试异步检测10张图像中的对象,但一直遇到这个panic错误。只检测4张图像时不会出错。

我使用了sync.WaitGroup来同步goroutine的执行。

我对OpenCV和Go都比较新手,正在尝试找出问题出在哪里。我猜测可能是某个资源被耗尽了,但具体是哪个资源我不确定。

英文:

I'm using an OpenCV binding library for Go and trying to asynchronously detect objects in 10 images but keep getting this panic. Detecting only 4 images never fails.

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()

I'm fairly new to OpenCV and Go and trying to figure where the problem lies. I'm guessing some resource is being exhausted but which one.

答案1

得分: 12

每次调用DetectObjects时,OpenCV的底层实现会构建一个分类器树,并将其存储在cascade中。你可以在https://github.com/Itseez/opencv/blob/master/modules/objdetect/src/haar.cpp的第2002行看到对这些内存块的处理的一部分。

你的原始代码只有一个全局的级联分类器。每次调用DetectObjects时,新的goroutine都会使用相同的根级联分类器。每个新的图像都会释放旧的内存并重新构建一个新的树,最终它们会互相覆盖内存使用并导致通过0进行解引用,从而引发panic。

将级联分类器的分配移到goroutine内部为每个DetectObject调用分配一个新的级联分类器,它们不共享任何内存。

之所以在4个图像上从未发生过问题,但在5个图像上失败,是计算机的特性。你在4个图像上运气好,从未遇到问题。你总是在5个图像上遇到问题,因为每次都发生了完全相同的事情(无论并发性如何)。

多次重复相同的图像不会导致级联分类器树被重新构建。如果图像没有改变,为什么要做额外的工作...这是OpenCV中处理多个图像帧的优化。

英文:

Each time you call DetectObjects the underlying implementation of OpenCV builds a tree of classifiers and stores them inside of cascade. You can see part of the handling of these chunks of memory at https://github.com/Itseez/opencv/blob/master/modules/objdetect/src/haar.cpp line 2002

Your original code only had one cascade as a global. Each new go routine call DetectObjects used the same root cascade. Each new image would have free'd the old memory and rebuilt a new tree and eventually they would stomp on each other's memory use and cause a dereference through 0, causing the panic.

Moving the allocation of the cascade inside the goroutine allocates a new one for each DetectObject call and they do not share any memory.

The fact that it never happened on 4 images, but failed on 5 images is the nature of computing. You got lucky with 4 images and never saw the problem. You always saw the problem on 5 images because exactly the same thing happened each time (regardless of concurrency).

Repeating the same image multiple times doesn't cause the cascade tree to be rebuilt. If the image didn't change why do the work ... an optimization in OpenCV to handle multiple images frames.

答案2

得分: 3

问题似乎是将级联器作为全局变量的原因。

一旦我将
cascade := opencv.LoadHaarClassifierCascade("haarcascade_frontalface_alt.xml")
移动到协程中,一切都正常了。

英文:

The problem seemed to be having the cascade as a global variable.

Once I moved
cascade := opencv.LoadHaarClassifierCascade("haarcascade_frontalface_alt.xml")
into the goroutine all was fine.

答案3

得分: 2

你没有处理空的image

image := opencv.LoadImage(strconv.Itoa(i) + ".jpg")
if image == nil {
    // 处理错误
}
英文:

You are not handling for a nil image

image := opencv.LoadImage(strconv.Itoa(i) + ".jpg")
if image == nil {
    // handle error
}

huangapple
  • 本文由 发表于 2014年9月11日 05:49:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/25775650.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定