IT Notes

OpenCV: Установка и использование под Linux

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

В этой статье мы соберем и установим OpenCV из исходных кодов под Linux, а затем разработаем тестовое приложение, способное находить лица на фотографии с помощью модуля CascadeClassifier:

opencv-face-classifier-demo

Установка OpenCV под Linux

Прежде чем приступать к сборке OpenCV из исходных кодов, рекомендую проверить, что он не доступен в репозиториях вашего дистрибутива Linux. Например, в Archlinux библиотеку OpenCV можно установить следующей командой:

sudo pacman -S opencv

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

Шаг 1: Получаем исходные коды OpenCV из Git

mkdir <путь_где_мы_хотим_вести_сборку>
cd <путь_где_мы_хотим_вести_сборку>
git clone https://github.com/opencv/opencv.git

Шаг 2: Подготавливаем OpenCV к сборке

mkdir release # Предполагается, что мы в каталоге, куда был склонирован git-проект
cd release
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=<путь_куда_мы_хотим_установить_opencv> ../

В качестве каталога установки я использую домашний каталог /home/michael/OpenCV/.

Шаг 3: Собираем и устанавливаем OpenCV

make # Предполагается, что мы в каталоге release/
sudo make install # Если вы устанавливаете OpenCV, как и я, в домашний каталог, то sudo не нужно

Если все прошло без ошибок, то процесс сборки и установки OpenCV завершен. Теперь можно перейти в каталог, который мы указали в параметре CMAKE_INSTALL_PREFIX. Там вы должны увидеть примерно такой набор директорий:

ставки на спорт онлайн андроид. https://www.paradise-r.ru.

drwx------   6 michael michael 4,0K мар 31 08:44 ./
drwx------ 171 michael michael  12K мар 31 09:30 ../
drwx------   2 michael michael 4,0K мар 31 08:44 bin/
drwx------   4 michael michael 4,0K мар 31 08:44 include/
drwx------   3 michael michael 4,0K мар 31 08:44 lib/
drwx------   3 michael michael 4,0K мар 31 08:44 share/

Разработка Qt-проекта с использованием OpenCV

Начнем с подготовки pro-файла:

# …
# Остальное нас сейчас не интересует

INCLUDEPATH += <path_to_opencv_include>
LIBS += -L<path_to_opencv_libs>/

LIBS += -lopencv_core \
        -lopencv_imgproc \
        -lopencv_imgcodecs \
        -lopencv_highgui \
        -lopencv_objdetect

Для успешной работы с OpenCV в Qt-проекте нужно указать пути, где находятся заголовочные файлы и библиотеки. Например, если мы установили OpenCV в домашнем каталоге: ~/OpenCV, то:

INCLUDEPATH += $(HOME)/OpenCV/include/
LIBS += -L$(HOME)/OpenCV/lib/

Также не забываем подключать необходимые opencv-библиотеки:

LIBS += -lopencv_core \
        -lopencv_imgproc \
        -lopencv_imgcodecs \
        -lopencv_highgui \
        -lopencv_objdetect

Теперь переходим к файлу mainwidget.h:

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <opencv2/objdetect.hpp>

#include <QWidget>

namespace Ui {
class MainWidget;
}

class MainWidget : public QWidget {
    Q_OBJECT

public:
    explicit MainWidget( QWidget* parent = 0 );
    ~MainWidget();

private slots:
    void onLoadImage();

private:
    Ui::MainWidget* ui;

    cv::CascadeClassifier m_faceClassifier;
};

#endif // MAINWIDGET_H

Мы лишь подготовили очень простой виджет, в котором одним из полей является объект класса OpenCV - cv::CascadeClassifier.

Реализация в mainwidget.cpp:

#include "mainwidget.h"
#include "ui_mainwidget.h"

#include <opencv2/imgproc.hpp>
#include <opencv2/opencv.hpp>

#include <QFileDialog>
#include <QPainter>

MainWidget::MainWidget( QWidget* parent ) :
    QWidget( parent ),
    ui( new Ui::MainWidget ) {
    ui->setupUi( this );

    m_faceClassifier.load( "haarcascade_frontalface_default.xml" );

    connect( ui->bnOpen, SIGNAL( clicked( bool ) ), SLOT( onLoadImage() ) );
}

MainWidget::~MainWidget() {
    delete ui;
}

void MainWidget::onLoadImage() {
    QString imgPath = QFileDialog::getOpenFileName(
                          this,
                          trUtf8( "Открыть" ),
                          ".",
                          trUtf8( "Изображения (*.jpg *.png *.bmp)" )
                      );

    if( imgPath.isEmpty() ) {
        return;
    }

    cv::Mat img = cv::imread( imgPath.toStdString() );
    cv::Mat gray;
    cv::cvtColor( img, gray, cv::COLOR_BGR2GRAY );
    std::vector< cv::Rect > faces;
    m_faceClassifier.detectMultiScale( gray, faces );

    QPixmap pix( imgPath );
    QPainter painter;
    painter.begin( &pix );
    painter.setPen( Qt::green );
    foreach( const cv::Rect& r, faces ) {
        painter.drawRect( r.x, r.y, r.width, r.height );
    }
    painter.end();

    ui->lbView->setPixmap( pix.scaled( ui->lbView->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
}

Обратите внимание на строку:

m_faceClassifier.load( "haarcascade_frontalface_default.xml" );

Здесь мы загружаем классификатор haarcascade_frontalface_default.xml, обученный на распознавание лиц. Найти его можно в каталоге data/haarcascades/, который расположен в склонированном гит-репозитории OpenCV. Обратите внимание, что этот xml-файл должен находиться в одном каталоге с исполняемым файлом для правильной работы приложения.

Следующий важный фрагмент:

cv::Mat img = cv::imread( imgPath.toStdString() );
cv::Mat gray;
cv::cvtColor( img, gray, cv::COLOR_BGR2GRAY );
std::vector< cv::Rect > faces;
m_faceClassifier.detectMultiScale( gray, faces );

В этом месте мы и выполняем непосредственное распознавание для загруженной фотографии. "Волшебство" происходит в этой строке:

m_faceClassifier.detectMultiScale( gray, faces );

На вход detectMultiScale() получает черно-белое изображение, а возвращает вектор с прямоугольниками, соответствующими всем найденным лицам.

Далее мы просто проходим по получившемуся вектору и помечаем все лица на фотографии зеленой рамкой:

QPixmap pix( imgPath );
QPainter painter;
painter.begin( &pix );
painter.setPen( Qt::green );
foreach( const cv::Rect& r, faces ) {
    painter.drawRect( r.x, r.y, r.width, r.height );
}
painter.end();

Если вы потестируете это приложение подольше, то увидите, что часто встречаются ложные срабатывания (лица находятся там, где их нет). Но решение этой проблемы уже выходит за рамки этой статьи и требует более аккуратного подхода.

Исходники

 Скачать пример распознавания лиц на фотографии с помощью OpenCV

Похожие публикации

Комментарии

почему не под винду?

Anonymous:

почему не под винду?

Статья написана в ответ на вопрос в комментариях. Под Windows процесс установки и подключения к проекту отличается не сильно. Если есть необходимость, то могу подготовить и подобный материал.

Отличное начало, спасибо! Небольшое замечание: вы, видимо, забыли в LIBS -lopencv_imgcodecs

Да можете подготовить материал под винду статья может перерасти в небольшой фото редактор с разными эффектами (фильтры размытие яркость контрастность удаление красных глаз) =)

Anonymous:

Отличное начало, спасибо! Небольшое замечание: вы, видимо, забыли в LIBS -lopencv_imgcodecs

Да. Согласен. С версии OpenCV 3.0 эту библиотеку необходимо подключать для использования возможности чтения/записи изображений. Внес соответствующие поправки в текст статьи.

tysik:

Да можете подготовить материал под винду статья может перерасти в небольшой фото редактор с разными эффектами (фильтры размытие яркость контрастность удаление красных глаз) =)

Хорошая идея. Постепенно постараюсь ее отработать =)

Спасибо за статью!! Давайте еще по OpenCV!

Поддерживаю! 100501 редактор особо не нужен, тот же Gimp умеет и красные глаза и тучу разных спецэффектов. Ну, либо краденый фотошоп.

А вот статей по OpenCV мало.

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

Благодарю за статью!

Пожалуйста =)

Когда будет новая статья ?

Здравствуйте, к сожалению, пока что обещать ничего не могу - на написание полноценных статей пока что нет времени.