Imagem de Capa

Instalação do Dlib com OpenBLAS no Windows para C++

Tutorial de instalação da biblioteca Dlib com OpenBLAS no Windows 10 para a linguagem de programação C++

By João Paulo Siqueira At Fri Jan 14 2022 13:25:26 GMT+0000 (Coordinated Universal Time)

#c++ #dlib #openblas

Introdução

Dlib é conjunto de ferramentas C++ que contém algoritmos de aprendizado de máquina e ferramentas para criar softwares complexos em C++, ele é de código aberto e permite que você o use em qualquer aplicativo gratuitamente.

OpenBLAS é uma implementação de código aberto das APIs BLAS e LAPACK, usadas pelo Dlib para tarefas como reconhecimento facial, a utilização dessas APIs melhoram consideravelmente o desempenho desses algoritmos.

Normalmente se usa o Visual Studio para compilar a biblioteca Dlib, porém ainda não consegui compilar o Dlib com OpenBLAS usando o Visual Studio e por esse motivo, usaremos outro compilador. O Visual Studio também não reconheceu o OpenBLAS, ao tentar compilar o Dlib para a linguagem Python.

O compilador que vamos utilizar é o G++, que é um compilador da GNU Compiler Collection, e para isso precisamos instalar o MSYS2, uma coleção de ferramentas e bibliotecas que contêm o MinGW, que por sua vez contêm o compilador G++.

Para compilar, será utilizado o CMake, que é um conjunto de ferramentas multiplataforma de código aberto que vai gerenciar o processo de compilação do Dlib.

Após compilar, será mostrado como configurar um projeto C++ usando o Visual Studio Code para calcula a distância entre dois rostos.

Configurando o Compilador C++

Acesse o site do MSYS2 e baixe seu instalador.

Execute o instalador, e escolha a pasta de instalação:

Marque a opção Run MSYS2 now e clique em Finish.

No terminal que foi aberto, execute o seguinte comando:

pacman -Syu

Então digite Y para finalizar o comando e fechar o Terminal.

Abra novamente o Terminal do MSYS2, clicando no Menu Iniciar e digitando MSYS2 MSYS e pressione Enter, então digite o seguinte comando:

pacman -Su

Por fim, instale o MinGW-w64 com o comando:

pacman -S --needed base-devel mingw-w64-x86_64-toolchain

Então digite Y para prosseguir com a instalação.

Após instalar, feche o terminal e clique novamente no Menu Iniciar, então digite Variáveis de Ambiente e pressione Enter.

Na Janela de Propriedades do Sistema, clique na Aba Avançado, então no botão Variáveis de Ambiente…, então na sessão das Variáveis do sistema, localize a variável Path, clique no botão Editar…, então adicione o endereço dos binários do MinGW64 C:\msys64\mingw64\bin.

Após isso, clique em OK em todas essas janelas.

Para testar se o compilador foi instalado com sucesso, abra o Prompt de Comando e execute os seguintes comando:

g++ --version
gdb --version

Instalando o OpenBLAS

Acesse o repositório do OpenBLAS no GitHub e baixe o arquivo Source code (zip), que é a versão mais recente da biblioteca. Extraia a pasta do OpenBLAS no diretório Downloads, ou em algum outro diretório temporário.

Após a instalação essas pasta pode ser excluídas.

Em seguida, acesse o site do CMake, baixe o arquivo Windows i386 ZIP, e extraia a pasta do CMake no diretório Downloads.

Dentro da pasta do CMake, entre no diretório bin e execute o arquivo cmake-gui.

No campo Where is the source code:, informe o diretório da pasta do OpenBLAS, por exemplo: C:/Users/joaops/Downloads/OpenBLAS-0.3.19.

No campo Where to build the binaries:, informe o mesmo diretório mais a pasta de build, por exemplo: C:/Users/joaops/Downloads/OpenBLAS-0.3.19/build.

Agora clique no botão Configure, será mostrado uma caixa de mensagem avisando que o diretório build não existe e perguntando se você deseja criá-lo, clique em Yes.

Após isso será mostrado uma tela para especificar o gerador do projeto, selecione MinGW Makefiles e clique no botão Finish.

CMake-GUI Select Compiler

Depois que o CMake terminar de configurar o Projeto, localize a propriedade CMAKE_INSTALL_PREFIX e altere o valor para C:\Program Files\OpenBLAS, uma vez que estamos instalando para o sistema de arquivo x64 e não x86.

Então clique no botão Configure mais uma vez para gravar a alteração e depois no botão Generate para gerar o projeto.

CMake-GUI OpenBLAS

Feche o CMake-GUI e abra um Prompt de Comando como Administrador.

Clique no Menu Iniciar do Windows, digite cmd, clique em Executar como administrador, então clique em Sim nessa Janela de Controle de Conta de Usuário.

Navegue até o diretório de build do OpenBLAS:

cd C:\Users\joaops\Downloads\OpenBLAS-0.3.19\build

Então execute o comando para compilar o projeto:

mingw32-make -j12

O argumento -j12 significa que será utilizado 12 jobs, ou 12 threads, para compilar os arquivos em paralelo, essa é a quantidade de threads que o meu processador possui. Verifique quantas threads o seu computador suporta para utilizar o parâmetro correto.

Não é necessário usar todas as threads, posso usar menos, como -j6.

No Windows se usa o comando mingw32-make, mas no Linux se usa o comando make.

Após compilar, execute o comando de instalação:

mingw32-make install

Com isso, o OpenBLAS será instalado no diretório C:\Program Files\OpenBLAS, você já pode fechar o Prompt de Comando e excluir a pasta de código fonte do OpenBLAS que está no diretório Downloads.

Por fim, clique novamente no Menu Iniciar, então digite Variáveis de Ambiente e pressione Enter.

Na Janela de Propriedades do Sistema, clique na Aba Avançado, então no botão Variáveis de Ambiente…, então na sessão das Variáveis do sistema, localize a variável Path, clique no botão Editar…, então adicione o endereço de instalação do OpenBLAS C:\Program Files\OpenBLAS no final da lista.

Após isso, clique em OK em todas essas janelas.

Compilando o Dlib

Pelo site do Dlib, faça o download do código fonte, então extraia o arquivo zip no diretório Downloads ou em algum outro diretório temporário.

Execute o CMake-GUI e configure o campo Where is the source code: com o diretório do código fonte do Dlib C:\Users\joaops\Downloads\dlib-19.22 e o campo Where to build the binaries: com o diretório da pasta build C:\Users\joaops\Downloads\dlib-19.22\build.

Clique no botão Configure, será mostrado uma caixa de mensagem avisando que o diretório build não existe e perguntando se você deseja criá-lo, clique em Yes.

Após isso será mostrado uma tela para especificar o gerador do projeto, selecione MinGW Makefiles e depois no botão Finish.

CMake-GUI Select Compiler

Após o CMake terminar de configurar o projeto, localize a propriedade USE_AVX_INSTRUCTIONS e selecione ela. Não é preciso mudar o diretório de instalação do Dlib na propriedade CMAKE_INSTALL_PREFIX, não será necessário executar o comando de instalação nesse tutorial.

Então clique no botão Configure mais uma vez para gravar a alteração e depois no botão Generate para gerar o projeto.

CMake-GUI Dlib

Note que as propriedade DLIB_USE_BLAS e DLIB_USE_LAPACK estão selecionadas, isso significa que o OpenBLAS foi reconhecido pelo Dlib.

Feche o CMake-GUI e abra um Prompt de Comando, então navegue até o diretório da pasta build:

cd C:\Users\joaops\Downloads\dlib-19.22\build

Então execute o comando para compilar o projeto:

mingw32-make -j12

E com isso a biblioteca DLib foi compilada com a otimização da biblioteca OpenBLAS, bastando apenas configurar ela dentro de um projeto C++.

Configurando um Projeto C++ com DLib pelo Visual Studio Code

Instale o Visual Studio Code e a extensão para C/C++.

No seu diretório de projetos, crie uma nova pasta chamada CalcularDistancia e abra ela no VS Code.

Crie um novo arquivo main.cpp com o seguinte código:

#include <iostream>

using namespace std;

int main(int argc, char const *argv[]) {
    cout << "Olá, Mundo!" << endl;
}

Clique em Terminal, depois em Configurar Tarefa de Build Padrão…, então selecione a opção C/C++: g++.exe arquivo de build ativo.

Ao fazer isso, será criado o arquivo tasks.json com o seguinte conteúdo:

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "cppbuild",
			"label": "C/C++: g++.exe arquivo de build ativo",
			"command": "C:\\msys64\\mingw64\\bin\\g++.exe",
			"args": [
				"-fdiagnostics-color=always",
				"-g",
				"${file}",
				"-o",
				"${fileDirname}\\${fileBasenameNoExtension}.exe"
			],
			"options": {
				"cwd": "${fileDirname}"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": {
				"kind": "build",
				"isDefault": true
			},
			"detail": "compilador: C:\\msys64\\mingw64\\bin\\g++.exe"
		}
	]
}

No Explorador de arquivos do VS Code, selecione o arquivo main.cpp e pressione as teclas Ctrl + Shift + B para compilar o arquivo.

Ao fazer isso, será gerado o arquivo main.exe no mesmo diretório do arquivo selecionado. Para executá-lo, abra o terminal do VS Code com as teclas Ctrl + ', então execute ele pelo terminal:

C:\Users\joaops\Downloads\CalcularDistancia>main.exe

Também é possível executar o programa clicando nele diretamente pelo Explorador de Arquivos do Windows, porém não vai dar nem pra ver o programa executar, pois ele vai abrir e já fechar. Você pode fazer o programa aguardar até que o usuário pressione a tecla Enter adicionando as seguintes linhas:

#include <iostream>

using namespace std;

int main(int argc, char const *argv[]) {
    cout << "Ola, Mundo!" << endl;
    cout << "Precione Enter para sair..." << endl;
    cin.get();
}

Para compilar o programa novamente, selecione o arquivo main.cpp e pressione as teclas Ctrl + Shift + B.

Após compilar e executar esse exemplo básico, podemos prosseguir para a configuração das dependências do projeto e para isso, na raiz do projeto, crie uma pasta chamada deps e outra chamada build.

Dentro da pasta deps, crie outra pasta chamada dlib e dentre dela, crie duas pastas, uma chamada lib e outra chamada include.

Dentro do diretório de build do Dlib, existe uma pasta chamada dlib e dentro dela estão dois arquivos importantes para a configuração do projeto, a biblioteca compilada libdlib.a e o arquivo dlib-1.pc que contêm os parâmetros para compilação.

Conteúdo do arquivo dlib-1.pc:

libdir=C:/Program Files (x86)/dlib_project/lib
includedir=C:/Program Files (x86)/dlib_project/include

Name: dlib
Description: Numerical and networking C++ library
Version: 19.22.0
Libs: -L${libdir} -ldlib ws2_32 winmm comctl32 gdi32 imm32 C:/Program Files/OpenBLAS/lib/libopenblas.a C:/msys64/mingw64/lib/libsqlite3.dll.a
Cflags: -I${includedir}  -IC:/msys64/mingw64/include

Copie o arquivo:

C:\Users\joaops\Downloads\dlib-19.22\build\dlib\libdlib.a

Para dentro do diretório:

C:\Users\joaops\Downloads\CalcularDistancia\deps\dlib\lib

Copie o diretório:

C:\Users\joaops\Downloads\dlib-19.22\dlib

Para dentro do diretório:

C:\Users\joaops\Downloads\CalcularDistancia\deps\dlib\include

Agora abra o arquivo tasks.json e adicione as seguintes configurações:

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "cppbuild",
			"label": "C/C++: g++.exe Windows 10 x64",
			"command": "C:/msys64/mingw64/bin/g++.exe",
			"args": [
				"-fdiagnostics-color=always",
				"-std=c++17",
				// "-g",
				"${file}",
				"-O3",
				"-I",
                "C:/msys64/mingw64/include",
                "-I",
                "${workspaceFolder}/deps/dlib/include",
                "-I",
                "${workspaceFolder}/deps/dlib/include/dlib/external/libpng",
                "-I",
                "${workspaceFolder}/deps/dlib/include/dlib/external/libjpeg",
                "-L",
                "${workspaceFolder}/deps/dlib/lib",
                "-l",
                "dlib",
				"-l",
                "ws2_32",
				"-l",
                "winmm",
				"-l",
                "comctl32",
				"-l",
                "gdi32",
				"-l",
                "imm32",
				"-L",
				"C:/Program Files/OpenBLAS/lib",
				"-l",
				"openblas",
				"-D",
                "DLIB_PNG_SUPPORT",
                "-D",
                "DLIB_JPEG_SUPPORT",
				"-o",
				"${fileDirname}/build/${fileBasenameNoExtension}.exe"
			],
			"options": {
				"cwd": "${fileDirname}"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": {
				"kind": "build",
				"isDefault": true
			},
			"detail": "compilador: C:\\msys64\\mingw64\\bin\\g++.exe"
		}
	]
}

Perceba que eu adicionei os alguns do parâmetros que estavam no arquivo dlib-1.pc e modifiquei outras configurações.

No arquivo main.cpp copie o seguinte código:

#include <chrono>
#include <iostream>
#include <dlib/dnn.h>
#include <dlib/image_io.h>
#include <dlib/clustering.h>
#include <dlib/gui_widgets.h>
#include <dlib/image_processing.h>
#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing/render_face_detections.h>

using namespace std;
using namespace dlib;

template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual = add_prev1<block<N,BN,1,tag1<SUBNET>>>;

template <template <int,template<typename>class,int,typename> class block, int N, template<typename>class BN, typename SUBNET>
using residual_down = add_prev2<avg_pool<2,2,2,2,skip1<tag2<block<N,BN,2,tag1<SUBNET>>>>>>;

template <int N, template <typename> class BN, int stride, typename SUBNET> 
using block  = BN<con<N,3,3,1,1,relu<BN<con<N,3,3,stride,stride,SUBNET>>>>>;

template <int N, typename SUBNET> using ares      = relu<residual<block,N,affine,SUBNET>>;
template <int N, typename SUBNET> using ares_down = relu<residual_down<block,N,affine,SUBNET>>;

template <typename SUBNET> using alevel0 = ares_down<256,SUBNET>;
template <typename SUBNET> using alevel1 = ares<256,ares<256,ares_down<256,SUBNET>>>;
template <typename SUBNET> using alevel2 = ares<128,ares<128,ares_down<128,SUBNET>>>;
template <typename SUBNET> using alevel3 = ares<64,ares<64,ares<64,ares_down<64,SUBNET>>>>;
template <typename SUBNET> using alevel4 = ares<32,ares<32,ares<32,SUBNET>>>;

using anet_type = loss_metric<fc_no_bias<128,avg_pool_everything<
                            alevel0<
                            alevel1<
                            alevel2<
                            alevel3<
                            alevel4<
                            max_pool<3,3,2,2,relu<affine<con<32,7,7,2,2,
                            input_rgb_image_sized<150>
                            >>>>>>>>>>>>;

int main(int argc, char const *argv[]) {
    try {
        auto tempo_total_inicio = std::chrono::high_resolution_clock::now();

        // Carrega o detector hog
        frontal_face_detector detectorHog = get_frontal_face_detector();
        
        // Carrega o shape predictor
        shape_predictor shapePredictor;
        deserialize("shape_predictor_68_face_landmarks.dat") >> shapePredictor;
        
        // Caminho da imagem 1
        string caminho_imagem_1 = "pessoas/11-12.jpg";

        // Caminho da imagem 2
        string caminho_imagem_2 = "pessoas/26-12.jpg";

        // Pega o caminho das imagens pelo argumento
        if (argc == 3) {
            caminho_imagem_1 = argv[1];
            caminho_imagem_2 = argv[2];
        }

        // Carrega a imagem 1
        array2d<rgb_pixel> imagem_1;
        load_image(imagem_1, caminho_imagem_1);
        // Converte a imagem 1 para gray
        array2d<unsigned char> imagem_cinza_1;
        assign_image(imagem_cinza_1, imagem_1);
        // Detecta as faces na imagem 1
        std::vector<rectangle> faces_detectadas_hog_1 = detectorHog(imagem_cinza_1);
        int size_1 = faces_detectadas_hog_1.size();
        if (size_1 == 0) {
            cout << "Nenhuma Face Detectada na Imagem 1" << endl;
            return 1;
        }
        // Pega a primeira face detectada
        rectangle face_1 = faces_detectadas_hog_1[0];
        
        // Carrega a imagem 2
        array2d<rgb_pixel> imagem_2;
        load_image(imagem_2, caminho_imagem_2);
        // Converte a imagem 2 para gray
        array2d<unsigned char> imagem_cinza_2;
        assign_image(imagem_cinza_2, imagem_2);
        // Detecta as faces na imagem 2
        std::vector<rectangle> faces_detectadas_hog_2 = detectorHog(imagem_cinza_2);
        int size_2 = faces_detectadas_hog_2.size();
        if (size_2 == 0) {
            cout << "Nenhuma Face Detectada na Imagem 2" << endl;
            return 1;
        }
        // Pega a primeira face detectada
        rectangle face_2 = faces_detectadas_hog_2[0];
        
        // detectando os pontos faciais da imagem 1
        full_object_detection shape_1 = shapePredictor(imagem_1, face_1);
        
        // detectando os pontos faciais da imagem 2
        full_object_detection shape_2 = shapePredictor(imagem_2, face_2);
        
        // pego apena as faces recortadas das pessoas para fazer o treinamento
        std::vector<matrix<rgb_pixel>> faces;
        
        // recorto a face 1
        matrix<rgb_pixel> face_chip_1;
        extract_image_chip(imagem_1, get_face_chip_details(shape_1, 150, 0.25), face_chip_1);
        faces.push_back(move(face_chip_1));
        
        // recorto a face 2
        matrix<rgb_pixel> face_chip_2;
        extract_image_chip(imagem_2, get_face_chip_details(shape_2, 150, 0.25), face_chip_2);
        faces.push_back(move(face_chip_2));
        
        // Carrega o classificador
        anet_type net;
        deserialize("dlib_face_recognition_resnet_model_v1.dat") >> net;
        
        // Fazendo a predição
        auto tempo_inicio_predicao = std::chrono::high_resolution_clock::now();
        std::vector<matrix<float, 0, 1>> face_descriptors = net(faces);
        auto tempo_fim_predicao = std::chrono::high_resolution_clock::now();

        if (face_descriptors.size() == 2) {
            cout << "Distancia: " << length(face_descriptors[0] - face_descriptors[1]) << endl;
        }

        // Mostra o Tempo Total
        auto tempo_total_fim = std::chrono::high_resolution_clock::now();
        double tempo_total = std::chrono::duration<double, std::milli>(tempo_total_fim - tempo_total_inicio).count();
        cout << "Tempo Total: " << to_string(tempo_total) << endl;

        // Mostra o Tempo de Predição
        double tempo_predicao = std::chrono::duration<double, std::milli>(tempo_fim_predicao - tempo_inicio_predicao).count();
        cout << "Tempo Predicao: " << to_string(tempo_predicao) << endl;

        // Mostra a Imagem 1 em uma Janela
        image_window my_window_1(imagem_1, "Imagem 1");
        my_window_1.add_overlay(faces_detectadas_hog_1, rgb_pixel(0, 255, 0));
        my_window_1.add_overlay(render_face_detections(shape_1));
        // my_window_1.wait_until_closed();

        // Mostra a Imagem 2 em uma Janela
        image_window my_window_2(imagem_2, "Imagem 2");
        my_window_2.add_overlay(faces_detectadas_hog_2, rgb_pixel(0, 255, 0));
        my_window_2.add_overlay(render_face_detections(shape_2));
        my_window_2.wait_until_closed();

    } catch (exception& e) {
        cout << "\nexception thrown!" << endl;
        cout << e.what() << endl;
        return 1;
    }
}

Agora acesse o repositório de arquivos http://dlib.net/files/ e baixe os arquivos dlib_face_recognition_resnet_model_v1.dat.bz2 e shape_predictor_68_face_landmarks.dat.bz2. Extraia os arquivos dentro do diretório de build do projeto CalcularDistancia\build.

Crie uma pasta chamada pessoas dentro do diretório CalcularDistancia\build e adicione duas imagens de duas pessoas, renomeie a primeira imagem para 11-12.jpg e a segunda para 26-12.jpg.

Recomendo utilizar as imagens do FEI Face Database.

Após isso, mantenha o arquivo main.cpp selecionado no VS Code, então compile o projeto com as teclas Ctrl + Shift + B.

Entre na pasta do build e execute o programa usando o terminal:

C:\Users\joaops\Downloads\CalcularDistancia>cd build
C:\Users\joaops\Downloads\CalcularDistancia\build>main.exe
Distancia: 0.72887       
Tempo Total: 833.495300  
Tempo Predicao: 24.682900

Ou localize o programa pelo explorador de arquivos do Windows, então execute ele para ver o resultado.

Resultado do Programa Calcular a Distância.

Também é possível passar as imagem por parâmetro:

C:\Users\joaops\Downloads\CalcularDistancia\build>main.exe pessoas\2-12.jpg pessoas\7-12.jpg
Distancia: 0.71298
Tempo Total: 834.554300
Tempo Predicao: 23.432900

Agora que o programa já está funcionando, você já pode excluir a pasta do código fonte do Dlib e do CMake que estão no diretório Downloads, uma vez que você já tem os já tem os arquivos no seu projeto e você só precisa copiar eles para um outro projeto caso precise.

Configurando o IntelliSense

Volte no VS Code, precisamos terminar de configurar o projeto.

Com o VS Code aberto, pressione as Teclas Ctrl + Shift + P, então digite C/C++: Editar Configurações (IU) depois pressione Enter.

No campo Nome da configuração, você pode manter o mesmo nome ou alterar, por exemplo para Windows x64, é útil quando seu projeto possui outros ambientes configurados, por exemplo para Windows e Linux.

Ao alterar a configuração padrão, será criado o arquivo c_cpp_properties.json na pasta .vscode.

No campo Caminho do compilador, selecione o caminho do MinGW64 C:/msys64/mingw64/bin/g++.exe.

No campo Modo do IntelliSense, escolha a opção windows-gcc-x64.

E para finalizar, no campo Incluir caminho, adicione o caminha da pasta include do Dlib ${workspaceFolder}/deps/dlib/include/**.

Caso seu projeto tenha mais de uma configuração C++, você pode selecionar ela clicando na barra de status do VS Code.

Selecionando a Configuração do IntelliSence

Comparação de Desempenho

Eu compilei novamente a biblioteca Dlib, mas dessa vez sem o OpenBLAS, então executei o projeto usando as mesmas imagens e esse foi o resultado:

C:\Users\joaops\Downloads\CalcularDistancia>cd build
C:\Users\joaops\Downloads\CalcularDistancia\build>main.exe
Distancia: 0.72887
Tempo Total: 1020.049500  
Tempo Predicao: 137.686900

Antes o tempo para predição era de apenas 24 milissegundos e agora levou 137 milissegundos, quase 6 vezes mais lento do que o primeiro teste. É por causa disso que o OpenBLAS é tão importante ao compilar a biblioteca Dlib.

Executando o Projeto em Outros Computadores

Executar esse projeto no seu computador de desenvolvimento é uma coisa, você já tem o MinGW64 instalado e configurado nas variáveis de ambiente. Mas a história é outra ao tentar executar em um outro computador, caso você copie a pasta build para um outro computador e tente executar o arquivo main.exe, vai perceber que vai faltar algumas DLLs. Mais especificamente a libgcc_s_seh-1.dll, libstdc++-6.dll e libwinpthread-1.dll que estão dentro da pasta C:\msys64\mingw64\bin, copiar elas para dentro da pasta build fará que o seu programa funcione em outros computadores.

Mas o principal problema não é copiar as DLLs para a pasta build, mas sim saber quais são as DLLs certas que você precisa copiar para que seu projeto funcione.

E para descobrir isso, precisamos configurar o projeto para debug.

No VS Code, mantenha o arquivo main.cpp selecionado e aberto no editor, então clique no menu principal Executar, depois em Adicionar Configuração…, escolha C++ (GDB/LLDB), por fim escolha g++ - Criar e depurar o arquivo ativo.

O VS Code irá compilar e tentar executar o arquivo main.cpp, porém ele não vai encontrar o executável main.exe, pois ele foi criado dentro da pasta build. Será mostrado uma mensagem de alerta, informando desse problema, clique em Abrir 'launch.json', para que o VS Code crie esse arquivo dentro da pasta .vscode.

Abra o arquivo .vscode/launch.json e altere o valor da propriedade program para:

${fileDirname}/build/${fileBasenameNoExtension}.exe

E o valor da propriedade cwd para:

${workspaceFolder}/build

O seu arquivo .vscode/launch.json deve ter ficado parecido com este:

{
    // Use o IntelliSense para saber mais sobre os atributos possíveis.
    // Focalizar para exibir as descrições dos atributos existentes.
    // Para obter mais informações, acesse: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++.exe - Criar e depurar o arquivo ativo",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}/build/${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}/build",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:/msys64/mingw64/bin/gdb.exe",
            "setupCommands": [
                {
                    "description": "Habilitar a reformatação automática para gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "Definir Tipo de Desmontagem como Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: g++.exe Windows 10 x64"
        }
    ]
}

Após isso, mantenha o arquivo main.cpp aberto no editor e pressione a tecla F5 para iniciar o debug.

O VS Code irá compilar e executar o programa em modo debug e irá mostrar todas as DLLs que são carregadas no Console de Depuração.

Console de Depuração do VS Code

Incluindo as DLLs do MinGW64 necessárias para executar o programa em outros computadores.

Não é necessário adicionar as DLLs do Windows, pois elas já fazem parte do sistema.

Referências e Outros Links

Repositório do Projeto

Documentação do Visual Studio Code de Como Configurar GCC no Windows

https://www.msys2.org/

http://dlib.net/

Exemplo de um Algoritmo de Reconhecimento Facial

https://www.openblas.net/

Fei Face Database