Обнаружение лица ацетин Golang

Я использую библиотеку привязки OpenCV для Go и пытаюсь асинхронно обнаруживать объекты на 10 изображениях, но продолжаю получать этот панические. Обнаружение только 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 и пытаюсь понять, где проблема. Я предполагаю, что какой-то ресурс исчерпан, но какой.

Ответ 1

Каждый раз, когда вы вызываете DetectObjects, базовая реализация OpenCV строит дерево классификаторов и сохраняет их внутри cascade. Вы можете увидеть часть обработки этих фрагментов памяти на https://github.com/Itseez/opencv/blob/master/modules/objdetect/src/haar.cpp строке 2002

В исходном коде только один каскад был глобальным. Каждый новый рутинный вызов DetectObjects использовал один и тот же корневой каскад. Каждое новое изображение освободило бы прежнюю память и восстановило новое дерево, и в конечном итоге они будут топать друг другу в использовании памяти и вызывать разыменование через 0, вызывая панику.

Перемещение выделения каскада внутри goroutine выделяет новый для каждого вызова DetectObject, и они не разделяют память.

Тот факт, что он никогда не происходил на 4 изображениях, но не удалось на 5 изображениях, - это природа вычислений. Вам повезло с 4 изображениями и никогда не видел проблемы. Вы всегда видели проблему на 5 изображениях, потому что точно так же все происходило каждый раз (независимо от concurrency).

Повторение одного и того же изображения несколько раз не приводит к перестройке каскадного дерева. Если изображение не изменилось, зачем нужна работа... оптимизация в OpenCV для обработки нескольких кадров изображений.

Ответ 2

Кажется, что проблема связана с каскадом как глобальной переменной.

Как только я переехал cascade := opencv.LoadHaarClassifierCascade("haarcascade_frontalface_alt.xml")
в goroutine все было хорошо.

Ответ 3

Вы не обрабатываете ниль image

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