Browse Source

initial commit

main
cailean 1 month ago
commit
7afc14d0eb
  1. 89
      .gitignore
  2. 260
      .vscode/c_cpp_properties.json
  3. 6
      .vscode/extensions.json
  4. 72
      .vscode/launch.json
  5. 92
      .vscode/tasks.json
  6. 143
      MacbethCV.code-workspace
  7. 13
      Makefile
  8. 0
      README.md
  9. 4
      addons.make
  10. 1
      bin/data/.gitkeep
  11. BIN
      bin/data/compressed-test-video.mp4
  12. BIN
      bin/data/fer.onnx
  13. BIN
      bin/data/test-video.mp4
  14. BIN
      bin/data/yolov5s-face.onnx
  15. 145
      config.make
  16. 17
      src/main.cpp
  17. 46
      src/ofApp.cpp
  18. 23
      src/ofApp.h
  19. 175
      src/ofYolo.cpp
  20. 130
      src/ofYolo.h
  21. 145
      src/onxProcess.cpp
  22. 44
      src/onxProcess.h

89
.gitignore

@ -0,0 +1,89 @@
#.gitignore is a file which makes git ignore files which should
# not go into version control in the first place
# Questions? See
# http://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#Ignoring-Files
# http://git-scm.com/docs/gitignore
###########################
# ignore generated binaries
# but not the data folder
###########################
/bin/*
!/bin/data/
#########
# general
#########
[Bb]uild/
[Oo]bj/
*.o
[Dd]ebug*/
[Rr]elease*/
*.mode*
*.app/
*.pyc
.svn/
*.log
########################
# IDE files which should
# be ignored
########################
# XCode
*.pbxuser
*.perspective
*.perspectivev3
*.mode1v3
*.mode2v3
# XCode 4
*.xccheckout
xcuserdata/
# Visual Studio
*.sdf
*.opensdf
*.suo
*.pdb
*.ilk
*.aps
ipch/
# Eclipse
.metadata
local.properties
.externalToolBuilders
# Android Studio
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
##################
# operating system
##################
# Linux
*~
# KDE
.directory
.AppleDouble
# OSX
.DS_Store
*.swp
*~.nib
# Thumbnails
._*
# Windows
# Image file caches
Thumbs.db
# Folder config file
Desktop.ini
# Android
.csettings

260
.vscode/c_cpp_properties.json

@ -0,0 +1,260 @@
{
"configurations": [
{
"browse": {
"databaseFilename": "${workspaceRoot}/.vscode/browse.db",
"limitSymbolsToIncludedHeaders": true,
"path": [
"/usr/local/include",
"/System/Library/Frameworks",
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/",
"${workspaceFolder}/src/**",
"${OF_INCLUDE}",
"${OF_LIBS_INCLUDE}",
"${PROJECT_ADDON_INCLUDES}",
"${PROJECT_EXTRA_INCLUDES}"
]
},
"cStandard": "c17",
"compilerPath": "/usr/bin/gcc",
"configurationProvider": "ms-vscode.makefile-tools",
"cppStandard": "c++17",
"includePath": [
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/",
"${OF_INCLUDE}",
"${OF_LIBS_INCLUDE}",
"${workspaceFolder}/src/**",
"${PROJECT_ADDON_INCLUDES}",
"${PROJECT_EXTRA_INCLUDES}"
],
"intelliSenseMode": "${default}",
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
],
"mergeConfigurations": true,
"name": "Mac"
},
{
"browse": {
"databaseFilename": "",
"limitSymbolsToIncludedHeaders": true,
"path": [
"/usr/local/include",
"/usr/include",
"${workspaceFolder}/src/**",
"${OF_INCLUDE}",
"${OF_LIBS_INCLUDE}",
"${PROJECT_ADDON_INCLUDES}",
"${PROJECT_EXTRA_INCLUDES}"
]
},
"cStandard": "c17",
"compilerPath": "/usr/bin/gcc",
"configurationProvider": "ms-vscode.makefile-tools",
"cppStandard": "c++17",
"includePath": [
"/usr/include",
"/usr/local/include",
"/usr/include/c++/*",
"/usr/lib/gcc/x86_64-linux-gnu/*",
"/usr/lib/x86_64-linux-gnu/glib-2.0/include",
"/usr/lib/x86_64-linux-gnu/gstreamer-1.0/include",
"/usr/local/include",
"/usr/include/x86_64-linux-gnu",
"${OF_INCLUDE}",
"${OF_LIBS_INCLUDE}",
"${workspaceRoot}/../../../libs/kiss/include",
"/usr/include/x86_64-linux-gnu/c++/*",
"/usr/include/pulse",
"/usr/include/cairo",
"/usr/include/gstreamer-1.0",
"/usr/include/glib-2.0",
"${workspaceRoot}",
"${workspaceFolder}/src/**",
"${PROJECT_ADDON_INCLUDES}",
"${PROJECT_EXTRA_INCLUDES}"
],
"intelliSenseMode": "${default}",
"mergeConfigurations": true,
"name": "Linux"
},
{
"browse": {
"databaseFilename": "",
"limitSymbolsToIncludedHeaders": true,
"path": [
"${workspaceFolder}/src/**",
"${OF_INCLUDE}",
"${OF_LIBS_INCLUDE}",
"${PROJECT_ADDON_INCLUDES}",
"${PROJECT_EXTRA_INCLUDES}"
]
},
"cStandard": "c17",
"compilerPath": "C:/msys64/mingw64/bin/g++.exe",
"configurationProvider": "ms-vscode.makefile-tools",
"cppStandard": "c++17",
"includePath": [
"C:/msys64/mingw64/include/c++/**",
"C:/msys64/mingw64/i686-w64-mingw64/include",
"${OF_INCLUDE}",
"${OF_LIBS_INCLUDE}",
"${workspaceFolder}/src/**",
"${PROJECT_ADDON_INCLUDES}",
"${PROJECT_EXTRA_INCLUDES}"
],
"intelliSenseMode": "clang-x64",
"mergeConfigurations": true,
"name": "Win32"
}
],
"env": {
"OF_INCLUDE": [
"${OF_LIBS_ROOT}/openFrameworks/**"
],
"OF_LIBS_INCLUDE": [
"${OF_LIBS_ROOT}/cairo/include/cairo",
"${OF_LIBS_ROOT}/curl/include",
"${OF_LIBS_ROOT}/fmod/include",
"${OF_LIBS_ROOT}/FreeImage/include",
"${OF_LIBS_ROOT}/freetype/include",
"${OF_LIBS_ROOT}/glew/include",
"${OF_LIBS_ROOT}/glfw/include",
"${OF_LIBS_ROOT}/glm/include",
"${OF_LIBS_ROOT}/json/include",
"${OF_LIBS_ROOT}/pugixml/include",
"${OF_LIBS_ROOT}/rtAudio/include",
"${OF_LIBS_ROOT}/tess2/include",
"${OF_LIBS_ROOT}/uriparser/include",
"${OF_LIBS_ROOT}/utf8/include"
],
"OF_LIBS_ROOT": "${OF_ROOT}/libs",
"OF_ROOT": "${workspaceFolder}/../../..",
"PROJECT_ADDON_INCLUDES": [],
"PROJECT_EXTRA_INCLUDES": [
"${workspaceRoot}/..\\..\\..\\addons\\ofxGui\\src",
"${workspaceRoot}/..\\..\\..\\addons\\ofxNetwork\\src",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\src",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOnnxRuntime\\libs\\onnxruntime\\include",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOnnxRuntime\\src",
"${workspaceRoot}/src",
"${workspaceRoot}/..\\..\\..\\addons\\ofxGui\\src",
"${workspaceRoot}/..\\..\\..\\addons\\ofxNetwork\\src",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\etc",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\aruco",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\bioinspired",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\calib3d",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\cuda",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\cuda\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\hal",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\opencl",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\opencl\\runtime",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\opencl\\runtime\\autogenerated",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\parallel",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\parallel\\backend",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\core\\utils",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\dnn",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\dnn\\utils",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\features2d",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\features2d\\hal",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\flann",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\fuzzy",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\img_hash",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\imgcodecs",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\imgcodecs\\legacy",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\imgproc",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\imgproc\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\imgproc\\hal",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\line_descriptor",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\mcc",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\objdetect",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\optflow",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\phase_unwrapping",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\reg",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\saliency",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\signal",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\stereo",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\structured_light",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\surface_matching",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\tracking",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\video",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\video\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\video\\legacy",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\xfeatures2d",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\include\\opencv4\\opencv2\\ximgproc",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\calib3d",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\cuda",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\cuda\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\hal",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\llapi",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\opencl",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\opencl\\runtime",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\opencl\\runtime\\autogenerated",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\openvx",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\parallel",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\parallel\\backend",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\private",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\core\\utils",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\dnn",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\dnn\\utils",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\features2d",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\features2d\\hal",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\flann",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\cpu",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\fluid",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\gpu",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\infer",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\oak",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\ocl",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\own",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\plaidml",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\python",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\render",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\s11n",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\streaming",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\streaming\\gstreamer",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\streaming\\onevpl",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\gapi\\util",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\highgui",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\imgcodecs",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\imgcodecs\\legacy",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\imgproc",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\imgproc\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\imgproc\\hal",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\ml",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\objdetect",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\photo",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\photo\\legacy",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\stitching",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\stitching\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\ts",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\video",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\video\\detail",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\video\\legacy",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\videoio",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\videoio\\doc",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\include\\opencv2\\videoio\\legacy",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\lib",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\libs\\opencv\\license",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOpenCv\\src",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOnnxRuntime\\libs\\onnxruntime\\include",
"${workspaceRoot}/..\\..\\..\\addons\\ofxOnnxRuntime\\src"
]
},
"version": 4
}

6
.vscode/extensions.json

@ -0,0 +1,6 @@
{
"recommendations": [
"ms-vscode.makefile-tools",
"ms-vscode.cpptools"
]
}

72
.vscode/launch.json

@ -0,0 +1,72 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "C++ Launch",
"type": "cppdbg",
"request": "launch",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}",
"environment": [],
"externalConsole": false,
"linux": {
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"program": "${workspaceRoot}/bin/${workspaceFolderBasename}_debug"
},
"osx": {
"MIMode": "lldb",
"program": "${workspaceRoot}/bin/${workspaceFolderBasename}_debug.app/Contents/MacOS/${workspaceFolderBasename}_debug"
},
"windows": {
"MIMode": "gdb",
"miDebuggerPath": "gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"program": "${workspaceRoot}/bin/${workspaceFolderBasename}_debug"
}
},
{
"name": "C++ Attach",
"type": "cppdbg",
"request": "attach",
"program": "enter program name, for example ${workspaceRoot}/a.out",
"processId": "${command:pickProcess}",
"linux": {
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
"osx": {
"MIMode": "lldb"
},
"windows": {
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
}
]
}

92
.vscode/tasks.json

@ -0,0 +1,92 @@
{
"version": "2.0.0",
"shell":{
"task": true
},
"windows" : {
"options": {
"shell": {
"executable": "C:\\msys64\\msys2_shell.cmd",
"args": [
"-defterm",
"-mingw64",
"-no-start",
"-here",
"-shell bash -c"
]
}
}
},
"problemMatcher": {
"owner": "cpp",
"fileLocation": ["relative", "${workspaceFolder}"],
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
},
"group": {
"kind": "build",
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"tasks": [
{
"type": "shell",
"label": "Build RELEASE",
"command": "make -j -s 2>&1"
// "windows" : {
// "command" : "msbuild"
// }
},
{
"type": "shell",
"label": "Run RELEASE",
"command": "make RunRelease >&1",
"windows" : {
"command" : "bin/*.exe"
}
},
{
"label": "Build and Run Release",
"dependsOn": ["Build RELEASE", "Run RELEASE"],
"dependsOrder": "sequence",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "shell",
"label": "Build DEBUG",
"command": "make Debug -j -s 2>&1 || exit 1"
},
{
"type": "shell",
"label": "Clean DEBUG",
"command": "make CleanDebug"
},
{
"type": "shell",
"label": "Clean RELEASE",
"command": "make CleanRelease"
},
{
"type": "shell",
"label": "Clean ALL",
"command": "make clean"
}
]
}

143
MacbethCV.code-workspace

@ -0,0 +1,143 @@
{
"folders": [
{
"path": "."
},
{
"path": "${workspaceRoot}/../../../../libs/openFrameworks"
},
{
"path": "${workspaceRoot}/../..\\..\\..\\addons\\ofxGui"
},
{
"path": "${workspaceRoot}/../..\\..\\..\\addons\\ofxNetwork"
},
{
"path": "${workspaceRoot}/../..\\..\\..\\addons\\ofxOpenCv"
},
{
"path": "${workspaceRoot}/../..\\..\\..\\addons\\ofxOnnxRuntime"
},
{
"path": "${workspaceRoot}/../..\\..\\..\\addons\\ofxGui"
},
{
"path": "${workspaceRoot}/../..\\..\\..\\addons\\ofxNetwork"
},
{
"path": "${workspaceRoot}/../..\\..\\..\\addons\\ofxOpenCv"
},
{
"path": "${workspaceRoot}/../..\\..\\..\\addons\\ofxOnnxRuntime"
}
],
"openFrameworksProjectGeneratorVersion": "0.103.0",
"settings": {
"files.associations": {
"algorithm": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"cfenv": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"cinttypes": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"coroutine": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"format": "cpp",
"forward_list": "cpp",
"fstream": "cpp",
"functional": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"map": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"numeric": "cpp",
"optional": "cpp",
"ostream": "cpp",
"queue": "cpp",
"random": "cpp",
"ranges": "cpp",
"ratio": "cpp",
"regex": "cpp",
"semaphore": "cpp",
"set": "cpp",
"shared_mutex": "cpp",
"source_location": "cpp",
"span": "cpp",
"sstream": "cpp",
"stack": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"string": "cpp",
"strstream": "cpp",
"system_error": "cpp",
"thread": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"utility": "cpp",
"valarray": "cpp",
"variant": "cpp",
"vector": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstddef": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"string_view": "cpp",
"stdfloat": "cpp",
"text_encoding": "cpp"
}
}
}

13
Makefile

@ -0,0 +1,13 @@
# Attempt to load a config.make file.
# If none is found, project defaults in config.project.make will be used.
ifneq ($(wildcard config.make),)
include config.make
endif
# make sure the the OF_ROOT location is defined
ifndef OF_ROOT
OF_ROOT=../../..
endif
# call the project makefile!
include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk

0
README.md

4
addons.make

@ -0,0 +1,4 @@
ofxGui
ofxNetwork
ofxOpenCv
ofxOnnxRuntime

1
bin/data/.gitkeep

@ -0,0 +1 @@

BIN
bin/data/compressed-test-video.mp4

Binary file not shown.

BIN
bin/data/fer.onnx

Binary file not shown.

BIN
bin/data/test-video.mp4

Binary file not shown.

BIN
bin/data/yolov5s-face.onnx

Binary file not shown.

145
config.make

@ -0,0 +1,145 @@
################################################################################
# CONFIGURE PROJECT MAKEFILE (optional)
# This file is where we make project specific configurations.
################################################################################
################################################################################
# OF ROOT
# The location of your root openFrameworks installation
# (default) OF_ROOT = ../../..
################################################################################
OF_ROOT = ../../..
################################################################################
# PROJECT ROOT
# The location of the project - a starting place for searching for files
# (default) PROJECT_ROOT = . (this directory)
#
################################################################################
# PROJECT_ROOT = .
################################################################################
# PROJECT SPECIFIC CHECKS
# This is a project defined section to create internal makefile flags to
# conditionally enable or disable the addition of various features within
# this makefile. For instance, if you want to make changes based on whether
# GTK is installed, one might test that here and create a variable to check.
################################################################################
# None
################################################################################
# PROJECT EXTERNAL SOURCE PATHS
# These are fully qualified paths that are not within the PROJECT_ROOT folder.
# Like source folders in the PROJECT_ROOT, these paths are subject to
# exlclusion via the PROJECT_EXLCUSIONS list.
#
# (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank)
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_EXTERNAL_SOURCE_PATHS =
################################################################################
# PROJECT EXCLUSIONS
# These makefiles assume that all folders in your current project directory
# and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations
# to look for source code. The any folders or files that match any of the
# items in the PROJECT_EXCLUSIONS list below will be ignored.
#
# Each item in the PROJECT_EXCLUSIONS list will be treated as a complete
# string unless teh user adds a wildcard (%) operator to match subdirectories.
# GNU make only allows one wildcard for matching. The second wildcard (%) is
# treated literally.
#
# (default) PROJECT_EXCLUSIONS = (blank)
#
# Will automatically exclude the following:
#
# $(PROJECT_ROOT)/bin%
# $(PROJECT_ROOT)/obj%
# $(PROJECT_ROOT)/%.xcodeproj
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_EXCLUSIONS =
################################################################################
# PROJECT LINKER FLAGS
# These flags will be sent to the linker when compiling the executable.
#
# (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# Currently, shared libraries that are needed are copied to the
# $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to
# add a runtime path to search for those shared libraries, since they aren't
# incorporated directly into the final executable application binary.
# TODO: should this be a default setting?
# PROJECT_LDFLAGS=-Wl,-rpath=./libs
################################################################################
# PROJECT DEFINES
# Create a space-delimited list of DEFINES. The list will be converted into
# CFLAGS with the "-D" flag later in the makefile.
#
# (default) PROJECT_DEFINES = (blank)
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_DEFINES =
################################################################################
# PROJECT CFLAGS
# This is a list of fully qualified CFLAGS required when compiling for this
# project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS
# defined in your platform specific core configuration files. These flags are
# presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below.
#
# (default) PROJECT_CFLAGS = (blank)
#
# Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in
# your platform specific configuration file will be applied by default and
# further flags here may not be needed.
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_CFLAGS =
################################################################################
# PROJECT OPTIMIZATION CFLAGS
# These are lists of CFLAGS that are target-specific. While any flags could
# be conditionally added, they are usually limited to optimization flags.
# These flags are added BEFORE the PROJECT_CFLAGS.
#
# PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets.
#
# (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank)
#
# PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets.
#
# (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank)
#
# Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the
# PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration
# file will be applied by default and further optimization flags here may not
# be needed.
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_OPTIMIZATION_CFLAGS_RELEASE =
# PROJECT_OPTIMIZATION_CFLAGS_DEBUG =
################################################################################
# PROJECT COMPILERS
# Custom compilers can be set for CC and CXX
# (default) PROJECT_CXX = (blank)
# (default) PROJECT_CC = (blank)
# Note: Leave a leading space when adding list items with the += operator
################################################################################
# PROJECT_CXX =
# PROJECT_CC =
# vscode template

17
src/main.cpp

@ -0,0 +1,17 @@
#include "ofMain.h"
#include "ofApp.h"
//========================================================================
int main( ){
//Use ofGLFWWindowSettings for more options like multi-monitor fullscreen
ofGLWindowSettings settings;
settings.setSize(1920, 1080);
settings.windowMode = OF_WINDOW; //can also be OF_FULLSCREEN
auto window = ofCreateWindow(settings);
ofRunApp(window, std::make_shared<ofApp>());
ofRunMainLoop();
}

46
src/ofApp.cpp

@ -0,0 +1,46 @@
#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
ofSetFrameRate(60);
videoPlayer.load(videoPath);
videoPlayer.setLoopState(OF_LOOP_NORMAL);
videoPlayer.play();
inputImage.allocate(640, 640, OF_IMAGE_COLOR); // Allocate image, so we don't get any issues when processing on the thread
videoFrame.allocate(1920, 1080, OF_IMAGE_COLOR);
onnx.setup(&inputImage); // setup onnx -> will need to pass in a pointer to the two fbos?
}
//--------------------------------------------------------------
void ofApp::update(){
videoPlayer.update();
if(videoPlayer.isFrameNew()) {
ofPixels & p = videoPlayer.getPixels();
videoFrame.setFromPixels(p);
}
onnx.update(videoFrame);
}
//--------------------------------------------------------------
void ofApp::draw(){
//videoPlayer.draw(0, 0, 1920, 1080);
onnx.draw();
}
//--------------------------------------------------------------
void ofApp::exit(){
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key){
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key){
}

23
src/ofApp.h

@ -0,0 +1,23 @@
#pragma once
#include "ofMain.h"
#include "onxProcess.h"
class ofApp : public ofBaseApp{
public:
void setup() override;
void update() override;
void draw() override;
void exit() override;
void keyPressed(int key) override;
void keyReleased(int key) override;
ofVideoPlayer videoPlayer;
std::string videoPath = "compressed-test-video.mp4";
onxProcess onnx;
ofImage inputImage;
ofImage videoFrame;
};

175
src/ofYolo.cpp

@ -0,0 +1,175 @@
#include "ofYolo.h"
// Takes output tensor data, processes that data, and returns an array of BoxfWithLandmarks (detected_faces)
void ofYolo::ParseOutput(float* &output_tensors, std::vector<BoxfWithLandmarks> &sorted_faces, unsigned int num_anchors) {
std::vector<BoxfWithLandmarks> detected_faces;
for (unsigned int i = 0; i < num_anchors; ++i) {
const float *row_ptr = output_tensors + i * 16; // Each row contains 16 values
float obj_conf = row_ptr[4]; // Objectness confidence
if (obj_conf < 0.5) continue; // Filter out low-confidence detections
// Extract bounding box, confidence, and landmarks
float cx = row_ptr[0];
float cy = row_ptr[1];
float w = row_ptr[2];
float h = row_ptr[3];
float cls_conf = row_ptr[15]; // Face confidence score
if (cls_conf < 0.5) continue; // Filter by class confidence
BoxfWithLandmarks face;
face.box.x1 = cx - w / 2;
face.box.y1 = cy - h / 2;
face.box.x2 = cx + w / 2;
face.box.y2 = cy + h / 2;
face.box.score = cls_conf;
face.box.label_text = "face";
// Extract landmarks
for (int j = 0; j < 10; j += 2) {
face.landmarks.points.push_back(cv::Point2f(row_ptr[5 + j], row_ptr[5 + j + 1]));
}
detected_faces.push_back(face); // Store the detected face with landmarks
}
// Apply NMS to detected faces list to remove any overlapping bounding boxes.
NonMaximumSuppression(detected_faces, sorted_faces, 0.5);
// Sort faces based on confidence value
SortDetectedFaces(sorted_faces);
}
// Simple helper for drawing boxes given x1, y1, x2, y2 coordinates.
void ofYolo::DrawBox(std::vector<BoxfWithLandmarks> &detected_faces){
for (const auto &face : detected_faces) {
ofPushStyle();
ofNoFill();
ofSetColor(ofColor::cyan);
ofDrawRectangle(face.box.x1, face.box.y1, ((face.box.x2) - (face.box.x1)), face.box.y2 - face.box.y1);
ofPopStyle();
}
}
// Simple helper to draw boxes at the center of the detected face.
void ofYolo::DrawCenter(std::vector<BoxfWithLandmarks> &detected_faces){
ofNoFill();
glm::vec2 position = detected_faces[0].box.center;
ofDrawCircle(position.x + ofGetWindowWidth() / 2, position.y, 5);
}
// Applies NMS to an array of BoxfWithLandmarks.face.boxes, to remove any overlapping bounding boxes.
void ofYolo::NonMaximumSuppression(std::vector<BoxfWithLandmarks> &input_faces, std::vector<BoxfWithLandmarks> &output_faces, float iou_threshold)
{
// Sort the boxes by their confidence scores (highest to lowest)
std::sort(input_faces.begin(), input_faces.end(),
[](const BoxfWithLandmarks &a, const BoxfWithLandmarks &b) {
return a.box.score > b.box.score;
});
std::vector<int> suppressed(input_faces.size(), 0); // Suppression mask
// Iterate through the boxes
for (size_t i = 0; i < input_faces.size(); ++i) {
if (suppressed[i]) continue; // Skip already suppressed boxes
// Add this box to the output
output_faces.push_back(input_faces[i]);
for (size_t j = i + 1; j < input_faces.size(); ++j) {
if (suppressed[j]) continue;
// Calculate IoU between box i and box j
float iou = input_faces[i].box.iou_of(input_faces[j].box);
// Suppress box j if IoU is greater than the threshold
if (iou > iou_threshold) {
suppressed[j] = 1;
}
}
}
}
// Scales the coordinates of detected faces from the model output dimensions -> the original input image dimensions.
void ofYolo::ConvertBoxCoordsToOriginalSize(std::vector<BoxfWithLandmarks> &detected_faces, size_t original_width, size_t original_height){
float width_scale = static_cast<float>(original_width) / modelSize;
float height_scale = static_cast<float>(original_height) / modelSize;
for (auto &face : detected_faces) {
// Convert bounding box coordinates
face.box.x1 *= width_scale;
face.box.y1 *= height_scale;
face.box.x2 *= width_scale;
face.box.y2 *= height_scale;
face.box.UpdateCenter();
// Expansion factor
float expansion_factor = 1.0f;
// Find current dimensions
float current_width = face.box.x2 - face.box.x1;
float current_height = face.box.y2 - face.box.y1;
// Use width as the base for the 1:1.5 ratio
float base_width = max(current_width, current_height);
float new_width = base_width;
float new_height = base_width * 1.5f; // Make height 1.5 times the width
// Apply expansion
new_width *= expansion_factor;
new_height *= expansion_factor;
// Recalculate coordinates maintaining the center
face.box.x1 = face.box.center.x - (new_width / 2.0f);
face.box.x2 = face.box.center.x + (new_width / 2.0f);
face.box.y1 = face.box.center.y - (new_height / 2.0f);
face.box.y2 = face.box.center.y + (new_height / 2.0f);
}
SortDetectedFaces(detected_faces);
}
void ofYolo::CropFaceToImage(ofImage &inputImage, BoxfWithLandmarks &face, ofImage &colorImage, int imageSize){
//colorImage.resetROI();
// Calculate the coordinates and dimensions of the face box
float x1 = face.box.x1;
float y1 = face.box.y1;
float x2 = face.box.x2;
float y2 = face.box.y2;
// Ensure coordinates are within the input image bounds
x1 = ofClamp(x1, 0.0f, (float)inputImage.getWidth());
y1 = ofClamp(y1, 0.0f, (float)inputImage.getHeight());
x2 = ofClamp(x2, 0.0f, (float)inputImage.getWidth());
y2 = ofClamp(y2, 0.0f, (float)inputImage.getHeight());
// Calculate width and height of the cropped area
float cropWidth = x2 - x1;
float cropHeight = y2 - y1;
// Create cropped section, defined by the box coords
ofFbo tempFbo;
tempFbo.allocate(cropWidth, cropHeight, GL_RGB);
tempFbo.begin();
ofClear(0);
inputImage.getTexture().drawSubsection(0, 0, cropWidth, cropHeight, x1, y1);
tempFbo.end();
ofPixels pix;
tempFbo.readToPixels(pix);
face.img.setFromPixels(pix);
face.img.resize(imageSize, imageSize);
}
void ofYolo::SortDetectedFaces(std::vector<BoxfWithLandmarks> &detectedFaces){
std::sort(detectedFaces.begin(), detectedFaces.end(),
[](const BoxfWithLandmarks &a, const BoxfWithLandmarks &b) {
return a.box.center.x > b.box.center.x; // Sort in descending order
});
}

130
src/ofYolo.h

@ -0,0 +1,130 @@
#ifndef YOLO
#define YOLO
#include "ofMain.h"
#include "ofxOpenCv.h"
#include "ofxOnnxRuntime.h"
#include <algorithm>
/*
Struct for storing information about detetced faces.
*/
struct Emotion {
float anger;
float disgust;
float fear;
float happiness;
float neutral;
float sadness;
float surprise;
void applySoftmax() {
float values[7] = {anger, disgust, fear, happiness, neutral, sadness, surprise};
// Find max value for numerical stability
float maxVal = values[0];
for(int i = 1; i < 7; i++) {
maxVal = std::max(maxVal, values[i]);
}
// Calculate exp(x - max) and sum
float sum = 0.0f;
for(int i = 0; i < 7; i++) {
values[i] = std::exp(values[i] - maxVal);
sum += values[i];
}
// Normalize
anger = values[0] / sum;
disgust = values[1] / sum;
fear = values[2] / sum;
happiness = values[3] / sum;
neutral = values[4] / sum;
sadness = values[5] / sum;
surprise = values[6] / sum;
}
std::string getDominantEmotion() const {
float values[7] = {anger, disgust, fear, happiness, neutral, sadness, surprise};
const char* names[7] = {"anger", "disgust", "fear", "happiness", "neutral", "sadness", "surprise"};
int maxIndex = 0;
float maxValue = values[0];
for(int i = 1; i < 7; i++) {
if(values[i] > maxValue) {
maxValue = values[i];
maxIndex = i;
}
}
return std::string(names[maxIndex]);
}
};
struct Boxf {
float x1, y1, x2, y2; // Coordinates of the bounding box
float score; // Confidence score
glm::vec2 center;
int label; // Class label (e.g., "face")
std::string label_text;
// Calculate Intersection over Union (IoU) with another box
float iou_of(const Boxf &other) const {
float intersection_x1 = std::max(x1, other.x1);
float intersection_y1 = std::max(y1, other.y1);
float intersection_x2 = std::min(x2, other.x2);
float intersection_y2 = std::min(y2, other.y2);
float intersection_area = std::max(0.0f, intersection_x2 - intersection_x1) *
std::max(0.0f, intersection_y2 - intersection_y1);
float this_area = (x2 - x1) * (y2 - y1);
float other_area = (other.x2 - other.x1) * (other.y2 - other.y1);
float union_area = this_area + other_area - intersection_area;
return intersection_area / union_area;
}
void UpdateCenter(){
center.x = (x1 + x2) / 2;
center.y = (y1 + y2) / 2;
}
};
struct Landmarks {
std::vector<cv::Point2f> points; // Facial landmarks points (e.g., eyes, nose, mouth)
bool flag = false; // Indicator if landmarks are available
};
struct BoxfWithLandmarks {
Boxf box; // Bounding box for the face
Landmarks landmarks; // Landmark points for the face
bool flag = false; // Indicator if this detection is valid
ofImage img;
Emotion emotion;
};
class ofYolo{
public:
ofYolo(){};
void ParseOutput(float* &out_ptr, std::vector<BoxfWithLandmarks> &sorted_faces, unsigned int num_anchors);
void DrawBox(std::vector<BoxfWithLandmarks> &detected_faces);
void DrawCenter(std::vector<BoxfWithLandmarks> &detected_faces);
void NonMaximumSuppression(std::vector<BoxfWithLandmarks> &input_faces, std::vector<BoxfWithLandmarks> &output_faces, float iou_threshold);
void ConvertBoxCoordsToOriginalSize(std::vector<BoxfWithLandmarks> &detected_faces, size_t original_width, size_t original_height);
void CropFaceToImage(ofImage &inputImage, BoxfWithLandmarks &face, ofImage &colorImage, int imageSize);
void SortDetectedFaces(std::vector<BoxfWithLandmarks> &detectedFaces);
private:
// Input dimenions of the model -- used for coordinate scaling.
size_t modelSize = 640;
};
#endif

145
src/onxProcess.cpp

@ -0,0 +1,145 @@
#include "onxProcess.h"
void onxProcess::setup(ofImage* img) {
// Setup code here
this->inputImage = img;
modelInput.emplace_back(inputImage);
// Need to allocate ofImage objects & point to them
for(size_t i = 0; i < batchSizeFer; i++) {
ofImage t;
t.allocate(modelInputDimensionsFer, modelInputDimensionsFer, OF_IMAGE_COLOR);
inputImagesFer.push_back(t);
}
for(auto & i : inputImagesFer) {
modelInputFer.emplace_back(&i);
}
std::cout << "ONNX Runtime version: " << ORT_API_VERSION << std::endl;
onxFaceDetection.setup(modelPath, ofxOnnxRuntime::BaseSetting{ ofxOnnxRuntime::INFER_CUDA, 0, ofxOnnxRuntime::FLOAT32, ofxOnnxRuntime::FLOAT32, modelInputWidth, modelInputHeight, true}, 1, false, false);
onxFaceDetection.setInputs(modelInput);
onxFER.setup(modelPathFer, ofxOnnxRuntime::BaseSetting{ ofxOnnxRuntime::INFER_CUDA, 0, ofxOnnxRuntime::FLOAT32, ofxOnnxRuntime::FLOAT32, modelInputDimensionsFer, modelInputDimensionsFer, true}, batchSizeFer, false, false);
onxFER.setInputs(modelInputFer);
fdThread.setup(&onxFaceDetection);
fdThread.start();
}
void onxProcess::update(ofImage& frame) {
// Update frame (the current video frame)
videoFrame = frame;
// Getthe number of anchors and output tensor -> processes that with some helper functions given an array to fill wil detected faces
if(fdThread.checkInferenceComplete()) {
// Update input image when thread is not busy
ofPixels & p = videoFrame.getPixels();
inputImage[0].setFromPixels(p);
auto output = fdThread.getResult();
auto outputShape = output->front().GetTensorTypeAndShapeInfo().GetShape();
unsigned int numAnchors = outputShape[1];
float* tensor = output->front().GetTensorMutableData<float>();
detectedFaces.clear();
yolo.ParseOutput(tensor, detectedFaces, numAnchors);
yolo.ConvertBoxCoordsToOriginalSize(detectedFaces, 1920, 1080);
fdThread.resetInferenceFlag();
fdThread.shouldRunInference = true;
}
cropFaces();
updateEmotions();
try{
fdThread.update();
} catch (_exception e) {
ofLogError() << "Model Thread did not run ) :";
}
}
void onxProcess::cropFaces() {
inputImagesFerTemp.clear();
// Populate a list of images with cropped faces. Set for model input!
// Makes sure I do not exceed batchsize, even if more faces are detected
ofImage temp;
for(size_t i = 0; i < detectedFaces.size() && i < inputImagesFer.size(); i++) {
// Adds the cropped image to the boxf object
yolo.CropFaceToImage(videoFrame, detectedFaces[i], temp, modelInputDimensionsFer);
inputImagesFer[i].setFromPixels(detectedFaces[i].img.getPixels());
}
}
void onxProcess::updateEmotions() {
//Run model!
auto out = onxFER.run();
float* tensor = out->front().GetTensorMutableData<float>();
// Makes sure I do not exceed batchsize, even if more faces are detected
for(size_t i = 0; i < detectedFaces.size() && i < inputImagesFer.size(); i++) {
Emotion emotion;
emotion.anger = tensor[i * 7];
emotion.disgust = tensor[i * 7 + 1];
emotion.fear = tensor[i * 7 + 2];
emotion.happiness = tensor[i * 7 + 3];
emotion.neutral = tensor[i * 7 + 4];
emotion.sadness = tensor[i * 7 + 5];
emotion.surprise = tensor[i * 7 + 6];
// Normalises values between 0-1
emotion.applySoftmax();
detectedFaces[i].emotion = emotion;
}
}
void onxProcess::draw() {
// Drawing code here
//videoFrame.draw(0, 0);
//yolo.DrawBox(detectedFaces);
int faceSize = modelInputDimensionsFer;
int facesPerRow = ofGetWindowWidth() / faceSize;
for (size_t i = 0; i < modelInputFer.size(); i++) {
int col = i % facesPerRow;
int row = i / facesPerRow;
int x = col * faceSize;
int y = 640 + (row * faceSize);
modelInputFer[i]->draw(x, y);
}
}
void onxProcess::drawGrid() {
ofImage temp;
int faceSize = 384;
int facesPerRow = ofGetWindowWidth() / faceSize;
int totalRows = (detectedFaces.size() + facesPerRow - 1) / facesPerRow;
for (int row = 0; row < totalRows; ++row) {
// Calculate number of faces in this row
int startIdx = row * facesPerRow;
int endIdx = std::min(startIdx + facesPerRow, (int)detectedFaces.size());
int facesInThisRow = endIdx - startIdx;
// Calculate horizontal offset to center faces in this row
int rowWidth = facesInThisRow * faceSize;
int xOffset = (ofGetWindowWidth() - rowWidth) / 2;
for (int i = 0; i < facesInThisRow; ++i) {
int idx = startIdx + i;
yolo.CropFaceToImage(videoFrame, detectedFaces[idx], temp, faceSize);
int x = xOffset + i * faceSize;
int y = row * faceSize;
temp.draw(x, y);
}
}
}

44
src/onxProcess.h

@ -0,0 +1,44 @@
#pragma once
#include "ofMain.h"
#include "ofxOnnxRuntime.h"
#include "ofxOnnxRuntimeThread.h"
#include "ofYolo.h"
class onxProcess {
public:
void setup(ofImage* img);
void update(ofImage& frame);
void cropFaces();
void updateEmotions();
void draw();
void drawGrid();
ofxOnnxRuntime::BaseHandler onxFaceDetection;
ofxOnnxRuntime::OnnxThread fdThread;
ofxOnnxRuntime::BaseHandler onxFER;
ofxOnnxRuntime::OnnxThread ferThread;
ofYolo yolo;
std::vector<ofImage*> modelInput;
std::vector<ofImage*> modelInputFer;
ofImage* inputImage;
std::vector<ofImage> inputImagesFer;
std::vector<ofImage> inputImagesFerTemp;
int modelInputWidth = 640;
int modelInputHeight = 640;
int modelInputDimensionsFer = 260;
int batchSizeFer = 2;
std::string modelPath = "yolov5s-face.onnx";
std::string modelPathFer = "fer.onnx";
std::vector<BoxfWithLandmarks> detectedFaces;
ofImage videoFrame;
};
Loading…
Cancel
Save