[Перевод] Строим систему распознавания лиц на основе Golang и OpenCV

d549aaccd055ce9a0a5c233c5882cada.png


OpenCV — библиотека, разработанная для проектов по компьютерному зрению. Ей уже около 20 лет. Я использовал ее еще в колледже и до сих пор применяю для своих проектов на C++ и Python, поскольку она имеет неплохую поддержку этих языков.

Но когда я начал изучать и использовать Go, мне стало интересно, можно ли применить OpenCV для работы с этим языком. В то время уже существовали примеры и туториалы по интеграции, но мне показалось, что они слишком сложные. Чуть позже мне в руки попался враппер, созданный командой The Hybrid Group. В этой статье я покажу, как начать с GoCV, разработав простую систему распознавания лиц с каскадами Хаара (Haar Cascades).

Skillbox рекомендует: Практический курс «Python-разработчик с нуля».

Напоминаем: для всех читателей «Хабра» — скидка 10 000 рублей при записи на любой курс Skillbox по промокоду «Хабр».


Что потребуется:

  • Go;
  • OpenCV (ссылки на установщик ниже);
  • веб- или обычная видеокамера.


Установка

Пример 1


В первом примере мы попробуем создать приложение, которое открывает окно с демонстрацией видеопотока камеры.

Сначала надо импортировать библиотеки, нужные для работы.

import (
«log»
«gocv.io/x/gocv»
)

После этого нужно создать объект VideoCapture с использованием функции VideoCaptureDevice. Последняя дает возможность захватывать видеопоток с помощью камеры. В функции используется целое число в качестве параметра (он представляет ID устройства).

webcam, err := gocv.VideoCaptureDevice(0)
if err != nil {    log.Fatalf("error opening web cam: %v”, err)
}
defer webcam.Close()


Теперь нужно создать n-мерную матрицу. Она будет хранить изображения, считанные с камеры.

img := gocv.NewMat()
defer img.Close()


Для отображения видеопотока нужно создать окно — это можно сделать с помощью функции NewWindow.

window := gocv.NewWindow("webcamwindow”)
defer window.Close()


Теперь перейдем к самой интересной части.

Поскольку видео представляет собой непрерывный поток кадров-изображений, нам нужно будет создать бесконечный цикл для бесконечного считывания видеопотока камеры. Для этого нужен метод Read типа VideoCapture. Он будет ожидать тип Mat (матрица, которую мы создали выше), возвращая логическое значение, указывающее, был ли кадр из VideoCapture считан успешно или нет.

for {     
        if ok := webcam.Read(&img); !ok || img.Empty( {
        log.Println("Unable to read from the webcam”)    continue
     }
.
.
.
}


Теперь нужно отобразить фрейм в созданном окне. Пауза для перехода к следующему фрейму — 50 мс.

window.IMShow (img)
window.WaitKey (50)

После запуска приложения откроется окно с видеопотоком с камеры.

a252e815e5e8627147512749e1f63699.png

package main
 
import (
"log"
 
"gocv.io/x/gocv"
)
 
func main() {
webcam, err := gocv.VideoCaptureDevice(0)
if err != nil {
    log.Fatalf("error opening device: %v", err)
}
defer webcam.Close()
 
img := gocv.NewMat()
defer img.Close()
 
window := gocv.NewWindow("webcamwindow")
defer window.Close()
 
for {
if ok := webcam.Read(&img); !ok || img.Empty() {
log.Println("Unable to read from the webcam")
continue
}
 
window.IMShow(img)
window.WaitKey(50)
}
}


Пример 2


В этом примере давайте воспользуемся предыдущим примером и построим систему по распознаванию лиц на основе Haar Cascades (каскады Хаара).

Каскады Хаара — это каскадные классификаторы, которые обучаются на основе техники вейвлетов Хаара. Они анализируют пиксели в изображении, чтобы обнаружить определенные признаки. Чтобы узнать больше о Haar Cascades, можно пройти по ссылкам ниже.

Viola-Jones object detection framework
Cascading classifiers
Haar-like feature

Скачать уже обученные каскады можно здесь. В текущем примере каскады будут использоваться для идентификации лица человека в фас.

Для того чтобы сделать это, нужно создать классификатор и скормить ему уже обученный файл (выше дана ссылка). Я уже загрузил файл pencv_haarcascade_frontalface_default.xml в директорию, где расположена наша программа.

harrcascade := "opencv_haarcascade_frontalface_default.xml”classifier := gocv.NewCascadeClassifier()classifier.Load(harrcascade)
defer classifier.Close()


Для обнаружения лиц на изображении нужно воспользоваться методом DetectMultiScale. Эта функция принимает кадр (тип Mat), который был только что считан с видеопотока камеры, и возвращает массив типа Rectangle. Размер массива представляет количество лиц, которые классификатор смог обнаружить в кадре. Затем, чтобы убедиться, что мы видим то, что он нашел, давайте пройдемся по списку прямоугольников и выведем объект Rectangle на консоль, создав границу вокруг обнаруженного прямоугольника. Это можно сделать при помощи функции Rectangle. Она будет принимать Mat, считанный камерой, объект Rectangle, который был возвращен методом DetectMultiScale, цвет и толщину для границы.

for _, r := range rects {
fmt.Println("detected”, r)
gocv.Rectangle(&img, r, color, 2)
}


26e10c5871175eb78a8f1ec4d65056d0.png

e0e5727236a25895003151ab2f089fb9.png

package main
 
import (
"fmt"
"image/color"
"log"
 
"gocv.io/x/gocv"
)
 
func main() {
webcam, err := gocv.VideoCaptureDevice(0)
if err != nil {
log.Fatalf("error opening web cam: %v", err)
}
defer webcam.Close()
 
img := gocv.NewMat()
defer img.Close()
 
window := gocv.NewWindow("webcamwindow")
defer window.Close()
 
harrcascade := "opencv_haarcascade_frontalface_default.xml"
classifier := gocv.NewCascadeClassifier()
classifier.Load(harrcascade)
defer classifier.Close()
 
color := color.RGBA{0, 255, 0, 0}
for {
if ok := webcam.Read(&img); !ok || img.Empty() {
log.Println("Unable to read from the device")
continue
}
 
rects := classifier.DetectMultiScale(img)
for _, r := range rects {
fmt.Println("detected", r)
gocv.Rectangle(&img, r, color, 3)
}
 
window.IMShow(img)
window.WaitKey(50)
}
}


И… да, все получилось! Теперь у нас есть простая система распознавания лиц, написанная на Go. В скором времени я планирую продолжить эти эксперименты и создать новые классные штуки, сочетая Go и OpenCV.

Если вам интересно, то оцените gRPC web server, который я написал на Python и OpenCV. Он стримит данные в момент обнаружения лица. Это основа для создания разных клиентов на разных языках программирования. Они смогут подключаться к серверу и считывать с него данные.

Спасибо, что прочитали статью!

Skillbox рекомендует:

© Habrahabr.ru