diff --git a/.gitignore b/.gitignore
index 2244ce63..e5f6867c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,32 @@
-# Build files
-/CMakeCache.txt
-/CMakeFiles/
-/Makefile
-/cmake_install.cmake
-/yolo_mark
\ No newline at end of file
+*.o
+*.a
+*.dSYM
+*.csv
+*.out
+*.png
+*.so
+*.exe
+*.dll
+*.lib
+build_*/
+*.weights
+
+# OS Generated #
+.DS_Store*
+ehthumbs.db
+Icon?
+Thumbs.db
+*.swp
+
+# IDE generated #
+.vs/
+.vscode/
+
+#Build artifacts
+yolo_mark
+
+#Examples
+data/*
+data
+examples/
+
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..7b70f353
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,70 @@
+language: cpp
+cache:
+ timeout: 1000
+ directories:
+ - $HOME/vcpkg
+
+matrix:
+ include:
+
+ - os: osx
+ compiler: clang
+ name: macOS - native clang - opencv@3
+ env:
+ - OpenCV_DIR="/usr/local/opt/opencv@3/"
+ - additional_defines="-DOpenCV_DIR=${OpenCV_DIR}"
+ - MATRIX_EVAL="brew install opencv@3"
+
+ - os: osx
+ compiler: clang
+ name: macOS - native clang - opencv(latest)
+ env:
+ - additional_defines=""
+ - MATRIX_EVAL="brew install opencv"
+
+ - os: osx
+ name: macOS - vcpkg
+ osx_image: xcode10.1
+ env:
+ - additional_defines=""
+ - MATRIX_EVAL="brew install gcc && unset CC && unset CXX"
+ - USE_VCPKG=true
+ - VCPKG_DEFINES="-DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake"
+
+ - os: linux
+ dist: bionic
+ compiler: gcc
+ name: ubuntu 18.04 - gcc - vcpkg
+ env:
+ - additional_defines=""
+ - USE_VCPKG=true
+ - VCPKG_DEFINES="-DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake"
+ - MATRIX_EVAL=""
+
+before_install:
+ - travis_retry eval "${MATRIX_EVAL}"
+
+install:
+ # CMake upgrade on Linux
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]] ; then wget --no-check-certificate https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-Linux-x86_64.tar.gz ; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]] ; then tar -xzf cmake-3.13.4-Linux-x86_64.tar.gz ; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]] ; then export PATH=$PWD/cmake-3.13.4-Linux-x86_64/bin:$PATH ; fi
+ - pushd $HOME
+ - if [ -d "$HOME/vcpkg/.git" ] ; then echo vcpkg cached ; else rm -rf vcpkg ; git clone https://github.com/Microsoft/vcpkg ; fi
+ - cd vcpkg
+ - git pull
+ - if [ "${USE_VCPKG}" = true ] ; then ./bootstrap-vcpkg.sh ; fi
+ - if [ "${USE_VCPKG}" = true ] ; then echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-osx.cmake ; fi
+ - if [ "${USE_VCPKG}" = true ] ; then echo "set(VCPKG_BUILD_TYPE release)" >> triplets/x64-linux.cmake ; fi
+ - if [ "${USE_VCPKG}" = true ] ; then travis_wait 45 ./vcpkg install opencv[contrib] --recurse ; fi
+ - popd
+
+before_script:
+ - echo ${additional_defines}
+ - mkdir build_release
+ - cd build_release
+ - cmake .. -DCMAKE_BUILD_TYPE="Release" ${VCPKG_DEFINES} ${additional_defines}
+ - cd ..
+
+script:
+ - cd build_release && cmake --build . --target install -- -j8 && cd ..
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9c1875bd..a933d8fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,11 +1,57 @@
-cmake_minimum_required(VERSION 2.8)
-project( yolo_mark CXX )
-find_package( OpenCV REQUIRED )
+cmake_minimum_required(VERSION 3.2)
-set( sources main.cpp )
+set(Yolo_mark_MAJOR_VERSION 1)
+set(Yolo_mark_MINOR_VERSION 0)
+set(Yolo_mark_PATCH_VERSION 0)
+set(Yolo_mark_VERSION ${Yolo_mark_MAJOR_VERSION}.${Yolo_mark_MINOR_VERSION}.${Yolo_mark_PATCH_VERSION})
-add_executable( yolo_mark ${sources} )
+set(CMAKE_VERBOSE_MAKEFILE "FALSE" CACHE BOOL "Create verbose makefile")
-target_compile_options( yolo_mark PUBLIC -std=c++11 -fpermissive -w -Wall )
+if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+ set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
+ message(STATUS "VCPKG found: $ENV{VCPKG_ROOT}")
+ message(STATUS "Using VCPKG integration")
+endif()
-target_link_libraries( yolo_mark ${OpenCV_LIBS} -L/usr/lib64 -ldl )
+project(Yolo_mark VERSION ${Yolo_mark_VERSION})
+
+enable_language(CXX)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules/" ${CMAKE_MODULE_PATH})
+
+if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}" CACHE PATH "Install prefix" FORCE)
+endif()
+set(INSTALL_BIN_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE PATH "Path where exe will be installed")
+
+find_package(OpenCV REQUIRED)
+
+if(TARGET opencv_world)
+ list(APPEND OpenCV_LINKED_COMPONENTS "opencv_world")
+else()
+ if(TARGET opencv_video)
+ list(APPEND OpenCV_LINKED_COMPONENTS "opencv_video")
+ endif()
+ if(TARGET opencv_videoio)
+ list(APPEND OpenCV_LINKED_COMPONENTS "opencv_videoio")
+ endif()
+ if(TARGET opencv_highgui)
+ list(APPEND OpenCV_LINKED_COMPONENTS "opencv_highgui")
+ endif()
+ if(TARGET opencv_imgproc)
+ list(APPEND OpenCV_LINKED_COMPONENTS "opencv_imgproc")
+ endif()
+ if(TARGET opencv_imgcodecs)
+ list(APPEND OpenCV_LINKED_COMPONENTS "opencv_imgcodecs")
+ endif()
+ if(TARGET opencv_core)
+ list(APPEND OpenCV_LINKED_COMPONENTS "opencv_core")
+ endif()
+endif()
+
+set(Yolo_mark_SOURCES "${CMAKE_CURRENT_LIST_DIR}/src/main.cpp")
+
+add_executable(yolo_mark ${Yolo_mark_SOURCES})
+target_link_libraries(yolo_mark ${OpenCV_LINKED_COMPONENTS})
+install(TARGETS yolo_mark DESTINATION "${INSTALL_BIN_DIR}")
diff --git a/README.md b/README.md
index 7be25129..557f4a33 100644
--- a/README.md
+++ b/README.md
@@ -1,103 +1,73 @@
# Yolo_mark
-**Windows** & **Linux** GUI for marking bounded boxes of objects in images for training Yolo v3 and v2
-* To compile on **Windows** open `yolo_mark.sln` in MSVS2013/2015, compile it **x64 & Release** and run the file: `x64/Release/yolo_mark.cmd`. Change paths in `yolo_mark.sln` to the OpenCV 2.x/3.x installed on your computer:
+GUI for marking bounding boxes of objects in images for training Yolo
- * (right click on project) -> properties -> C/C++ -> General -> Additional Include Directories: `C:\opencv_3.0\opencv\build\include;`
-
- * (right click on project) -> properties -> Linker -> General -> Additional Library Directories: `C:\opencv_3.0\opencv\build\x64\vc14\lib;`
+* To build the tool, you need a compiler, cmake and OpenCV. Then run:
-* To compile on **Linux** type in console 3 commands:
- ```
- cmake .
- make
- ./linux_mark.sh
- ```
+```bash
+cmake .
+make
+./run.sh (or run.cmd on Windows)
+```
-Supported both: OpenCV 2.x and OpenCV 3.x
+There are also build scripts (`build.sh` and `build.ps1`) to ease building on *nix systems and on windows.
---------
+To use for labeling your custom images:
-1. To test, simply run
- * **on Windows:** `x64/Release/yolo_mark.cmd`
- * **on Linux:** `./linux_mark.sh`
+* delete all files from directory `data/img`
+* put your `.jpg`-images to this directory `data/img`
+* change numer of classes (objects for detection) in file [`data/obj.data`](data/obj.data#L1)
+* put names of objects, one for each line in file [`data/obj.names`](data/obj.names)
+* run file: `yolo_mark.cmd`
-2. To use for labeling your custom images:
+To train the net for your custom objects, you should change 2 lines in file `yolo-obj.cfg`:
- * delete all files from directory `x64/Release/data/img`
- * put your `.jpg`-images to this directory `x64/Release/data/img`
- * change numer of classes (objects for detection) in file `x64/Release/data/obj.data`: https://github.com/AlexeyAB/Yolo_mark/blob/master/x64/Release/data/obj.data#L1
- * put names of objects, one for each line in file `x64/Release/data/obj.names`: https://github.com/AlexeyAB/Yolo_mark/blob/master/x64/Release/data/obj.names
- * run file: `x64\Release\yolo_mark.cmd`
+* [set number of classes (objects)](yolo-obj.cfg#L230)
+* set `filter`-value
+ * [For Yolo-v2 `(classes + 5)*5`](yolo-obj.cfg#L224)
+ * For Yolo-v3 `(classes + 5)*3`
+* Download [pre-trained weights](http://pjreddie.com/media/files/darknet19_448.conv.23) for the convolutional layers
+* Put files: `yolo-obj.cfg`, `data/train.txt`, `data/obj.names`, `data/obj.data`, `darknet19_448.conv.23` and directory `data/img` near with executable `darknet`-file, and start training: `darknet detector train data/obj.data yolo-obj.cfg darknet19_448.conv.23`
-3. To training for your custom objects, you should change 2 lines in file `x64/Release/yolo-obj.cfg`:
+For a detailed description, see [darknet repo](https://github.com/AlexeyAB/darknet#how-to-train-to-detect-your-custom-objects)
- * set number of classes (objects): https://github.com/AlexeyAB/Yolo_mark/blob/master/x64/Release/yolo-obj.cfg#L230
- * set `filter`-value
- * For Yolov2 `(classes + 5)*5`: https://github.com/AlexeyAB/Yolo_mark/blob/master/x64/Release/yolo-obj.cfg#L224
- * For Yolov3 `(classes + 5)*3`
+## How to get frames from video files
- 3.1 Download pre-trained weights for the convolutional layers (76 MB): http://pjreddie.com/media/files/darknet19_448.conv.23
-
- 3.2 Put files: `yolo-obj.cfg`, `data/train.txt`, `data/obj.names`, `data/obj.data`, `darknet19_448.conv.23` and directory `data/img` near with executable `darknet`-file, and start training: `darknet detector train data/obj.data yolo-obj.cfg darknet19_448.conv.23`
+To get frames from video files (save each N frame, in example N=10), you can use this command:
-For a detailed description, see: https://github.com/AlexeyAB/darknet#how-to-train-to-detect-your-custom-objects
-
-----
-
-#### How to get frames from videofile:
-
-To get frames from videofile (save each N frame, in example N=10), you can use this command:
* on Windows: `yolo_mark.exe data/img cap_video test.mp4 10`
* on Linux: `./yolo_mark x64/Release/data/img cap_video test.mp4 10`
-Directory `data/img` should be created before this. Also on Windows, the file `opencv_ffmpeg340_64.dll` from `opencv\build\bin` should be placed near with `yolo_mark.exe`.
+Directory `data/img` should be created before this.
+
+As a result, many frames will be collected in the directory `data/img`. Then you can label them manually using such command
-As a result, many frames will be collected in the directory `data/img`. Then you can label them manually using such command:
* on Windows: `yolo_mark.exe data/img data/train.txt data/obj.names`
* on Linux: `./yolo_mark x64/Release/data/img x64/Release/data/train.txt x64/Release/data/obj.names`
-----
-
-#### Here are:
+## Instruction manual
-* /x64/Release/
- * `yolo_mark.cmd` - example hot to use yolo mark: `yolo_mark.exe data/img data/train.txt data/obj.names`
- * `train_obj.cmd` - example how to train yolo for your custom objects (put this file near with darknet.exe): `darknet.exe detector train data/obj.data yolo-obj.cfg darknet19_448.conv.23`
- * `yolo-obj.cfg` - example of yoloV3-neural-network for 2 object
-* /x64/Release/data/
- * `obj.names` - example of list with object names
- * `obj.data` - example with configuration for training Yolo v3
- * `train.txt` - example with list of image filenames for training Yolo v3
-
-* /x64/Release/data/img/`air4.txt` - example with coordinates of objects on image `air4.jpg` with aircrafts (class=0)
+### Mouse control
-![Image of Yolo_mark](https://habrastorage.org/files/229/f06/277/229f06277fcc49279342b7edfabbb47a.jpg)
-
-### Instruction manual
-
-#### Mouse control
-
-Button | Description |
---- | --- |
+Button | Description
+--- | ---
Left | Draw box
Right | Move box
-#### Keyboard Shortcuts
-
-Shortcut | Description |
---- | --- |
-→ | Next image |
-← | Previous image |
-r | Delete selected box (mouse hovered) |
-c | Clear all marks on the current image |
-p | Copy previous mark |
-o | Track objects |
-ESC | Close application |
-n | One object per image |
-0-9 | Object id |
-m | Show coords |
-w | Line width |
-k | Hide object name |
-h | Help |
-
+### Keyboard Shortcuts
+
+Shortcut | Description
+--- | ---
+→ | Next image
+← | Previous image
+r | Delete selected box (mouse hovered)
+c | Clear all marks on the current image
+p | Copy previous mark
+o | Track objects
+ESC | Close application
+n | One object per image
+0-9 | Object id
+m | Show coords
+w | Line width
+k | Hide object name
+h | Help
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000..06bc11a8
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,57 @@
+image: Visual Studio 2017
+clone_folder: c:\projects\Yolo_mark
+cache: C:\Tools\vcpkg\installed\
+
+environment:
+ WORKSPACE: C:\projects
+ matrix:
+ - platform: Cygwin64
+ COMPILER: cygwin
+ CYGWIN_NOWINPATH: yes
+ CYGSH: C:\cygwin64\bin\bash -c
+ - platform: Win64
+ COMPILER: vs
+ configuration: Release
+ VCPKG_ROOT: C:\Tools\vcpkg
+ VCPKG_DEFAULT_TRIPLET: x64-windows
+
+install:
+ - if [%COMPILER%]==[vs] cinst cmake ninja
+ - if [%COMPILER%]==[vs] set "PATH=C:\Program Files\CMake\bin;%PATH%"
+ - if [%COMPILER%]==[vs] call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
+ - if [%COMPILER%]==[cygwin] SET "PATH=C:\cygwin64\usr\local\bin;C:\cygwin64\bin;C:\cygwin64\usr\bin;%PATH%"
+ - if [%COMPILER%]==[cygwin] SET PATH=%PATH:C:\Program Files\Git\usr\bin;=%
+ - git submodule -q update --init --recursive
+ - cd %WORKSPACE%\
+ - cd %WORKSPACE%\
+ - mkdir cygwin-downloads
+ - ps: if($env:COMPILER -eq "cygwin") { Invoke-WebRequest https://cygwin.com/setup-x86_64.exe -OutFile $env:WORKSPACE\cygwin-setup.exe }
+ - if [%COMPILER%]==[cygwin] %WORKSPACE%\cygwin-setup.exe --quiet-mode --no-shortcuts --no-startmenu --no-desktop --upgrade-also --root C:\cygwin64 --local-package-dir %WORKSPACE%\cygwin-downloads --packages gcc-g++,cmake,libopencv-devel,libncurses-devel
+ - ps: if($env:COMPILER -eq "cygwin") { Invoke-WebRequest https://github.com/Kitware/CMake/releases/download/v3.14.0/cmake-3.14.0.tar.gz -OutFile $env:WORKSPACE\cmake-3.14.0.tar.gz }
+ - if [%COMPILER%]==[cygwin] %CYGSH% 'tar zxvf cmake-3.14.0.tar.gz'
+ - if [%COMPILER%]==[cygwin] cd %WORKSPACE%\cmake-3.14.0
+ - if [%COMPILER%]==[cygwin] %CYGSH% 'cmake .'
+ - if [%COMPILER%]==[cygwin] %CYGSH% 'make -j8'
+ - if [%COMPILER%]==[cygwin] %CYGSH% 'make install'
+ - if [%COMPILER%]==[cygwin] cd %WORKSPACE%
+ - if [%COMPILER%]==[vs] cd %VCPKG_ROOT%
+ - if [%COMPILER%]==[vs] git pull
+ - if [%COMPILER%]==[vs] .\bootstrap-vcpkg.bat
+ - if [%COMPILER%]==[vs] echo set(VCPKG_BUILD_TYPE release) >> triplets\%VCPKG_DEFAULT_TRIPLET%.cmake
+ - if [%COMPILER%]==[vs] .\vcpkg.exe install opencv[contrib] --recurse
+ - cd %WORKSPACE%\Yolo_mark\
+ - mkdir build_debug && cd build_debug
+ - if [%COMPILER%]==[cygwin] %CYGSH% 'cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="Debug"'
+ - cd ..
+ - mkdir build_release && cd build_release
+ - if [%COMPILER%]==[cygwin] %CYGSH% 'cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE="Release"'
+ - if [%COMPILER%]==[vs] if [%configuration%]==[Release] cmake -G "Visual Studio 15 2017" -T "host=x64" -A "x64" "-DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%\scripts\buildsystems\vcpkg.cmake" "-DVCPKG_TARGET_TRIPLET=%VCPKG_DEFAULT_TRIPLET%" -DCMAKE_BUILD_TYPE="Release" ..
+ - cd ..
+
+build_script:
+ - if [%COMPILER%]==[cygwin] cd build_debug && %CYGSH% 'cmake --build . --target install -- -j8' && cd ..
+ - if [%COMPILER%]==[cygwin] cd build_release && %CYGSH% 'cmake --build . --target install -- -j8' && cd ..
+ - if [%COMPILER%]==[vs] if [%configuration%]==[Release] cd build_release && cmake --build . --config Release --parallel 8 --target install && cd ..
+
+artifacts:
+ - path: '*.exe'
diff --git a/build.ps1 b/build.ps1
new file mode 100755
index 00000000..b5defa9d
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,163 @@
+#!/usr/bin/env pwsh
+
+$number_of_build_workers=8
+$use_vcpkg=$true
+
+function getProgramFiles32bit() {
+ $out = ${env:PROGRAMFILES(X86)}
+ if ($null -eq $out) {
+ $out = ${env:PROGRAMFILES}
+ }
+
+ if ($null -eq $out) {
+ throw "Could not find [Program Files 32-bit]"
+ }
+
+ return $out
+}
+
+function getLatestVisualStudioWithDesktopWorkloadPath() {
+ $programFiles = getProgramFiles32bit
+ $vswhereExe = "$programFiles\Microsoft Visual Studio\Installer\vswhere.exe"
+ if (Test-Path $vswhereExe) {
+ $output = & $vswhereExe -products * -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -format xml
+ [xml]$asXml = $output
+ foreach ($instance in $asXml.instances.instance) {
+ $installationPath = $instance.InstallationPath -replace "\\$" # Remove potential trailing backslash
+ }
+ if (!$installationPath) {
+ Write-Host "Warning: no full Visual Studio setup has been found, extending search to include also partial installations" -ForegroundColor Yellow
+ $output = & $vswhereExe -products * -latest -format xml
+ [xml]$asXml = $output
+ foreach ($instance in $asXml.instances.instance) {
+ $installationPath = $instance.InstallationPath -replace "\\$" # Remove potential trailing backslash
+ }
+ }
+ if (!$installationPath) {
+ Throw "Could not locate any installation of Visual Studio"
+ }
+ }
+ else {
+ Throw "Could not locate vswhere at $vswhereExe"
+ }
+ return $installationPath
+}
+
+
+function getLatestVisualStudioWithDesktopWorkloadVersion() {
+ $programFiles = getProgramFiles32bit
+ $vswhereExe = "$programFiles\Microsoft Visual Studio\Installer\vswhere.exe"
+ if (Test-Path $vswhereExe) {
+ $output = & $vswhereExe -products * -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -format xml
+ [xml]$asXml = $output
+ foreach ($instance in $asXml.instances.instance) {
+ $installationVersion = $instance.InstallationVersion
+ }
+ if (!$installationVersion) {
+ Write-Host "Warning: no full Visual Studio setup has been found, extending search to include also partial installations" -ForegroundColor Yellow
+ $output = & $vswhereExe -products * -latest -format xml
+ [xml]$asXml = $output
+ foreach ($instance in $asXml.instances.instance) {
+ $installationVersion = $instance.installationVersion
+ }
+ }
+ if (!$installationVersion) {
+ Throw "Could not locate any installation of Visual Studio"
+ }
+ }
+ else {
+ Throw "Could not locate vswhere at $vswhereExe"
+ }
+ return $installationVersion
+}
+
+
+if ((Test-Path env:VCPKG_ROOT) -and $use_vcpkg) {
+ $vcpkg_path = "$env:VCPKG_ROOT"
+ Write-Host "Found vcpkg in VCPKG_ROOT: $vcpkg_path"
+}
+elseif ((Test-Path "${env:WORKSPACE}\vcpkg") -and $use_vcpkg) {
+ $vcpkg_path = "${env:WORKSPACE}\vcpkg"
+ Write-Host "Found vcpkg in WORKSPACE\vcpkg: $vcpkg_path"
+}
+else {
+ Write-Host "Unable to find VCPKG`n" -ForegroundColor Yellow
+}
+
+if ($null -eq $env:VCPKG_DEFAULT_TRIPLET -and $use_vcpkg) {
+ Write-Host "No default triplet has been set-up for vcpkg. Defaulting to x64-windows" -ForegroundColor Yellow
+ $vcpkg_triplet = "x64-windows"
+}
+elseif ($use_vcpkg) {
+ $vcpkg_triplet = $env:VCPKG_DEFAULT_TRIPLET
+}
+
+if ($vcpkg_triplet -Match "x86" -and $use_vcpkg) {
+ Throw "Yolo_mark is supported only in x64 builds!"
+}
+
+if ($null -eq (Get-Command "cl.exe" -ErrorAction SilentlyContinue)) {
+ $vsfound = getLatestVisualStudioWithDesktopWorkloadPath
+ Write-Host "Found VS in ${vsfound}"
+ Push-Location "${vsfound}\Common7\Tools"
+ cmd.exe /c "VsDevCmd.bat -arch=x64 & set" |
+ ForEach-Object {
+ if ($_ -match "=") {
+ $v = $_.split("="); Set-Item -force -path "ENV:\$($v[0])" -value "$($v[1])"
+ }
+ }
+ Pop-Location
+ Write-Host "Visual Studio Command Prompt variables set" -ForegroundColor Yellow
+}
+
+$tokens = getLatestVisualStudioWithDesktopWorkloadVersion
+$tokens = $tokens.split('.')
+if ($tokens[0] -eq "14") {
+ $generator = "Visual Studio 14 2015"
+}
+elseif ($tokens[0] -eq "15") {
+ $generator = "Visual Studio 15 2017"
+}
+elseif ($tokens[0] -eq "16") {
+ $generator = "Visual Studio 16 2019"
+}
+else {
+ throw "Unknown Visual Studio version, unsupported configuration"
+}
+Write-Host "Setting up environment to use CMake generator: $generator" -ForegroundColor Yellow
+
+if ($null -eq (Get-Command "nvcc.exe" -ErrorAction SilentlyContinue)) {
+ if (Test-Path env:CUDA_PATH) {
+ $env:PATH += ";${env:CUDA_PATH}\bin"
+ Write-Host "Found cuda in ${env:CUDA_PATH}" -ForegroundColor Yellow
+ }
+ else {
+ Write-Host "Unable to find CUDA, if necessary please install it or define a CUDA_PATH env variable pointing to the install folder" -ForegroundColor Yellow
+ }
+}
+
+if (Test-Path env:CUDA_PATH) {
+ if (-Not(Test-Path env:CUDA_TOOLKIT_ROOT_DIR)) {
+ $env:CUDA_TOOLKIT_ROOT_DIR = "${env:CUDA_PATH}"
+ Write-Host "Added missing env variable CUDA_TOOLKIT_ROOT_DIR" -ForegroundColor Yellow
+ }
+}
+
+
+## DEBUG
+#New-Item -Path .\build_win_debug -ItemType directory -Force
+#Set-Location build_win_debug
+#cmake -G "$generator" -T "host=x64" -A "x64" "-DCMAKE_TOOLCHAIN_FILE=$vcpkg_path\scripts\buildsystems\vcpkg.cmake" "-DVCPKG_TARGET_TRIPLET=$vcpkg_triplet" #"-DCMAKE_BUILD_TYPE=Debug" $additional_build_setup ..
+#cmake --build . --config Debug --target install
+##cmake --build . --config Debug --parallel ${number_of_build_workers} --target install #valid only for CMake 3.12+
+#Copy-Item Debug\*.dll ..
+#Set-Location ..
+
+# RELEASE
+New-Item -Path .\build_win_release -ItemType directory -Force
+Set-Location build_win_release
+cmake -G "$generator" -T "host=x64" -A "x64" "-DCMAKE_TOOLCHAIN_FILE=$vcpkg_path\scripts\buildsystems\vcpkg.cmake" "-DVCPKG_TARGET_TRIPLET=$vcpkg_triplet" "-DCMAKE_BUILD_TYPE=Release" $additional_build_setup ..
+cmake --build . --config Release --target install
+#cmake --build . --config Release --parallel ${number_of_build_workers} --target install #valid only for CMake 3.12+
+Copy-Item Release\*.dll ..
+Set-Location ..
diff --git a/build.sh b/build.sh
new file mode 100755
index 00000000..81d54d65
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+
+number_of_build_workers=8
+bypass_vcpkg=true
+
+if [[ "$OSTYPE" == "darwin"* ]]; then
+ if [[ "$1" == "gcc" ]]; then
+ export CC="/usr/local/bin/gcc-9"
+ export CXX="/usr/local/bin/g++-9"
+ fi
+ vcpkg_triplet="x64-osx"
+else
+ vcpkg_triplet="x64-linux"
+fi
+
+if [[ ! -z "${VCPKG_ROOT}" ]] && [ -d ${VCPKG_ROOT} ] && [ ! "$bypass_vcpkg" = true ]
+then
+ vcpkg_path="${VCPKG_ROOT}"
+ vcpkg_define="-DCMAKE_TOOLCHAIN_FILE=${vcpkg_path}/scripts/buildsystems/vcpkg.cmake"
+ vcpkg_triplet_define="-DVCPKG_TARGET_TRIPLET=$vcpkg_triplet"
+ echo "Found vcpkg in VCPKG_ROOT: ${vcpkg_path}"
+elif [[ ! -z "${WORKSPACE}" ]] && [ -d ${WORKSPACE}/vcpkg ] && [ ! "$bypass_vcpkg" = true ]
+then
+ vcpkg_path="${WORKSPACE}/vcpkg"
+ vcpkg_define="-DCMAKE_TOOLCHAIN_FILE=${vcpkg_path}/scripts/buildsystems/vcpkg.cmake"
+ vcpkg_triplet_define="-DVCPKG_TARGET_TRIPLET=$vcpkg_triplet"
+ echo "Found vcpkg in WORKSPACE/vcpkg: ${vcpkg_path}"
+elif [ ! "$bypass_vcpkg" = true ]
+then
+ (>&2 echo "yolo_mark is unsupported without vcpkg, use at your own risk!")
+fi
+
+## DEBUG
+#mkdir -p build_debug
+#cd build_debug
+#cmake .. -DCMAKE_BUILD_TYPE=Debug ${vcpkg_define} ${vcpkg_triplet_define} ${additional_defines} ${additional_build_setup}
+#cmake --build . --target install -- -j${number_of_build_workers}
+##cmake --build . --target install --parallel ${number_of_build_workers} #valid only for CMake 3.12+
+#cd ..
+
+# RELEASE
+mkdir -p build_release
+cd build_release
+cmake .. -DCMAKE_BUILD_TYPE=Release ${vcpkg_define} ${vcpkg_triplet_define} ${additional_defines} ${additional_build_setup}
+cmake --build . --target install -- -j${number_of_build_workers}
+#cmake --build . --target install --parallel ${number_of_build_workers} #valid only for CMake 3.12+
+cd ..
+
+# In case you want to discard changes from examples, it's useful to run this command:
+# git update-index --assume-unchanged data/img/air1.jpg data/img/air1.txt data/img/air2.jpg data/img/air2.txt data/img/air3.jpg data/img/air3.txt data/img/air4.jpg data/img/air4.txt data/img/air5.jpg data/img/air5.txt data/img/air6.jpg data/img/air6.txt data/img/bird1.jpg data/img/bird1.txt data/img/bird2.jpg data/img/bird2.txt data/img/bird3.jpg data/img/bird3.txt data/img/bird4.jpg data/img/bird4.txt data/obj.data data/obj.names data/train.txt
+
diff --git a/x64/Release/data/img/air1.jpg b/data/img/air1.jpg
similarity index 100%
rename from x64/Release/data/img/air1.jpg
rename to data/img/air1.jpg
diff --git a/x64/Release/data/img/air1.txt b/data/img/air1.txt
similarity index 100%
rename from x64/Release/data/img/air1.txt
rename to data/img/air1.txt
diff --git a/x64/Release/data/img/air2.jpg b/data/img/air2.jpg
similarity index 100%
rename from x64/Release/data/img/air2.jpg
rename to data/img/air2.jpg
diff --git a/x64/Release/data/img/air2.txt b/data/img/air2.txt
similarity index 100%
rename from x64/Release/data/img/air2.txt
rename to data/img/air2.txt
diff --git a/x64/Release/data/img/air3.jpg b/data/img/air3.jpg
similarity index 100%
rename from x64/Release/data/img/air3.jpg
rename to data/img/air3.jpg
diff --git a/x64/Release/data/img/air3.txt b/data/img/air3.txt
similarity index 100%
rename from x64/Release/data/img/air3.txt
rename to data/img/air3.txt
diff --git a/x64/Release/data/img/air4.jpg b/data/img/air4.jpg
similarity index 100%
rename from x64/Release/data/img/air4.jpg
rename to data/img/air4.jpg
diff --git a/x64/Release/data/img/air4.txt b/data/img/air4.txt
similarity index 100%
rename from x64/Release/data/img/air4.txt
rename to data/img/air4.txt
diff --git a/x64/Release/data/img/air5.jpg b/data/img/air5.jpg
similarity index 100%
rename from x64/Release/data/img/air5.jpg
rename to data/img/air5.jpg
diff --git a/x64/Release/data/img/air5.txt b/data/img/air5.txt
similarity index 100%
rename from x64/Release/data/img/air5.txt
rename to data/img/air5.txt
diff --git a/x64/Release/data/img/air6.jpg b/data/img/air6.jpg
similarity index 100%
rename from x64/Release/data/img/air6.jpg
rename to data/img/air6.jpg
diff --git a/x64/Release/data/img/air6.txt b/data/img/air6.txt
similarity index 100%
rename from x64/Release/data/img/air6.txt
rename to data/img/air6.txt
diff --git a/x64/Release/data/img/bird1.jpg b/data/img/bird1.jpg
similarity index 100%
rename from x64/Release/data/img/bird1.jpg
rename to data/img/bird1.jpg
diff --git a/x64/Release/data/img/bird1.txt b/data/img/bird1.txt
similarity index 100%
rename from x64/Release/data/img/bird1.txt
rename to data/img/bird1.txt
diff --git a/x64/Release/data/img/bird2.jpg b/data/img/bird2.jpg
similarity index 100%
rename from x64/Release/data/img/bird2.jpg
rename to data/img/bird2.jpg
diff --git a/x64/Release/data/img/bird2.txt b/data/img/bird2.txt
similarity index 100%
rename from x64/Release/data/img/bird2.txt
rename to data/img/bird2.txt
diff --git a/x64/Release/data/img/bird3.jpg b/data/img/bird3.jpg
similarity index 100%
rename from x64/Release/data/img/bird3.jpg
rename to data/img/bird3.jpg
diff --git a/x64/Release/data/img/bird3.txt b/data/img/bird3.txt
similarity index 100%
rename from x64/Release/data/img/bird3.txt
rename to data/img/bird3.txt
diff --git a/x64/Release/data/img/bird4.jpg b/data/img/bird4.jpg
similarity index 100%
rename from x64/Release/data/img/bird4.jpg
rename to data/img/bird4.jpg
diff --git a/x64/Release/data/img/bird4.txt b/data/img/bird4.txt
similarity index 100%
rename from x64/Release/data/img/bird4.txt
rename to data/img/bird4.txt
diff --git a/x64/Release/data/obj.data b/data/obj.data
similarity index 100%
rename from x64/Release/data/obj.data
rename to data/obj.data
diff --git a/x64/Release/data/obj.names b/data/obj.names
similarity index 100%
rename from x64/Release/data/obj.names
rename to data/obj.names
diff --git a/x64/Release/data/train.txt b/data/train.txt
similarity index 100%
rename from x64/Release/data/train.txt
rename to data/train.txt
diff --git a/linux_mark.sh b/linux_mark.sh
deleted file mode 100644
index 7b560195..00000000
--- a/linux_mark.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-echo Example how to start marking bouded boxes for training set Yolo v2
-
-
-./yolo_mark x64/Release/data/img x64/Release/data/train.txt x64/Release/data/obj.names
-
-
-pause
diff --git a/main.cpp b/main.cpp
deleted file mode 100644
index 53ec2dc6..00000000
--- a/main.cpp
+++ /dev/null
@@ -1,1014 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include // C++11: async(); feature<>;
-#include
-#include
-#include // std::ofstream
-#include // std::unique
-
-#include // C++
-#include
-#include
-#include
-//#include
-#include
-
-#ifdef _DEBUG
-#define LIB_SUFFIX "d.lib"
-#else
-#define LIB_SUFFIX ".lib"
-#endif // DEBUG
-
-#ifndef CV_VERSION_EPOCH
-#include "opencv2/videoio/videoio.hpp"
-#define OPENCV_VERSION CVAUX_STR(CV_VERSION_MAJOR)"" CVAUX_STR(CV_VERSION_MINOR)"" CVAUX_STR(CV_VERSION_REVISION)
-#pragma comment(lib, "opencv_world" OPENCV_VERSION LIB_SUFFIX)
-#else
-#define OPENCV_VERSION CVAUX_STR(CV_VERSION_EPOCH)"" CVAUX_STR(CV_VERSION_MAJOR)"" CVAUX_STR(CV_VERSION_MINOR)
-#pragma comment(lib, "opencv_core" OPENCV_VERSION LIB_SUFFIX)
-#pragma comment(lib, "opencv_imgproc" OPENCV_VERSION LIB_SUFFIX)
-#pragma comment(lib, "opencv_highgui" OPENCV_VERSION LIB_SUFFIX)
-#endif
-
-#ifndef CV_FILLED
-#define CV_FILLED cv::FILLED
-#endif
-
-
-using namespace cv;
-
-
-// label coordinates
-struct coord_t {
- cv::Rect_ abs_rect;
- int id;
-};
-
-class Tracker_optflow {
-public:
- const int flow_error;
-
- Tracker_optflow(int win_size = 15, int max_level = 3, int iterations = 8000, int _flow_error = -1) :
- flow_error((_flow_error > 0) ? _flow_error : (win_size * 4))
- {
- sync_PyrLKOpticalFlow = cv::SparsePyrLKOpticalFlow::create();
- sync_PyrLKOpticalFlow->setWinSize(cv::Size(win_size, win_size)); // 9, 15, 21, 31
- sync_PyrLKOpticalFlow->setMaxLevel(max_level); // +- 3 pt
-
- }
-
- // just to avoid extra allocations
- cv::Mat dst_grey;
- cv::Mat prev_pts_flow, cur_pts_flow;
- cv::Mat status, err;
-
- cv::Mat src_grey; // used in both functions
- cv::Ptr sync_PyrLKOpticalFlow;
-
- std::vector cur_bbox_vec;
- std::vector good_bbox_vec_flags;
-
- void update_cur_bbox_vec(std::vector _cur_bbox_vec)
- {
- cur_bbox_vec = _cur_bbox_vec;
- good_bbox_vec_flags = std::vector(cur_bbox_vec.size(), true);
- cv::Mat prev_pts, cur_pts_flow;
-
- for (auto &i : cur_bbox_vec) {
- float x_center = (i.abs_rect.x + i.abs_rect.width / 2.0F);
- float y_center = (i.abs_rect.y + i.abs_rect.height / 2.0F);
- prev_pts.push_back(cv::Point2f(x_center, y_center));
- }
-
- if (prev_pts.rows == 0)
- prev_pts_flow = cv::Mat();
- else
- cv::transpose(prev_pts, prev_pts_flow);
- }
-
-
- void update_tracking_flow(cv::Mat new_src_mat, std::vector _cur_bbox_vec)
- {
- if (new_src_mat.channels() == 1) {
- src_grey = new_src_mat.clone();
- }
- else if (new_src_mat.channels() == 3) {
- cv::cvtColor(new_src_mat, src_grey, cv::COLOR_BGR2GRAY, 1);
- }
- else if (new_src_mat.channels() == 4) {
- cv::cvtColor(new_src_mat, src_grey, cv::COLOR_BGRA2GRAY, 1);
- }
- else {
- std::cerr << " Warning: new_src_mat.channels() is not: 1, 3 or 4. It is = " << new_src_mat.channels() << " \n";
- return;
- }
- update_cur_bbox_vec(_cur_bbox_vec);
- }
-
-
- std::vector tracking_flow(cv::Mat new_dst_mat, bool check_error = true)
- {
- if (sync_PyrLKOpticalFlow.empty()) {
- std::cout << "sync_PyrLKOpticalFlow isn't initialized \n";
- return cur_bbox_vec;
- }
-
- cv::cvtColor(new_dst_mat, dst_grey, cv::COLOR_BGR2GRAY, 1);
-
- if (src_grey.rows != dst_grey.rows || src_grey.cols != dst_grey.cols) {
- src_grey = dst_grey.clone();
- //std::cerr << " Warning: src_grey.rows != dst_grey.rows || src_grey.cols != dst_grey.cols \n";
- return cur_bbox_vec;
- }
-
- if (prev_pts_flow.cols < 1) {
- return cur_bbox_vec;
- }
-
- ////sync_PyrLKOpticalFlow_gpu.sparse(src_grey_gpu, dst_grey_gpu, prev_pts_flow_gpu, cur_pts_flow_gpu, status_gpu, &err_gpu); // OpenCV 2.4.x
- sync_PyrLKOpticalFlow->calc(src_grey, dst_grey, prev_pts_flow, cur_pts_flow, status, err); // OpenCV 3.x
-
- dst_grey.copyTo(src_grey);
-
- std::vector result_bbox_vec;
-
- if (err.rows == cur_bbox_vec.size() && status.rows == cur_bbox_vec.size())
- {
- for (size_t i = 0; i < cur_bbox_vec.size(); ++i)
- {
- cv::Point2f cur_key_pt = cur_pts_flow.at(0, i);
- cv::Point2f prev_key_pt = prev_pts_flow.at(0, i);
-
- float moved_x = cur_key_pt.x - prev_key_pt.x;
- float moved_y = cur_key_pt.y - prev_key_pt.y;
-
- if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i])
- if (err.at(0, i) < flow_error && status.at(0, i) != 0 &&
- ((float)cur_bbox_vec[i].abs_rect.x + moved_x) > 0 && ((float)cur_bbox_vec[i].abs_rect.y + moved_y) > 0)
- {
- cur_bbox_vec[i].abs_rect.x += moved_x;// +0.5;
- cur_bbox_vec[i].abs_rect.y += moved_y;// +0.5;
- result_bbox_vec.push_back(cur_bbox_vec[i]);
- }
- else good_bbox_vec_flags[i] = false;
- else good_bbox_vec_flags[i] = false;
-
- //if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]);
- }
- }
-
- prev_pts_flow = cur_pts_flow.clone();
-
- return result_bbox_vec;
- }
-
-};
-
-std::atomic right_button_click;
-std::atomic move_rect_id;
-std::atomic move_rect;
-std::atomic clear_marks;
-std::atomic copy_previous_marks(false);
-std::atomic tracker_copy_previous_marks(false);
-
-std::atomic show_help;
-std::atomic exit_flag(false);
-
-std::atomic mark_line_width(2); // default mark line width is 2 pixels.
-const int MAX_MARK_LINE_WIDTH = 3;
-std::atomic show_mark_class(true);
-std::atomic delete_selected(false);
-
-std::atomic x_start, y_start;
-std::atomic x_end, y_end;
-std::atomic x_size, y_size;
-std::atomic draw_select, selected, undo;
-
-std::atomic add_id_img;
-Rect prev_img_rect(0, 0, 50, 100);
-Rect next_img_rect(1280 - 50, 0, 50, 100);
-
-
-void callback_mouse_click(int event, int x, int y, int flags, void* user_data)
-{
- if (event == cv::EVENT_LBUTTONDBLCLK)
- {
- std::cout << "cv::EVENT_LBUTTONDBLCLK \n";
- }
- else if (event == cv::EVENT_LBUTTONDOWN)
- {
- draw_select = true;
- selected = false;
- x_start = x;
- y_start = y;
-
- if (prev_img_rect.contains(Point2i(x, y))) add_id_img = -1;
- else if (next_img_rect.contains(Point2i(x, y))) add_id_img = 1;
- else add_id_img = 0;
- //std::cout << "cv::EVENT_LBUTTONDOWN \n";
- }
- else if (event == cv::EVENT_LBUTTONUP)
- {
- x_size = abs(x - x_start);
- y_size = abs(y - y_start);
- x_end = max(x, 0);
- y_end = max(y, 0);
- draw_select = false;
- selected = true;
- //std::cout << "cv::EVENT_LBUTTONUP \n";
- }
- else if (event == cv::EVENT_RBUTTONDOWN)
- {
- right_button_click = true;
-
- x_start = x;
- y_start = y;
- std::cout << "cv::EVENT_RBUTTONDOWN \n";
- }
- else if (event == cv::EVENT_RBUTTONUP)
- {
- right_button_click = false;
- move_rect = true;
- }
- if (event == cv::EVENT_RBUTTONDBLCLK)
- {
- std::cout << "cv::EVENT_RBUTTONDBLCLK \n";
- }
- else if (event == cv::EVENT_MOUSEMOVE)
- {
- x_end = max(x, 0);
- y_end = max(y, 0);
- }
-}
-
-class comma : public std::numpunct {
-public:
- comma() : std::numpunct() {}
-protected:
- char do_decimal_point() const { return '.'; }
-};
-
-
-int main(int argc, char *argv[])
-{
-
- try
- {
- std::locale loccomma(std::locale::classic(), new comma);
- std::locale::global(loccomma);
-
- std::string images_path = "./";
-
- if (argc >= 2) {
- images_path = std::string(argv[1]); // path to images, train and synset
- }
- else {
- std::cout << "Usage: [path_to_images] [train.txt] [obj.names] \n";
- return 0;
- }
-
- std::string train_filename = images_path + "train.txt";
- std::string synset_filename = images_path + "obj.names";
-
- if (argc >= 3) {
- train_filename = std::string(argv[2]); // file containing: list of images
- }
-
- if (argc >= 4) {
- synset_filename = std::string(argv[3]); // file containing: object names
- }
-
- // optical flow tracker
- Tracker_optflow tracker_optflow;
- cv::Mat optflow_img;
-
- // capture frames from video file - 1 frame per 3 seconds of video
- if (argc >= 4 && (train_filename == "cap_video" || train_filename == "cap_video_backward")) {
- const std::string videofile = synset_filename;
- cv::VideoCapture cap(videofile);
-#ifndef CV_VERSION_EPOCH // OpenCV 3.x
- const int fps = cap.get(cv::CAP_PROP_FPS);
-#else // OpenCV 2.x
- const int fps = cap.get(CV_CAP_PROP_FPS);
-#endif
- int frame_counter = 0, image_counter = 0;
- int backward = (train_filename == "cap_video_backward") ? 1 : 0;
- if (backward) image_counter = 99999999; // 99M
- float save_each_frames = 50;
- if (argc >= 5) save_each_frames = std::stoul(std::string(argv[4]));
-
- int pos_filename = 0;
- if ((1 + videofile.find_last_of("\\")) < videofile.length()) pos_filename = 1 + videofile.find_last_of("\\");
- if ((1 + videofile.find_last_of("/")) < videofile.length()) pos_filename = std::max(pos_filename, 1 + (int)videofile.find_last_of("/"));
- std::string const filename = videofile.substr(pos_filename);
- std::string const filename_without_ext = filename.substr(0, filename.find_last_of("."));
-
- for (cv::Mat frame; cap >> frame, cap.isOpened() && !frame.empty();) {
- cv::imshow("video cap to frames", frame);
-#ifndef CV_VERSION_EPOCH
- int pressed_key = cv::waitKeyEx(20); // OpenCV 3.x
-#else
- int pressed_key = cv::waitKey(20); // OpenCV 2.x
-#endif
- if (pressed_key == 27 || pressed_key == 1048603) break; // ESC - exit (OpenCV 2.x / 3.x)
- if (frame_counter++ >= save_each_frames) { // save frame for each 3 second
- frame_counter = 0;
- std::stringstream image_counter_ss;
- image_counter_ss << std::setw(8) << std::setfill('0') << image_counter;
- if (backward) image_counter--;
- else image_counter++;
- std::string img_name = images_path + "/" + filename_without_ext + "_" + image_counter_ss.str() + ".jpg";
- std::cout << "saved " << img_name << std::endl;
- cv::imwrite(img_name, frame);
- }
- }
- exit(0);
- }
-
- bool show_mouse_coords = false;
- std::vector filenames_in_folder;
- //glob(images_path, filenames_in_folder); // void glob(String pattern, std::vector& result, bool recursive = false);
- cv::String images_path_cv = images_path;
- std::vector filenames_in_folder_cv;
- glob(images_path_cv, filenames_in_folder_cv); // void glob(String pattern, std::vector& result, bool recursive = false);
- for (auto &i : filenames_in_folder_cv)
- filenames_in_folder.push_back(i);
-
- std::vector jpg_filenames_path;
- std::vector jpg_filenames;
- std::vector jpg_filenames_without_ext;
- std::vector image_ext;
- std::vector txt_filenames;
- std::vector jpg_in_train;
- std::vector synset_txt;
-
- // image-paths to txt-paths
- for (auto &i : filenames_in_folder)
- {
- int pos_filename = 0;
- if ((1 + i.find_last_of("\\")) < i.length()) pos_filename = 1 + i.find_last_of("\\");
- if ((1 + i.find_last_of("/")) < i.length()) pos_filename = std::max(pos_filename, 1 + (int)i.find_last_of("/"));
-
-
- std::string const filename = i.substr(pos_filename);
- std::string const ext = i.substr(i.find_last_of(".") + 1);
- std::string const filename_without_ext = filename.substr(0, filename.find_last_of("."));
-
- if (ext == "jpg" || ext == "JPG" ||
- ext == "jpeg" || ext == "JPEG" ||
- ext == "bmp" || ext == "BMP" ||
- ext == "png" || ext == "PNG" ||
- ext == "ppm" || ext == "PPM")
- {
- jpg_filenames_without_ext.push_back(filename_without_ext);
- image_ext.push_back(ext);
- jpg_filenames.push_back(filename);
- jpg_filenames_path.push_back(i);
- }
- if (ext == "txt") {
- txt_filenames.push_back(filename_without_ext);
- }
- }
- std::sort(jpg_filenames.begin(), jpg_filenames.end());
- std::sort(jpg_filenames_path.begin(), jpg_filenames_path.end());
- std::sort(txt_filenames.begin(), txt_filenames.end());
-
- if (jpg_filenames.size() == 0) {
- std::cout << "Error: Image files not found by path: " << images_path << std::endl;
- return 0;
- }
-
- // check whether there are files with the same names (but different extensions)
- {
- auto sorted_names_without_ext = jpg_filenames_without_ext;
- std::sort(sorted_names_without_ext.begin(), sorted_names_without_ext.end());
- for (size_t i = 1; i < sorted_names_without_ext.size(); ++i) {
- if (sorted_names_without_ext[i - 1] == sorted_names_without_ext[i]) {
- std::cout << "Error: Can't create " << sorted_names_without_ext[i] <<
- ".txt file for several images with different extensions but with the same filename: "
- << sorted_names_without_ext[i] << std::endl;
- // print duplicate images
- for (size_t k = 0; k < jpg_filenames_without_ext.size(); ++k) {
- if (jpg_filenames_without_ext[k] == sorted_names_without_ext[i]) {
- std::cout << jpg_filenames_without_ext[k] << "." << image_ext[k] << std::endl;
- }
- }
- return 0;
- }
- }
- }
-
- // intersect jpg & txt
- std::vector intersect_filenames(jpg_filenames.size());
- std::vector difference_filenames(jpg_filenames.size());
- std::vector intersect_ext;
- std::vector difference_ext;
-
- auto dif_it_end = std::set_difference(jpg_filenames_without_ext.begin(), jpg_filenames_without_ext.end(),
- txt_filenames.begin(), txt_filenames.end(),
- difference_filenames.begin());
- difference_filenames.resize(dif_it_end - difference_filenames.begin());
-
- auto inter_it_end = std::set_intersection(jpg_filenames_without_ext.begin(), jpg_filenames_without_ext.end(),
- txt_filenames.begin(), txt_filenames.end(),
- intersect_filenames.begin());
- intersect_filenames.resize(inter_it_end - intersect_filenames.begin());
-
- // get intersect extensions for intersect_filenames
- for (auto &i : intersect_filenames) {
- size_t ext_index = find(jpg_filenames_without_ext.begin(), jpg_filenames_without_ext.end(), i) - jpg_filenames_without_ext.begin();
- intersect_ext.push_back(image_ext[ext_index]);
- }
-
- // get difference extensions for intersect_filenames
- for (auto &i : difference_filenames) {
- size_t ext_index = find(jpg_filenames_without_ext.begin(), jpg_filenames_without_ext.end(), i) - jpg_filenames_without_ext.begin();
- difference_ext.push_back(image_ext[ext_index]);
- }
-
- txt_filenames.clear();
- for (auto &i : intersect_filenames) {
- txt_filenames.push_back(i + ".txt");
- }
-
- int image_list_count = max(1, (int)jpg_filenames_path.size() - 1);
-
- // store train.txt
- std::ofstream ofs_train(train_filename, std::ios::out | std::ios::trunc);
- if (!ofs_train.is_open()) {
- throw(std::runtime_error("Can't open file: " + train_filename));
- }
-
- for (size_t i = 0; i < intersect_filenames.size(); ++i) {
- ofs_train << images_path << "/" << intersect_filenames[i] << "." << intersect_ext[i] << std::endl;
- }
- ofs_train.flush();
- std::cout << "File opened for output: " << train_filename << std::endl;
-
-
- // load synset.txt
- {
- std::ifstream ifs(synset_filename);
- if (!ifs.is_open()) {
- throw(std::runtime_error("Can't open file: " + synset_filename));
- }
-
- for (std::string line; getline(ifs, line);)
- synset_txt.push_back(line);
- }
- std::cout << "File loaded: " << synset_filename << std::endl;
-
- Mat preview(Size(100, 100), CV_8UC3);
- Mat full_image(Size(1280, 720), CV_8UC3);
- Mat frame(Size(full_image.cols, full_image.rows + preview.rows), CV_8UC3);
-
- Rect full_rect_dst(Point2i(0, preview.rows), Size(frame.cols, frame.rows - preview.rows));
- Mat full_image_roi = frame(full_rect_dst);
-
- size_t const preview_number = frame.cols / preview.cols;
-
-
- // labels on the current image
- std::vector current_coord_vec;
- Size current_img_size;
-
-
- std::string const window_name = "Marking images";
- namedWindow(window_name, WINDOW_NORMAL);
- resizeWindow(window_name, 1280, 720);
- imshow(window_name, frame);
- moveWindow(window_name, 0, 0);
- setMouseCallback(window_name, callback_mouse_click);
-
- bool next_by_click = false;
- bool marks_changed = false;
-
- int old_trackbar_value = -1, trackbar_value = 0;
- std::string const trackbar_name = "image num";
- int tb_res = createTrackbar(trackbar_name, window_name, &trackbar_value, image_list_count);
-
- int old_current_obj_id = -1, current_obj_id = 0;
- std::string const trackbar_name_2 = "object id";
- int const max_object_id = (synset_txt.size() > 0) ? synset_txt.size() : 20;
- int tb_res_2 = createTrackbar(trackbar_name_2, window_name, ¤t_obj_id, max_object_id);
-
-
- do {
- //trackbar_value = min(max(0, trackbar_value), (int)jpg_filenames_path.size() - 1);
-
- // selected new image
- if (old_trackbar_value != trackbar_value || exit_flag)
- {
- trackbar_value = min(max(0, trackbar_value), (int)jpg_filenames_path.size() - 1);
- setTrackbarPos(trackbar_name, window_name, trackbar_value);
- frame(Rect(0, 0, frame.cols, preview.rows)) = Scalar::all(0);
- move_rect_id = -1;
-
- // save current coords
- if (old_trackbar_value >= 0) // && current_coord_vec.size() > 0) // Yolo v2 can processes background-image without objects
- {
- try
- {
- std::string const jpg_filename = jpg_filenames[old_trackbar_value];
- std::string const filename_without_ext = jpg_filename.substr(0, jpg_filename.find_last_of("."));
- std::string const txt_filename = filename_without_ext + ".txt";
- std::string const txt_filename_path = images_path + "/" + txt_filename;
-
- std::cout << "txt_filename_path = " << txt_filename_path << std::endl;
-
- std::ofstream ofs(txt_filename_path, std::ios::out | std::ios::trunc);
- ofs << std::fixed;
-
- // store coords to [image name].txt
- for (auto &i : current_coord_vec)
- {
- float const relative_center_x = (float)(i.abs_rect.x + i.abs_rect.width / 2) / full_image_roi.cols;
- float const relative_center_y = (float)(i.abs_rect.y + i.abs_rect.height / 2) / full_image_roi.rows;
- float const relative_width = (float)i.abs_rect.width / full_image_roi.cols;
- float const relative_height = (float)i.abs_rect.height / full_image_roi.rows;
-
- if (relative_width <= 0) continue;
- if (relative_height <= 0) continue;
- if (relative_center_x <= 0) continue;
- if (relative_center_y <= 0) continue;
-
- ofs << i.id << " " <<
- relative_center_x << " " << relative_center_y << " " <<
- relative_width << " " << relative_height << std::endl;
- }
-
- // store [path/image name.jpg] to train.txt
- auto it = std::find(difference_filenames.begin(), difference_filenames.end(), filename_without_ext);
- if (it != difference_filenames.end())
- {
- ofs_train << images_path << "/" << jpg_filename << std::endl;
- ofs_train.flush();
-
- size_t new_size = std::remove(difference_filenames.begin(), difference_filenames.end(), filename_without_ext) -
- difference_filenames.begin();
- difference_filenames.resize(new_size);
- }
- }
- catch (...) { std::cout << " Exception when try to write txt-file \n"; }
- }
-
- // show preview images
- for (size_t i = 0; i < preview_number && (i + trackbar_value) < jpg_filenames_path.size(); ++i)
- {
- Mat img = imread(jpg_filenames_path[trackbar_value + i]);
- // check if the image has been loaded successful to prevent crash
- if (img.cols == 0)
- {
- continue;
- }
- resize(img, preview, preview.size());
- int const x_shift = i*preview.cols + prev_img_rect.width;
- Rect rect_dst(Point2i(x_shift, 0), preview.size());
- Mat dst_roi = frame(rect_dst);
- preview.copyTo(dst_roi);
- //rectangle(frame, rect_dst, Scalar(200, 150, 200), 2);
- putText(dst_roi, jpg_filenames[trackbar_value + i], Point2i(0, 10), FONT_HERSHEY_COMPLEX_SMALL, 0.5, Scalar::all(255));
-
- if (i == 0)
- {
- optflow_img = img;
- resize(img, full_image, full_rect_dst.size());
- full_image.copyTo(full_image_roi);
- current_img_size = img.size();
-
- try {
- std::string const jpg_filename = jpg_filenames[trackbar_value];
- std::string const txt_filename = jpg_filename.substr(0, jpg_filename.find_last_of(".")) + ".txt";
- //std::cout << (images_path + "/" + txt_filename) << std::endl;
- std::ifstream ifs(images_path + "/" + txt_filename);
- if (copy_previous_marks) copy_previous_marks = false;
- else if (tracker_copy_previous_marks) {
- tracker_copy_previous_marks = false;
- current_coord_vec = tracker_optflow.tracking_flow(img, false);
- }
- else current_coord_vec.clear();
-
- for (std::string line; getline(ifs, line);)
- {
- std::stringstream ss(line);
- coord_t coord;
- coord.id = -1;
- ss >> coord.id;
- if (coord.id < 0) continue;
- float relative_coord[4] = { -1, -1, -1, -1 }; // rel_center_x, rel_center_y, rel_width, rel_height
- for (size_t i = 0; i < 4; i++) if(!(ss >> relative_coord[i])) continue;
- for (size_t i = 0; i < 4; i++) if (relative_coord[i] < 0) continue;
- coord.abs_rect.x = (relative_coord[0] - relative_coord[2] / 2) * (float)full_image_roi.cols;
- coord.abs_rect.y = (relative_coord[1] - relative_coord[3] / 2) * (float)full_image_roi.rows;
- coord.abs_rect.width = relative_coord[2] * (float)full_image_roi.cols;
- coord.abs_rect.height = relative_coord[3] * (float)full_image_roi.rows;
-
- current_coord_vec.push_back(coord);
- }
- }
- catch (...) { std::cout << " Exception when try to read txt-file \n"; }
- }
-
- std::string const jpg_filename = jpg_filenames[trackbar_value + i];
- std::string const filename_without_ext = jpg_filename.substr(0, jpg_filename.find_last_of("."));
- // green check-mark on the preview image if there is a lebel txt-file for this image
- if (!std::binary_search(difference_filenames.begin(), difference_filenames.end(), filename_without_ext))
- {
- line(dst_roi, Point2i(80, 88), Point2i(85, 93), Scalar(20, 70, 20), 5);
- line(dst_roi, Point2i(85, 93), Point2i(93, 85), Scalar(20, 70, 20), 5);
-
- line(dst_roi, Point2i(80, 88), Point2i(85, 93), Scalar(50, 200, 100), 2);
- line(dst_roi, Point2i(85, 93), Point2i(93, 85), Scalar(50, 200, 100), 2);
- }
-
- }
- std::cout << " trackbar_value = " << trackbar_value << std::endl;
-
- old_trackbar_value = trackbar_value;
-
- marks_changed = false;
-
- rectangle(frame, prev_img_rect, Scalar(100, 100, 100), CV_FILLED);
- rectangle(frame, next_img_rect, Scalar(100, 100, 100), CV_FILLED);
- }
-
- trackbar_value = min(max(0, trackbar_value), (int)jpg_filenames_path.size() - 1);
-
- // highlight prev img
- for (size_t i = 0; i < preview_number && (i + trackbar_value) < jpg_filenames_path.size(); ++i)
- {
- int const x_shift = i*preview.cols + prev_img_rect.width;
- Rect rect_dst(Point2i(x_shift, 0), Size(preview.cols - 2, preview.rows));
- Scalar color(100, 70, 100);
- if (i == 0) color = Scalar(250, 120, 150);
- if (y_end < preview.rows && i == (x_end - prev_img_rect.width) / preview.cols) color = Scalar(250, 200, 200);
- rectangle(frame, rect_dst, color, 2);
- }
-
- if (undo) {
- undo = false;
- if(current_coord_vec.size() > 0) {
- full_image.copyTo(full_image_roi);
- current_coord_vec.pop_back();
- }
- }
-
- // marking is completed (left mouse button is OFF)
- if (selected)
- {
- selected = false;
- full_image.copyTo(full_image_roi);
-
- if (y_end < preview.rows && x_end > prev_img_rect.width && x_end < (full_image.cols - prev_img_rect.width) &&
- y_start < preview.rows)
- {
- int const i = (x_end - prev_img_rect.width) / preview.cols;
- trackbar_value += i;
- }
- else if (y_end >= preview.rows)
- {
- if (next_by_click) {
- ++trackbar_value;
- current_coord_vec.clear();
- }
-
- Rect selected_rect(
- Point2i((int)min(x_start, x_end), (int)min(y_start, y_end)),
- Size(x_size, y_size));
-
- selected_rect &= full_rect_dst;
- selected_rect.y -= (int)prev_img_rect.height;
-
- coord_t coord;
- coord.abs_rect = selected_rect;
- coord.id = current_obj_id;
- current_coord_vec.push_back(coord);
-
- marks_changed = true;
- }
- }
-
- std::string current_synset_name;
- if (current_obj_id < synset_txt.size()) current_synset_name = " - " + synset_txt[current_obj_id];
-
- // show X and Y coords of mouse
- if (show_mouse_coords) {
- full_image.copyTo(full_image_roi);
- int const x_inside = std::min((int)x_end, full_image_roi.cols);
- int const y_inside = std::min(std::max(0, y_end - (int)prev_img_rect.height), full_image_roi.rows);
- float const relative_center_x = (float)(x_inside) / full_image_roi.cols;
- float const relative_center_y = (float)(y_inside) / full_image_roi.rows;
- int const abs_x = relative_center_x*current_img_size.width;
- int const abs_y = relative_center_y*current_img_size.height;
- char buff[100];
- snprintf(buff, 100, "Abs: %d x %d Rel: %.3f x %.3f", abs_x, abs_y, relative_center_x, relative_center_y);
- //putText(full_image_roi, buff, Point2i(800, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(50, 10, 10), 3);
- putText(full_image_roi, buff, Point2i(800, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(100, 50, 50), 2);
- putText(full_image_roi, buff, Point2i(800, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(220, 120, 120), 1);
- }
- else
- {
- full_image.copyTo(full_image_roi);
- //std::string text = "Show mouse coordinates - press M";
- //putText(full_image_roi, text, Point2i(800, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(100, 50, 50), 2);
- //putText(full_image_roi, text, Point2i(800, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(220, 120, 120), 1);
- }
-
- // marking is in progress (left mouse button is ON)
- if (draw_select)
- {
- if (add_id_img != 0) trackbar_value += add_id_img;
-
- if (y_start >= preview.rows)
- {
- //full_image.copyTo(full_image_roi);
- Rect selected_rect(
- Point2i(max(0, (int)min(x_start, x_end)), max(preview.rows, (int)min(y_start, y_end))),
- Point2i(max(x_start, x_end), max(y_start, y_end)));
- rectangle(frame, selected_rect, Scalar(150, 200, 150));
-
- if (show_mark_class)
- {
- putText(frame, std::to_string(current_obj_id) + current_synset_name,
- selected_rect.tl() + Point2i(2, 22), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(150, 200, 150), 2);
- }
- }
- }
-
- // Draw crosshair
- {
- const int offset = preview.rows; // Vertical offset
-
- // Only draw crosshair, if mouse is over image area
- if (y_end >= offset)
- {
- const bool bit_high = true;
- const bool bit_low = false;
- const int mouse_offset = 25;
- const int ver_min = draw_select ? std::min(x_end - mouse_offset, x_start - mouse_offset) : x_end - mouse_offset;
- const int ver_max = draw_select ? std::max(x_end + mouse_offset, x_start + mouse_offset) : x_end + mouse_offset;
- const int hor_min = draw_select ? std::min(y_end - mouse_offset, y_start - mouse_offset) : y_end - mouse_offset;
- const int hor_max = draw_select ? std::max(y_end + mouse_offset, y_start + mouse_offset) : y_end + mouse_offset;
-
- // Draw crosshair onto empty canvas (draws high bits on low-bit-canvas)
- cv::Mat crosshair_mask(frame.size(), CV_8UC1, cv::Scalar(bit_low));
- cv::line(crosshair_mask, cv::Point(0, y_end), cv::Point(ver_min, y_end), cv::Scalar(bit_high)); // Horizontal, left to mouse
- cv::line(crosshair_mask, cv::Point(ver_max, y_end), cv::Point(crosshair_mask.size().width, y_end), cv::Scalar(bit_high)); // Horizontal, mouse to right
- cv::line(crosshair_mask, cv::Point(x_end, offset), cv::Point(x_end, std::max(offset, hor_min)), cv::Scalar(bit_high)); // Vertical, top to mouse
- cv::line(crosshair_mask, cv::Point(x_end, hor_max), cv::Point(x_end, crosshair_mask.size().height), cv::Scalar(bit_high)); // Vertical, mouse to bottom
-
- // Draw crosshair onto frame copy
- cv::Mat crosshair_frame(frame.size(), frame.type());
- frame.copyTo(crosshair_frame);
- cv::bitwise_not(crosshair_frame, crosshair_frame, crosshair_mask);
-
- // Fade-in frame copy with crosshair into original frame (for alpha)
- const double alpha = 0.7;
- cv::addWeighted(crosshair_frame, alpha, frame, 1 - alpha, 0.0, frame);
- }
- }
-
- // remove all labels from this image
- if (clear_marks == true)
- {
- clear_marks = false;
- marks_changed = true;
- full_image.copyTo(full_image_roi);
- current_coord_vec.clear();
- }
-
-
- if (old_current_obj_id != current_obj_id)
- {
- full_image.copyTo(full_image_roi);
- old_current_obj_id = current_obj_id;
- setTrackbarPos(trackbar_name_2, window_name, current_obj_id);
- }
-
- int selected_id = -1;
- // draw all labels
- //for (auto &i : current_coord_vec)
- for(size_t k = 0; k < current_coord_vec.size(); ++k)
- {
- auto &i = current_coord_vec.at(k);
- std::string synset_name;
- if (i.id < synset_txt.size()) synset_name = " - " + synset_txt[i.id];
-
- int offset = i.id * 25;
- int red = (offset + 0) % 255 * ((i.id + 2) % 3);
- int green = (offset + 70) % 255 * ((i.id + 1) % 3);
- int blue = (offset + 140) % 255 * ((i.id + 0) % 3);
- Scalar color_rect(red, green, blue); // Scalar color_rect(100, 200, 100);
-
- // selected rect
- if (i.abs_rect.x < x_end && (i.abs_rect.x + i.abs_rect.width) > x_end &&
- (i.abs_rect.y + preview.rows) < y_end && (i.abs_rect.y + i.abs_rect.height + preview.rows) > y_end)
- {
- if (selected_id < 0) {
- color_rect = Scalar(100, 200, 300);
- selected_id = k;
- rectangle(full_image_roi, i.abs_rect, color_rect, mark_line_width*2);
- }
- }
-
- if (show_mark_class)
- {
- putText(full_image_roi, std::to_string(i.id) + synset_name,
- i.abs_rect.tl() + Point2f(2, 22), FONT_HERSHEY_SIMPLEX, 0.8, color_rect, 2);
- }
-
- rectangle(full_image_roi, i.abs_rect, color_rect, mark_line_width);
- }
-
- // remove selected rect
- if (delete_selected) {
- delete_selected = false;
- if (selected_id >= 0) current_coord_vec.erase(current_coord_vec.begin() + selected_id);
- }
-
- // show moving rect
- if (right_button_click == true)
- {
- if (move_rect_id < 0) move_rect_id = selected_id;
-
- int x_delta = x_end - x_start;
- int y_delta = y_end - y_start;
- auto rect = current_coord_vec[move_rect_id].abs_rect;
- rect.x += x_delta;
- rect.y += y_delta;
-
- Scalar color_rect = Scalar(300, 200, 100);
- rectangle(full_image_roi, rect, color_rect, mark_line_width);
- }
-
- // complete moving label rect
- if (move_rect && move_rect_id >= 0) {
- int x_delta = x_end - x_start;
- int y_delta = y_end - y_start;
- current_coord_vec[move_rect_id].abs_rect.x += x_delta;
- current_coord_vec[move_rect_id].abs_rect.y += y_delta;
- move_rect = false;
- move_rect_id = -1;
- }
-
-
- if (next_by_click) {
- putText(full_image_roi, "Mode: 1 mark per image (next by click)",
- Point2i(850, 20), FONT_HERSHEY_SIMPLEX, 0.6, Scalar(50, 170, 100), 2);
- }
-
-
- {
- std::string const obj_str = "Object id: " + std::to_string(current_obj_id) + current_synset_name;
-
- putText(full_image_roi, obj_str, Point2i(0, 21), FONT_HERSHEY_DUPLEX, 0.8, Scalar(10, 50, 10), 3);
- putText(full_image_roi, obj_str, Point2i(0, 21), FONT_HERSHEY_DUPLEX, 0.8, Scalar(20, 120, 60), 2);
- putText(full_image_roi, obj_str, Point2i(0, 21), FONT_HERSHEY_DUPLEX, 0.8, Scalar(50, 200, 100), 1);
- }
-
- if (show_help)
- {
- putText(full_image_roi,
- "<- prev_img -> next_img c - clear_marks n - one_object_per_img 0-9 - obj_id m - show coords ESC - exit",
- Point2i(0, 45), FONT_HERSHEY_SIMPLEX, 0.6, Scalar(50, 10, 10), 2);
- putText(full_image_roi,
- "w - line width k - hide obj_name p - copy previous o - track objects r - delete selected R-mouse - move box", // h - disable help",
- Point2i(0, 80), FONT_HERSHEY_SIMPLEX, 0.6, Scalar(50, 10, 10), 2);
- }
- else
- {
- putText(full_image_roi,
- "h - show help",
- Point2i(0, 45), FONT_HERSHEY_SIMPLEX, 0.6, Scalar(50, 10, 10), 2);
- }
-
-
- // arrows
- {
- Scalar prev_arrow_color(200, 150, 100);
- Scalar next_arrow_color = prev_arrow_color;
- if (prev_img_rect.contains(Point2i(x_end, y_end))) prev_arrow_color = Scalar(220, 190, 170);
- if (next_img_rect.contains(Point2i(x_end, y_end))) next_arrow_color = Scalar(220, 190, 170);
-
- std::vector prev_triangle_pts = { Point(5, 50), Point(40, 90), Point(40, 10), Point(5, 50) };
- Mat prev_roi = frame(prev_img_rect);
- line(prev_roi, prev_triangle_pts[0], prev_triangle_pts[1], prev_arrow_color, 5);
- line(prev_roi, prev_triangle_pts[1], prev_triangle_pts[2], prev_arrow_color, 5);
- line(prev_roi, prev_triangle_pts[2], prev_triangle_pts[3], prev_arrow_color, 5);
- line(prev_roi, prev_triangle_pts[3], prev_triangle_pts[0], prev_arrow_color, 5);
-
- std::vector next_triangle_pts = { Point(10, 10), Point(10, 90), Point(45, 50), Point(10, 10) };
- Mat next_roi = frame(next_img_rect);
- line(next_roi, next_triangle_pts[0], next_triangle_pts[1], next_arrow_color, 5);
- line(next_roi, next_triangle_pts[1], next_triangle_pts[2], next_arrow_color, 5);
- line(next_roi, next_triangle_pts[2], next_triangle_pts[3], next_arrow_color, 5);
- line(next_roi, next_triangle_pts[3], next_triangle_pts[0], next_arrow_color, 5);
- }
-
- imshow(window_name, frame);
-
-#ifndef CV_VERSION_EPOCH
- int pressed_key = cv::waitKeyEx(20); // OpenCV 3.x
-#else
- int pressed_key = cv::waitKey(20); // OpenCV 2.x
-#endif
-
- if (pressed_key >= 0)
- for (int i = 0; i < 5; ++i) cv::waitKey(1);
-
- if (exit_flag) break; // exit after saving
- if (pressed_key == 27 || pressed_key == 1048603) exit_flag = true;// break; // ESC - save & exit
-
- if (pressed_key >= '0' && pressed_key <= '9') current_obj_id = pressed_key - '0'; // 0 - 9
- if (pressed_key >= 1048624 && pressed_key <= 1048633) current_obj_id = pressed_key - 1048624; // 0 - 9
-
- switch (pressed_key)
- {
- //case 'z': // z
- //case 1048698: // z
- // undo = true;
- // break;
-
- case 'p': // p
- case 1048688: // p
- copy_previous_marks = 1;
- ++trackbar_value;
- break;
-
- case 'o': // o
- case 1048687: // o
- tracker_copy_previous_marks = 1;
- ++trackbar_value;
- break;
-
- case 32: // SPACE
- case 1048608: // SPACE
- ++trackbar_value;
- break;
-
- case 2424832: // <-
- case 65361: // <-
- case 91: // [
- --trackbar_value;
- break;
- case 2555904: // ->
- case 65363: // ->
- case 93: // ]
- ++trackbar_value;
- break;
- case 'c': // c
- case 1048675: // c
- clear_marks = true;
- break;
- case 'm': // m
- case 1048685: // m
- show_mouse_coords = !show_mouse_coords;
- full_image.copyTo(full_image_roi);
- break;
- case 'n': // n
- case 1048686: // n
- next_by_click = !next_by_click;
- full_image.copyTo(full_image_roi);
- break;
- case 'w': // w
- case 1048695: // w
- mark_line_width = mark_line_width % MAX_MARK_LINE_WIDTH + 1;
- break;
- case 'h': // h
- case 1048680: // h
- show_help = !show_help;
- break;
- case 'k':
- case 1048683:
- show_mark_class = !show_mark_class;
- break;
- case 'r': // r
- case 1048690: // r
- delete_selected = true;
- break;
- default:
- ;
- }
-
- if(tracker_copy_previous_marks)
- tracker_optflow.update_tracking_flow(optflow_img, current_coord_vec);
-
- //if (pressed_key >= 0) std::cout << "pressed_key = " << (int)pressed_key << std::endl;
-
- } while (true);
-
- }
- catch (std::exception &e) {
- std::cout << "exception: " << e.what() << std::endl;
- }
- catch (...) {
- std::cout << "unknown exception \n";
- }
-
- return 0;
-}
diff --git a/run.cmd b/run.cmd
new file mode 100755
index 00000000..4d2b645b
--- /dev/null
+++ b/run.cmd
@@ -0,0 +1,3 @@
+echo How to start marking bounging boxes to create training sets for Yolo
+
+yolo_mark.exe data/img data/train.txt data/obj.names
diff --git a/run.sh b/run.sh
new file mode 100755
index 00000000..693d4869
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo "How to start marking bounding boxes to create training sets for Yolo"
+
+./yolo_mark data/img data/train.txt data/obj.names
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 00000000..ca527dc7
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,962 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+//#include
+#include
+
+#ifndef CV_VERSION_EPOCH
+#include "opencv2/videoio/videoio.hpp"
+#define OPENCV_VERSION CVAUX_STR(CV_VERSION_MAJOR)"" CVAUX_STR(CV_VERSION_MINOR)"" CVAUX_STR(CV_VERSION_REVISION) OCV_D
+#else
+#define OPENCV_VERSION CVAUX_STR(CV_VERSION_EPOCH)"" CVAUX_STR(CV_VERSION_MAJOR)"" CVAUX_STR(CV_VERSION_MINOR) OCV_D
+#endif
+
+// label coordinates
+struct coord_t {
+ cv::Rect_ abs_rect;
+ int id;
+};
+
+class Tracker_optflow {
+ public:
+ const int flow_error;
+
+ Tracker_optflow(int win_size = 15, int max_level = 3, int iterations = 8000, int _flow_error = -1)
+ : flow_error((_flow_error > 0) ? _flow_error : (win_size * 4))
+ {
+ sync_PyrLKOpticalFlow = cv::SparsePyrLKOpticalFlow::create();
+ sync_PyrLKOpticalFlow->setWinSize(cv::Size(win_size, win_size)); // 9, 15, 21, 31
+ sync_PyrLKOpticalFlow->setMaxLevel(max_level); // +- 3 pt
+ }
+
+ // just to avoid extra allocations
+ cv::Mat dst_grey;
+ cv::Mat prev_pts_flow, cur_pts_flow;
+ cv::Mat status, err;
+
+ cv::Mat src_grey; // used in both functions
+ cv::Ptr sync_PyrLKOpticalFlow;
+
+ std::vector cur_bbox_vec;
+ std::vector good_bbox_vec_flags;
+
+ void update_cur_bbox_vec(std::vector _cur_bbox_vec)
+ {
+ cur_bbox_vec = _cur_bbox_vec;
+ good_bbox_vec_flags = std::vector(cur_bbox_vec.size(), true);
+ cv::Mat prev_pts, cur_pts_flow;
+
+ for (auto& i : cur_bbox_vec) {
+ float x_center = (i.abs_rect.x + i.abs_rect.width / 2.0F);
+ float y_center = (i.abs_rect.y + i.abs_rect.height / 2.0F);
+ prev_pts.push_back(cv::Point2f(x_center, y_center));
+ }
+
+ if (prev_pts.rows == 0)
+ prev_pts_flow = cv::Mat();
+ else
+ cv::transpose(prev_pts, prev_pts_flow);
+ }
+
+ void update_tracking_flow(cv::Mat new_src_mat, std::vector _cur_bbox_vec)
+ {
+ if (new_src_mat.channels() == 1) {
+ src_grey = new_src_mat.clone();
+ } else if (new_src_mat.channels() == 3) {
+ cv::cvtColor(new_src_mat, src_grey, cv::COLOR_BGR2GRAY, 1);
+ } else if (new_src_mat.channels() == 4) {
+ cv::cvtColor(new_src_mat, src_grey, cv::COLOR_BGRA2GRAY, 1);
+ } else {
+ std::cerr << " Warning: new_src_mat.channels() is not: 1, 3 or 4. It is = " << new_src_mat.channels() << " \n";
+ return;
+ }
+ update_cur_bbox_vec(_cur_bbox_vec);
+ }
+
+ std::vector tracking_flow(cv::Mat new_dst_mat, bool check_error = true)
+ {
+ if (sync_PyrLKOpticalFlow.empty()) {
+ std::cout << "sync_PyrLKOpticalFlow isn't initialized \n";
+ return cur_bbox_vec;
+ }
+
+ cv::cvtColor(new_dst_mat, dst_grey, cv::COLOR_BGR2GRAY, 1);
+
+ if (src_grey.rows != dst_grey.rows || src_grey.cols != dst_grey.cols) {
+ src_grey = dst_grey.clone();
+ //std::cerr << " Warning: src_grey.rows != dst_grey.rows || src_grey.cols != dst_grey.cols \n";
+ return cur_bbox_vec;
+ }
+
+ if (prev_pts_flow.cols < 1) {
+ return cur_bbox_vec;
+ }
+
+ ////sync_PyrLKOpticalFlow_gpu.sparse(src_grey_gpu, dst_grey_gpu, prev_pts_flow_gpu, cur_pts_flow_gpu, status_gpu, &err_gpu); // OpenCV 2.4.x
+ sync_PyrLKOpticalFlow->calc(src_grey, dst_grey, prev_pts_flow, cur_pts_flow, status, err); // OpenCV 3.x
+
+ dst_grey.copyTo(src_grey);
+
+ std::vector result_bbox_vec;
+
+ if (err.rows == cur_bbox_vec.size() && status.rows == cur_bbox_vec.size()) {
+ for (size_t i = 0; i < cur_bbox_vec.size(); ++i) {
+ cv::Point2f cur_key_pt = cur_pts_flow.at(0, i);
+ cv::Point2f prev_key_pt = prev_pts_flow.at(0, i);
+
+ float moved_x = cur_key_pt.x - prev_key_pt.x;
+ float moved_y = cur_key_pt.y - prev_key_pt.y;
+
+ if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i])
+ if (err.at(0, i) < flow_error && status.at(0, i) != 0 && ((float)cur_bbox_vec[i].abs_rect.x + moved_x) > 0 && ((float)cur_bbox_vec[i].abs_rect.y + moved_y) > 0) {
+ cur_bbox_vec[i].abs_rect.x += moved_x; // +0.5;
+ cur_bbox_vec[i].abs_rect.y += moved_y; // +0.5;
+ result_bbox_vec.push_back(cur_bbox_vec[i]);
+ } else
+ good_bbox_vec_flags[i] = false;
+ else
+ good_bbox_vec_flags[i] = false;
+
+ //if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]);
+ }
+ }
+
+ prev_pts_flow = cur_pts_flow.clone();
+
+ return result_bbox_vec;
+ }
+};
+
+std::atomic right_button_click;
+std::atomic move_rect_id;
+std::atomic move_rect;
+std::atomic clear_marks;
+std::atomic copy_previous_marks(false);
+std::atomic tracker_copy_previous_marks(false);
+
+std::atomic show_help;
+std::atomic exit_flag(false);
+
+std::atomic mark_line_width(2); // default mark line width is 2 pixels.
+const int MAX_MARK_LINE_WIDTH = 3;
+std::atomic show_mark_class(true);
+std::atomic delete_selected(false);
+
+std::atomic x_start, y_start;
+std::atomic x_end, y_end;
+std::atomic x_size, y_size;
+std::atomic draw_select, selected, undo;
+
+std::atomic add_id_img;
+cv::Rect prev_img_rect(0, 0, 50, 100);
+cv::Rect next_img_rect(1280 - 50, 0, 50, 100);
+
+void callback_mouse_click(int event, int x, int y, int flags, void* user_data)
+{
+ if (event == cv::EVENT_LBUTTONDBLCLK) {
+ std::cout << "cv::EVENT_LBUTTONDBLCLK \n";
+ } else if (event == cv::EVENT_LBUTTONDOWN) {
+ draw_select = true;
+ selected = false;
+ x_start = x;
+ y_start = y;
+
+ if (prev_img_rect.contains(cv::Point2i(x, y)))
+ add_id_img = -1;
+ else if (next_img_rect.contains(cv::Point2i(x, y)))
+ add_id_img = 1;
+ else
+ add_id_img = 0;
+ //std::cout << "cv::EVENT_LBUTTONDOWN \n";
+ } else if (event == cv::EVENT_LBUTTONUP) {
+ x_size = std::abs(x - x_start);
+ y_size = std::abs(y - y_start);
+ x_end = std::max(x, 0);
+ y_end = std::max(y, 0);
+ draw_select = false;
+ selected = true;
+ //std::cout << "cv::EVENT_LBUTTONUP \n";
+ } else if (event == cv::EVENT_RBUTTONDOWN) {
+ right_button_click = true;
+
+ x_start = x;
+ y_start = y;
+ std::cout << "cv::EVENT_RBUTTONDOWN \n";
+ } else if (event == cv::EVENT_RBUTTONUP) {
+ right_button_click = false;
+ move_rect = true;
+ }
+ if (event == cv::EVENT_RBUTTONDBLCLK) {
+ std::cout << "cv::EVENT_RBUTTONDBLCLK \n";
+ } else if (event == cv::EVENT_MOUSEMOVE) {
+ x_end = std::max(x, 0);
+ y_end = std::max(y, 0);
+ }
+}
+
+class comma : public std::numpunct {
+ public:
+ comma()
+ : std::numpunct()
+ {
+ }
+
+ protected:
+ char do_decimal_point() const { return '.'; }
+};
+
+int main(int argc, char* argv[])
+{
+
+ try {
+ std::locale loccomma(std::locale::classic(), new comma);
+ std::locale::global(loccomma);
+
+ std::string images_path = "./";
+
+ if (argc >= 2) {
+ images_path = std::string(argv[1]); // path to images, train and synset
+ } else {
+ std::cout << "Usage: [path_to_images] [train.txt] [obj.names] \n";
+ return 0;
+ }
+
+ std::string train_filename = images_path + "train.txt";
+ std::string synset_filename = images_path + "obj.names";
+
+ if (argc >= 3) {
+ train_filename = std::string(argv[2]); // file containing: list of images
+ }
+
+ if (argc >= 4) {
+ synset_filename = std::string(argv[3]); // file containing: object names
+ }
+
+ // optical flow tracker
+ Tracker_optflow tracker_optflow;
+ cv::Mat optflow_img;
+
+ // capture frames from video file - 1 frame per 3 seconds of video
+ if (argc >= 4 && (train_filename == "cap_video" || train_filename == "cap_video_backward")) {
+ const std::string videofile = synset_filename;
+ cv::VideoCapture cap(videofile);
+#ifndef CV_VERSION_EPOCH // OpenCV 3.x
+ const int fps = cap.get(cv::CAP_PROP_FPS);
+#else // OpenCV 2.x
+ const int fps = cap.get(CV_CAP_PROP_FPS);
+#endif
+ int frame_counter = 0, image_counter = 0;
+ int backward = (train_filename == "cap_video_backward") ? 1 : 0;
+ if (backward)
+ image_counter = 99999999; // 99M
+ float save_each_frames = 50;
+ if (argc >= 5)
+ save_each_frames = std::stoul(std::string(argv[4]));
+
+ int pos_filename = 0;
+ if ((1 + videofile.find_last_of("\\")) < videofile.length())
+ pos_filename = 1 + videofile.find_last_of("\\");
+ if ((1 + videofile.find_last_of("/")) < videofile.length())
+ pos_filename = std::max(pos_filename, 1 + (int)videofile.find_last_of("/"));
+ std::string const filename = videofile.substr(pos_filename);
+ std::string const filename_without_ext = filename.substr(0, filename.find_last_of("."));
+
+ for (cv::Mat frame; cap >> frame, cap.isOpened() && !frame.empty();) {
+ cv::imshow("video cap to frames", frame);
+#ifndef CV_VERSION_EPOCH
+ int pressed_key = cv::waitKeyEx(20); // OpenCV 3.x
+#else
+ int pressed_key = cv::waitKey(20); // OpenCV 2.x
+#endif
+ if (pressed_key == 27 || pressed_key == 1048603)
+ break; // ESC - exit (OpenCV 2.x / 3.x)
+ if (frame_counter++ >= save_each_frames) { // save frame for each 3 second
+ frame_counter = 0;
+ std::stringstream image_counter_ss;
+ image_counter_ss << std::setw(8) << std::setfill('0') << image_counter;
+ if (backward)
+ image_counter--;
+ else
+ image_counter++;
+ std::string img_name = images_path + "/" + filename_without_ext + "_" + image_counter_ss.str() + ".jpg";
+ std::cout << "saved " << img_name << std::endl;
+ cv::imwrite(img_name, frame);
+ }
+ }
+ exit(0);
+ }
+
+ bool show_mouse_coords = false;
+ std::vector filenames_in_folder;
+ //glob(images_path, filenames_in_folder); // void glob(String pattern, std::vector& result, bool recursive = false);
+ cv::String images_path_cv = images_path;
+ std::vector filenames_in_folder_cv;
+ cv::glob(images_path_cv, filenames_in_folder_cv); // void glob(String pattern, std::vector& result, bool recursive = false);
+ for (auto& i : filenames_in_folder_cv)
+ filenames_in_folder.push_back(i);
+
+ std::vector jpg_filenames_path;
+ std::vector jpg_filenames;
+ std::vector jpg_filenames_without_ext;
+ std::vector image_ext;
+ std::vector txt_filenames;
+ std::vector jpg_in_train;
+ std::vector synset_txt;
+
+ // image-paths to txt-paths
+ for (auto& i : filenames_in_folder) {
+ int pos_filename = 0;
+ if ((1 + i.find_last_of("\\")) < i.length())
+ pos_filename = 1 + i.find_last_of("\\");
+ if ((1 + i.find_last_of("/")) < i.length())
+ pos_filename = std::max(pos_filename, 1 + (int)i.find_last_of("/"));
+
+ std::string const filename = i.substr(pos_filename);
+ std::string const ext = i.substr(i.find_last_of(".") + 1);
+ std::string const filename_without_ext = filename.substr(0, filename.find_last_of("."));
+
+ if (ext == "jpg" || ext == "JPG" || ext == "jpeg" || ext == "JPEG" || ext == "bmp" || ext == "BMP" || ext == "png" || ext == "PNG" || ext == "ppm" || ext == "PPM") {
+ jpg_filenames_without_ext.push_back(filename_without_ext);
+ image_ext.push_back(ext);
+ jpg_filenames.push_back(filename);
+ jpg_filenames_path.push_back(i);
+ }
+ if (ext == "txt") {
+ txt_filenames.push_back(filename_without_ext);
+ }
+ }
+ std::sort(jpg_filenames.begin(), jpg_filenames.end());
+ std::sort(jpg_filenames_path.begin(), jpg_filenames_path.end());
+ std::sort(txt_filenames.begin(), txt_filenames.end());
+
+ if (jpg_filenames.size() == 0) {
+ std::cout << "Error: Image files not found by path: " << images_path << std::endl;
+ return 0;
+ }
+
+ // check whether there are files with the same names (but different extensions)
+ {
+ auto sorted_names_without_ext = jpg_filenames_without_ext;
+ std::sort(sorted_names_without_ext.begin(), sorted_names_without_ext.end());
+ for (size_t i = 1; i < sorted_names_without_ext.size(); ++i) {
+ if (sorted_names_without_ext[i - 1] == sorted_names_without_ext[i]) {
+ std::cout << "Error: Can't create " << sorted_names_without_ext[i] << ".txt file for several images with different extensions but with the same filename: "
+ << sorted_names_without_ext[i] << std::endl;
+ // print duplicate images
+ for (size_t k = 0; k < jpg_filenames_without_ext.size(); ++k) {
+ if (jpg_filenames_without_ext[k] == sorted_names_without_ext[i]) {
+ std::cout << jpg_filenames_without_ext[k] << "." << image_ext[k] << std::endl;
+ }
+ }
+ return 0;
+ }
+ }
+ }
+
+ // intersect jpg & txt
+ std::vector intersect_filenames(jpg_filenames.size());
+ std::vector difference_filenames(jpg_filenames.size());
+ std::vector intersect_ext;
+ std::vector difference_ext;
+
+ auto dif_it_end = std::set_difference(jpg_filenames_without_ext.begin(), jpg_filenames_without_ext.end(),
+ txt_filenames.begin(), txt_filenames.end(),
+ difference_filenames.begin());
+ difference_filenames.resize(dif_it_end - difference_filenames.begin());
+
+ auto inter_it_end = std::set_intersection(jpg_filenames_without_ext.begin(), jpg_filenames_without_ext.end(),
+ txt_filenames.begin(), txt_filenames.end(),
+ intersect_filenames.begin());
+ intersect_filenames.resize(inter_it_end - intersect_filenames.begin());
+
+ // get intersect extensions for intersect_filenames
+ for (auto& i : intersect_filenames) {
+ size_t ext_index = find(jpg_filenames_without_ext.begin(), jpg_filenames_without_ext.end(), i) - jpg_filenames_without_ext.begin();
+ intersect_ext.push_back(image_ext[ext_index]);
+ }
+
+ // get difference extensions for intersect_filenames
+ for (auto& i : difference_filenames) {
+ size_t ext_index = find(jpg_filenames_without_ext.begin(), jpg_filenames_without_ext.end(), i) - jpg_filenames_without_ext.begin();
+ difference_ext.push_back(image_ext[ext_index]);
+ }
+
+ txt_filenames.clear();
+ for (auto& i : intersect_filenames) {
+ txt_filenames.push_back(i + ".txt");
+ }
+
+ int image_list_count = std::max(1, (int)jpg_filenames_path.size() - 1);
+
+ // store train.txt
+ std::ofstream ofs_train(train_filename, std::ios::out | std::ios::trunc);
+ if (!ofs_train.is_open()) {
+ throw(std::runtime_error("Can't open file: " + train_filename));
+ }
+
+ for (size_t i = 0; i < intersect_filenames.size(); ++i) {
+ ofs_train << images_path << "/" << intersect_filenames[i] << "." << intersect_ext[i] << std::endl;
+ }
+ ofs_train.flush();
+ std::cout << "File opened for output: " << train_filename << std::endl;
+
+ // load synset.txt
+ {
+ std::ifstream ifs(synset_filename);
+ if (!ifs.is_open()) {
+ throw(std::runtime_error("Can't open file: " + synset_filename));
+ }
+
+ for (std::string line; getline(ifs, line);)
+ synset_txt.push_back(line);
+ }
+ std::cout << "File loaded: " << synset_filename << std::endl;
+
+ cv::Mat preview(cv::Size(100, 100), CV_8UC3);
+ cv::Mat full_image(cv::Size(1280, 720), CV_8UC3);
+ cv::Mat frame(cv::Size(full_image.cols, full_image.rows + preview.rows), CV_8UC3);
+
+ cv::Rect full_rect_dst(cv::Point2i(0, preview.rows), cv::Size(frame.cols, frame.rows - preview.rows));
+ cv::Mat full_image_roi = frame(full_rect_dst);
+
+ size_t const preview_number = frame.cols / preview.cols;
+
+ // labels on the current image
+ std::vector current_coord_vec;
+ cv::Size current_img_size;
+
+ std::string const window_name = "Marking images";
+ cv::namedWindow(window_name, cv::WINDOW_NORMAL);
+ cv::resizeWindow(window_name, 1280, 720);
+ cv::imshow(window_name, frame);
+ cv::moveWindow(window_name, 0, 0);
+ cv::setMouseCallback(window_name, callback_mouse_click);
+
+ bool next_by_click = false;
+ bool marks_changed = false;
+
+ int old_trackbar_value = -1, trackbar_value = 0;
+ std::string const trackbar_name = "image num";
+ int tb_res = cv::createTrackbar(trackbar_name, window_name, &trackbar_value, image_list_count);
+
+ int old_current_obj_id = -1, current_obj_id = 0;
+ std::string const trackbar_name_2 = "object id";
+ int const max_object_id = (synset_txt.size() > 0) ? synset_txt.size() : 20;
+ int tb_res_2 = cv::createTrackbar(trackbar_name_2, window_name, ¤t_obj_id, max_object_id);
+
+ do {
+ //trackbar_value = min(max(0, trackbar_value), (int)jpg_filenames_path.size() - 1);
+
+ // selected new image
+ if (old_trackbar_value != trackbar_value || exit_flag) {
+ trackbar_value = std::min(std::max(0, trackbar_value), (int)jpg_filenames_path.size() - 1);
+ cv::setTrackbarPos(trackbar_name, window_name, trackbar_value);
+ frame(cv::Rect(0, 0, frame.cols, preview.rows)) = cv::Scalar::all(0);
+ move_rect_id = -1;
+
+ // save current coords
+ if (old_trackbar_value >= 0) // && current_coord_vec.size() > 0) // Yolo v2 can processes background-image without objects
+ {
+ try {
+ std::string const jpg_filename = jpg_filenames[old_trackbar_value];
+ std::string const filename_without_ext = jpg_filename.substr(0, jpg_filename.find_last_of("."));
+ std::string const txt_filename = filename_without_ext + ".txt";
+ std::string const txt_filename_path = images_path + "/" + txt_filename;
+
+ std::cout << "txt_filename_path = " << txt_filename_path << std::endl;
+
+ std::ofstream ofs(txt_filename_path, std::ios::out | std::ios::trunc);
+ ofs << std::fixed;
+
+ // store coords to [image name].txt
+ for (auto& i : current_coord_vec) {
+ float const relative_center_x = (float)(i.abs_rect.x + i.abs_rect.width / 2) / full_image_roi.cols;
+ float const relative_center_y = (float)(i.abs_rect.y + i.abs_rect.height / 2) / full_image_roi.rows;
+ float const relative_width = (float)i.abs_rect.width / full_image_roi.cols;
+ float const relative_height = (float)i.abs_rect.height / full_image_roi.rows;
+
+ if (relative_width <= 0)
+ continue;
+ if (relative_height <= 0)
+ continue;
+ if (relative_center_x <= 0)
+ continue;
+ if (relative_center_y <= 0)
+ continue;
+
+ ofs << i.id << " " << relative_center_x << " " << relative_center_y << " " << relative_width << " " << relative_height << std::endl;
+ }
+
+ // store [path/image name.jpg] to train.txt
+ auto it = std::find(difference_filenames.begin(), difference_filenames.end(), filename_without_ext);
+ if (it != difference_filenames.end()) {
+ ofs_train << images_path << "/" << jpg_filename << std::endl;
+ ofs_train.flush();
+
+ size_t new_size = std::remove(difference_filenames.begin(), difference_filenames.end(), filename_without_ext) - difference_filenames.begin();
+ difference_filenames.resize(new_size);
+ }
+ } catch (...) {
+ std::cout << " Exception when try to write txt-file \n";
+ }
+ }
+
+ // show preview images
+ for (size_t i = 0; i < preview_number && (i + trackbar_value) < jpg_filenames_path.size(); ++i) {
+ cv::Mat img = cv::imread(jpg_filenames_path[trackbar_value + i]);
+ // check if the image has been loaded successful to prevent crash
+ if (img.cols == 0) {
+ continue;
+ }
+ resize(img, preview, preview.size());
+ int const x_shift = i * preview.cols + prev_img_rect.width;
+ cv::Rect rect_dst(cv::Point2i(x_shift, 0), preview.size());
+ cv::Mat dst_roi = frame(rect_dst);
+ preview.copyTo(dst_roi);
+ //rectangle(frame, rect_dst, Scalar(200, 150, 200), 2);
+ cv::putText(dst_roi, jpg_filenames[trackbar_value + i], cv::Point2i(0, 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.5, cv::Scalar::all(255));
+
+ if (i == 0) {
+ optflow_img = img;
+ resize(img, full_image, full_rect_dst.size());
+ full_image.copyTo(full_image_roi);
+ current_img_size = img.size();
+
+ try {
+ std::string const jpg_filename = jpg_filenames[trackbar_value];
+ std::string const txt_filename = jpg_filename.substr(0, jpg_filename.find_last_of(".")) + ".txt";
+ //std::cout << (images_path + "/" + txt_filename) << std::endl;
+ std::ifstream ifs(images_path + "/" + txt_filename);
+ if (copy_previous_marks)
+ copy_previous_marks = false;
+ else if (tracker_copy_previous_marks) {
+ tracker_copy_previous_marks = false;
+ current_coord_vec = tracker_optflow.tracking_flow(img, false);
+ } else
+ current_coord_vec.clear();
+
+ for (std::string line; getline(ifs, line);) {
+ std::stringstream ss(line);
+ coord_t coord;
+ coord.id = -1;
+ ss >> coord.id;
+ if (coord.id < 0)
+ continue;
+ float relative_coord[4] = { -1, -1, -1, -1 }; // rel_center_x, rel_center_y, rel_width, rel_height
+ for (size_t i = 0; i < 4; i++)
+ if (!(ss >> relative_coord[i]))
+ continue;
+ for (size_t i = 0; i < 4; i++)
+ if (relative_coord[i] < 0)
+ continue;
+ coord.abs_rect.x = (relative_coord[0] - relative_coord[2] / 2) * (float)full_image_roi.cols;
+ coord.abs_rect.y = (relative_coord[1] - relative_coord[3] / 2) * (float)full_image_roi.rows;
+ coord.abs_rect.width = relative_coord[2] * (float)full_image_roi.cols;
+ coord.abs_rect.height = relative_coord[3] * (float)full_image_roi.rows;
+
+ current_coord_vec.push_back(coord);
+ }
+ } catch (...) {
+ std::cout << " Exception when try to read txt-file \n";
+ }
+ }
+
+ std::string const jpg_filename = jpg_filenames[trackbar_value + i];
+ std::string const filename_without_ext = jpg_filename.substr(0, jpg_filename.find_last_of("."));
+ // green check-mark on the preview image if there is a lebel txt-file for this image
+ if (!std::binary_search(difference_filenames.begin(), difference_filenames.end(), filename_without_ext)) {
+ line(dst_roi, cv::Point2i(80, 88), cv::Point2i(85, 93), cv::Scalar(20, 70, 20), 5);
+ line(dst_roi, cv::Point2i(85, 93), cv::Point2i(93, 85), cv::Scalar(20, 70, 20), 5);
+
+ line(dst_roi, cv::Point2i(80, 88), cv::Point2i(85, 93), cv::Scalar(50, 200, 100), 2);
+ line(dst_roi, cv::Point2i(85, 93), cv::Point2i(93, 85), cv::Scalar(50, 200, 100), 2);
+ }
+ }
+ std::cout << " trackbar_value = " << trackbar_value << std::endl;
+
+ old_trackbar_value = trackbar_value;
+
+ marks_changed = false;
+
+#ifndef CV_VERSION_EPOCH // OpenCV 3.x
+ rectangle(frame, prev_img_rect, cv::Scalar(100, 100, 100), cv::FILLED);
+ rectangle(frame, next_img_rect, cv::Scalar(100, 100, 100), cv::FILLED);
+#else // OpenCV 2.x
+ rectangle(frame, prev_img_rect, cv::Scalar(100, 100, 100), CV_FILLED);
+ rectangle(frame, next_img_rect, cv::Scalar(100, 100, 100), CV_FILLED);
+#endif
+ }
+
+ trackbar_value = std::min(std::max(0, trackbar_value), (int)jpg_filenames_path.size() - 1);
+
+ // highlight prev img
+ for (size_t i = 0; i < preview_number && (i + trackbar_value) < jpg_filenames_path.size(); ++i) {
+ int const x_shift = i * preview.cols + prev_img_rect.width;
+ cv::Rect rect_dst(cv::Point2i(x_shift, 0), cv::Size(preview.cols - 2, preview.rows));
+ cv::Scalar color(100, 70, 100);
+ if (i == 0)
+ color = cv::Scalar(250, 120, 150);
+ if (y_end < preview.rows && i == (x_end - prev_img_rect.width) / preview.cols)
+ color = cv::Scalar(250, 200, 200);
+ rectangle(frame, rect_dst, color, 2);
+ }
+
+ if (undo) {
+ undo = false;
+ if (current_coord_vec.size() > 0) {
+ full_image.copyTo(full_image_roi);
+ current_coord_vec.pop_back();
+ }
+ }
+
+ // marking is completed (left mouse button is OFF)
+ if (selected) {
+ selected = false;
+ full_image.copyTo(full_image_roi);
+
+ if (y_end < preview.rows && x_end > prev_img_rect.width && x_end < (full_image.cols - prev_img_rect.width) && y_start < preview.rows) {
+ int const i = (x_end - prev_img_rect.width) / preview.cols;
+ trackbar_value += i;
+ } else if (y_end >= preview.rows) {
+ if (next_by_click) {
+ ++trackbar_value;
+ current_coord_vec.clear();
+ }
+
+ cv::Rect selected_rect(
+ cv::Point2i((int)min(x_start, x_end), (int)min(y_start, y_end)),
+ cv::Size(x_size, y_size));
+
+ selected_rect &= full_rect_dst;
+ selected_rect.y -= (int)prev_img_rect.height;
+
+ coord_t coord;
+ coord.abs_rect = selected_rect;
+ coord.id = current_obj_id;
+ current_coord_vec.push_back(coord);
+
+ marks_changed = true;
+ }
+ }
+
+ std::string current_synset_name;
+ if (current_obj_id < synset_txt.size())
+ current_synset_name = " - " + synset_txt[current_obj_id];
+
+ // show X and Y coords of mouse
+ if (show_mouse_coords) {
+ full_image.copyTo(full_image_roi);
+ int const x_inside = std::min((int)x_end, full_image_roi.cols);
+ int const y_inside = std::min(std::max(0, y_end - (int)prev_img_rect.height), full_image_roi.rows);
+ float const relative_center_x = (float)(x_inside) / full_image_roi.cols;
+ float const relative_center_y = (float)(y_inside) / full_image_roi.rows;
+ int const abs_x = relative_center_x * current_img_size.width;
+ int const abs_y = relative_center_y * current_img_size.height;
+ char buff[100];
+ snprintf(buff, 100, "Abs: %d x %d Rel: %.3f x %.3f", abs_x, abs_y, relative_center_x, relative_center_y);
+ //putText(full_image_roi, buff, Point2i(800, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(50, 10, 10), 3);
+ putText(full_image_roi, buff, cv::Point2i(800, 20), cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(100, 50, 50), 2);
+ putText(full_image_roi, buff, cv::Point2i(800, 20), cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(220, 120, 120), 1);
+ } else {
+ full_image.copyTo(full_image_roi);
+ //std::string text = "Show mouse coordinates - press M";
+ //putText(full_image_roi, text, Point2i(800, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(100, 50, 50), 2);
+ //putText(full_image_roi, text, Point2i(800, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(220, 120, 120), 1);
+ }
+
+ // marking is in progress (left mouse button is ON)
+ if (draw_select) {
+ if (add_id_img != 0)
+ trackbar_value += add_id_img;
+
+ if (y_start >= preview.rows) {
+ //full_image.copyTo(full_image_roi);
+ cv::Rect selected_rect(
+ cv::Point2i(std::max(0, (int)min(x_start, x_end)), std::max(preview.rows, (int)std::min(y_start, y_end))),
+ cv::Point2i(std::max(x_start, x_end), std::max(y_start, y_end)));
+ rectangle(frame, selected_rect, cv::Scalar(150, 200, 150));
+
+ if (show_mark_class) {
+ putText(frame, std::to_string(current_obj_id) + current_synset_name,
+ selected_rect.tl() + cv::Point2i(2, 22), cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(150, 200, 150), 2);
+ }
+ }
+ }
+
+ // Draw crosshair
+ {
+ const int offset = preview.rows; // Vertical offset
+
+ // Only draw crosshair, if mouse is over image area
+ if (y_end >= offset) {
+ const bool bit_high = true;
+ const bool bit_low = false;
+ const int mouse_offset = 25;
+ const int ver_min = draw_select ? std::min(x_end - mouse_offset, x_start - mouse_offset) : x_end - mouse_offset;
+ const int ver_max = draw_select ? std::max(x_end + mouse_offset, x_start + mouse_offset) : x_end + mouse_offset;
+ const int hor_min = draw_select ? std::min(y_end - mouse_offset, y_start - mouse_offset) : y_end - mouse_offset;
+ const int hor_max = draw_select ? std::max(y_end + mouse_offset, y_start + mouse_offset) : y_end + mouse_offset;
+
+ // Draw crosshair onto empty canvas (draws high bits on low-bit-canvas)
+ cv::Mat crosshair_mask(frame.size(), CV_8UC1, cv::Scalar(bit_low));
+ cv::line(crosshair_mask, cv::Point(0, y_end), cv::Point(ver_min, y_end), cv::Scalar(bit_high)); // Horizontal, left to mouse
+ cv::line(crosshair_mask, cv::Point(ver_max, y_end), cv::Point(crosshair_mask.size().width, y_end), cv::Scalar(bit_high)); // Horizontal, mouse to right
+ cv::line(crosshair_mask, cv::Point(x_end, offset), cv::Point(x_end, std::max(offset, hor_min)), cv::Scalar(bit_high)); // Vertical, top to mouse
+ cv::line(crosshair_mask, cv::Point(x_end, hor_max), cv::Point(x_end, crosshair_mask.size().height), cv::Scalar(bit_high)); // Vertical, mouse to bottom
+
+ // Draw crosshair onto frame copy
+ cv::Mat crosshair_frame(frame.size(), frame.type());
+ frame.copyTo(crosshair_frame);
+ cv::bitwise_not(crosshair_frame, crosshair_frame, crosshair_mask);
+
+ // Fade-in frame copy with crosshair into original frame (for alpha)
+ const double alpha = 0.7;
+ cv::addWeighted(crosshair_frame, alpha, frame, 1 - alpha, 0.0, frame);
+ }
+ }
+
+ // remove all labels from this image
+ if (clear_marks == true) {
+ clear_marks = false;
+ marks_changed = true;
+ full_image.copyTo(full_image_roi);
+ current_coord_vec.clear();
+ }
+
+ if (old_current_obj_id != current_obj_id) {
+ full_image.copyTo(full_image_roi);
+ old_current_obj_id = current_obj_id;
+ cv::setTrackbarPos(trackbar_name_2, window_name, current_obj_id);
+ }
+
+ int selected_id = -1;
+ // draw all labels
+ //for (auto &i : current_coord_vec)
+ for (size_t k = 0; k < current_coord_vec.size(); ++k) {
+ auto& i = current_coord_vec.at(k);
+ std::string synset_name;
+ if (i.id < synset_txt.size())
+ synset_name = " - " + synset_txt[i.id];
+
+ int offset = i.id * 25;
+ int red = (offset + 0) % 255 * ((i.id + 2) % 3);
+ int green = (offset + 70) % 255 * ((i.id + 1) % 3);
+ int blue = (offset + 140) % 255 * ((i.id + 0) % 3);
+ cv::Scalar color_rect(red, green, blue); // Scalar color_rect(100, 200, 100);
+
+ // selected rect
+ if (i.abs_rect.x < x_end && (i.abs_rect.x + i.abs_rect.width) > x_end && (i.abs_rect.y + preview.rows) < y_end && (i.abs_rect.y + i.abs_rect.height + preview.rows) > y_end) {
+ if (selected_id < 0) {
+ color_rect = cv::Scalar(100, 200, 300);
+ selected_id = k;
+ rectangle(full_image_roi, i.abs_rect, color_rect, mark_line_width * 2);
+ }
+ }
+
+ if (show_mark_class) {
+ putText(full_image_roi, std::to_string(i.id) + synset_name,
+ i.abs_rect.tl() + cv::Point2f(2, 22), cv::FONT_HERSHEY_SIMPLEX, 0.8, color_rect, 2);
+ }
+
+ rectangle(full_image_roi, i.abs_rect, color_rect, mark_line_width);
+ }
+
+ // remove selected rect
+ if (delete_selected) {
+ delete_selected = false;
+ if (selected_id >= 0)
+ current_coord_vec.erase(current_coord_vec.begin() + selected_id);
+ }
+
+ // show moving rect
+ if (right_button_click == true) {
+ if (move_rect_id < 0)
+ move_rect_id = selected_id;
+
+ int x_delta = x_end - x_start;
+ int y_delta = y_end - y_start;
+ auto rect = current_coord_vec[move_rect_id].abs_rect;
+ rect.x += x_delta;
+ rect.y += y_delta;
+
+ cv::Scalar color_rect = cv::Scalar(300, 200, 100);
+ rectangle(full_image_roi, rect, color_rect, mark_line_width);
+ }
+
+ // complete moving label rect
+ if (move_rect && move_rect_id >= 0) {
+ int x_delta = x_end - x_start;
+ int y_delta = y_end - y_start;
+ current_coord_vec[move_rect_id].abs_rect.x += x_delta;
+ current_coord_vec[move_rect_id].abs_rect.y += y_delta;
+ move_rect = false;
+ move_rect_id = -1;
+ }
+
+ if (next_by_click) {
+ putText(full_image_roi, "Mode: 1 mark per image (next by click)",
+ cv::Point2i(850, 20), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(50, 170, 100), 2);
+ }
+
+ {
+ std::string const obj_str = "Object id: " + std::to_string(current_obj_id) + current_synset_name;
+
+ putText(full_image_roi, obj_str, cv::Point2i(0, 21), cv::FONT_HERSHEY_DUPLEX, 0.8, cv::Scalar(10, 50, 10), 3);
+ putText(full_image_roi, obj_str, cv::Point2i(0, 21), cv::FONT_HERSHEY_DUPLEX, 0.8, cv::Scalar(20, 120, 60), 2);
+ putText(full_image_roi, obj_str, cv::Point2i(0, 21), cv::FONT_HERSHEY_DUPLEX, 0.8, cv::Scalar(50, 200, 100), 1);
+ }
+
+ if (show_help) {
+ putText(full_image_roi,
+ "<- prev_img -> next_img c - clear_marks n - one_object_per_img 0-9 - obj_id m - show coords ESC - exit",
+ cv::Point2i(0, 45), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(50, 10, 10), 2);
+ putText(full_image_roi,
+ "w - line width k - hide obj_name p - copy previous o - track objects r - delete selected R-mouse - move box", // h - disable help",
+ cv::Point2i(0, 80), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(50, 10, 10), 2);
+ } else {
+ putText(full_image_roi,
+ "h - show help",
+ cv::Point2i(0, 45), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(50, 10, 10), 2);
+ }
+
+ // arrows
+ {
+ cv::Scalar prev_arrow_color(200, 150, 100);
+ cv::Scalar next_arrow_color = prev_arrow_color;
+ if (prev_img_rect.contains(cv::Point2i(x_end, y_end)))
+ prev_arrow_color = cv::Scalar(220, 190, 170);
+ if (next_img_rect.contains(cv::Point2i(x_end, y_end)))
+ next_arrow_color = cv::Scalar(220, 190, 170);
+
+ std::vector prev_triangle_pts = { cv::Point(5, 50), cv::Point(40, 90), cv::Point(40, 10), cv::Point(5, 50) };
+ cv::Mat prev_roi = frame(prev_img_rect);
+ line(prev_roi, prev_triangle_pts[0], prev_triangle_pts[1], prev_arrow_color, 5);
+ line(prev_roi, prev_triangle_pts[1], prev_triangle_pts[2], prev_arrow_color, 5);
+ line(prev_roi, prev_triangle_pts[2], prev_triangle_pts[3], prev_arrow_color, 5);
+ line(prev_roi, prev_triangle_pts[3], prev_triangle_pts[0], prev_arrow_color, 5);
+
+ std::vector next_triangle_pts = { cv::Point(10, 10), cv::Point(10, 90), cv::Point(45, 50), cv::Point(10, 10) };
+ cv::Mat next_roi = frame(next_img_rect);
+ line(next_roi, next_triangle_pts[0], next_triangle_pts[1], next_arrow_color, 5);
+ line(next_roi, next_triangle_pts[1], next_triangle_pts[2], next_arrow_color, 5);
+ line(next_roi, next_triangle_pts[2], next_triangle_pts[3], next_arrow_color, 5);
+ line(next_roi, next_triangle_pts[3], next_triangle_pts[0], next_arrow_color, 5);
+ }
+
+ imshow(window_name, frame);
+
+#ifndef CV_VERSION_EPOCH
+ int pressed_key = cv::waitKeyEx(20); // OpenCV 3.x
+#else
+ int pressed_key = cv::waitKey(20); // OpenCV 2.x
+#endif
+
+ if (pressed_key >= 0)
+ for (int i = 0; i < 5; ++i)
+ cv::waitKey(1);
+
+ if (exit_flag)
+ break; // exit after saving
+ if (pressed_key == 27 || pressed_key == 1048603)
+ exit_flag = true; // break; // ESC - save & exit
+
+ if (pressed_key >= '0' && pressed_key <= '9')
+ current_obj_id = pressed_key - '0'; // 0 - 9
+ if (pressed_key >= 1048624 && pressed_key <= 1048633)
+ current_obj_id = pressed_key - 1048624; // 0 - 9
+
+ switch (pressed_key) {
+ //case 'z': // z
+ //case 1048698: // z
+ // undo = true;
+ // break;
+
+ case 'p': // p
+ case 1048688: // p
+ copy_previous_marks = 1;
+ ++trackbar_value;
+ break;
+
+ case 'o': // o
+ case 1048687: // o
+ tracker_copy_previous_marks = 1;
+ ++trackbar_value;
+ break;
+
+ case 32: // SPACE
+ case 1048608: // SPACE
+ ++trackbar_value;
+ break;
+
+ case 2424832: // <-
+ case 65361: // <-
+ case 91: // [
+ --trackbar_value;
+ break;
+ case 2555904: // ->
+ case 65363: // ->
+ case 93: // ]
+ ++trackbar_value;
+ break;
+ case 'c': // c
+ case 1048675: // c
+ clear_marks = true;
+ break;
+ case 'm': // m
+ case 1048685: // m
+ show_mouse_coords = !show_mouse_coords;
+ full_image.copyTo(full_image_roi);
+ break;
+ case 'n': // n
+ case 1048686: // n
+ next_by_click = !next_by_click;
+ full_image.copyTo(full_image_roi);
+ break;
+ case 'w': // w
+ case 1048695: // w
+ mark_line_width = mark_line_width % MAX_MARK_LINE_WIDTH + 1;
+ break;
+ case 'h': // h
+ case 1048680: // h
+ show_help = !show_help;
+ break;
+ case 'k':
+ case 1048683:
+ show_mark_class = !show_mark_class;
+ break;
+ case 'r': // r
+ case 1048690: // r
+ delete_selected = true;
+ break;
+ default:;
+ }
+
+ if (tracker_copy_previous_marks)
+ tracker_optflow.update_tracking_flow(optflow_img, current_coord_vec);
+
+ //if (pressed_key >= 0) std::cout << "pressed_key = " << (int)pressed_key << std::endl;
+
+ } while (true);
+
+ } catch (std::exception& e) {
+ std::cout << "exception: " << e.what() << std::endl;
+ } catch (...) {
+ std::cout << "unknown exception \n";
+ }
+
+ return 0;
+}
diff --git a/train.cmd b/train.cmd
new file mode 100755
index 00000000..87c06619
--- /dev/null
+++ b/train.cmd
@@ -0,0 +1,3 @@
+echo How to start training Darknet Yolo objects (air, bird)
+
+darknet.exe detector train data/obj.data yolo-obj.cfg darknet19_448.conv.23
diff --git a/x64/Release/train_obj.cmd b/x64/Release/train_obj.cmd
deleted file mode 100644
index e5bf36c3..00000000
--- a/x64/Release/train_obj.cmd
+++ /dev/null
@@ -1,7 +0,0 @@
-echo Example how to start training Darknet Yolo v2 for 2 objects (air, bird)
-
-
-darknet.exe detector train data/obj.data yolo-obj.cfg darknet19_448.conv.23
-
-
-pause
\ No newline at end of file
diff --git a/x64/Release/yolo_mark.cmd b/x64/Release/yolo_mark.cmd
deleted file mode 100644
index e412cf28..00000000
--- a/x64/Release/yolo_mark.cmd
+++ /dev/null
@@ -1,7 +0,0 @@
-echo Example how to start marking bouded boxes for training set Yolo v2
-
-
-yolo_mark.exe data/img data/train.txt data/obj.names
-
-
-pause
\ No newline at end of file
diff --git a/x64/Release/yolo-obj.cfg b/yolo-obj.cfg
similarity index 100%
rename from x64/Release/yolo-obj.cfg
rename to yolo-obj.cfg
diff --git a/yolo_mark.sln b/yolo_mark.sln
deleted file mode 100644
index e36777d6..00000000
--- a/yolo_mark.sln
+++ /dev/null
@@ -1,28 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yolo_mark", "yolo_mark.vcxproj", "{71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}.Debug|x64.ActiveCfg = Debug|x64
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}.Debug|x64.Build.0 = Debug|x64
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}.Debug|x86.ActiveCfg = Debug|Win32
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}.Debug|x86.Build.0 = Debug|Win32
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}.Release|x64.ActiveCfg = Release|x64
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}.Release|x64.Build.0 = Release|x64
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}.Release|x86.ActiveCfg = Release|Win32
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}.Release|x86.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/yolo_mark.vcxproj b/yolo_mark.vcxproj
deleted file mode 100644
index 187a3fb3..00000000
--- a/yolo_mark.vcxproj
+++ /dev/null
@@ -1,130 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- {71E25DC4-69FF-4FE2-9DDA-0517AEF2AEAD}
- OpenCV_mark_imgs
- yolo_mark
-
-
-
- Application
- true
- v140
- MultiByte
-
-
- Application
- true
- v140
- MultiByte
-
-
- Application
- false
- v140
- true
- MultiByte
-
-
- Application
- false
- v140
- true
- MultiByte
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Level3
- Disabled
- true
-
-
- true
-
-
-
-
- Level3
- Disabled
- true
- $(OPENCV_DIR)\include;C:\opencv_3.0\opencv\build\include
-
-
- true
- $(OPENCV_DIR)\x64\vc15\lib;$(OPENCV_DIR)\x64\vc14\lib;C:\opencv_3.0\opencv\build\x64\vc14\lib;C:\opencv_2.4.13\opencv\build\x64\vc12\lib;%(AdditionalLibraryDirectories)
-
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- true
- Async
-
-
- true
- true
- true
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- true
- $(OPENCV_DIR)\include;C:\opencv_3.0\opencv\build\include
-
-
- true
- true
- true
- $(OutDir)$(TargetName)$(TargetExt)
- $(OPENCV_DIR)\x64\vc15\lib;$(OPENCV_DIR)\x64\vc14\lib;C:\opencv_3.0\opencv\build\x64\vc14\lib;C:\opencv_2.4.13\opencv\build\x64\vc12\lib;%(AdditionalLibraryDirectories)
-
-
-
-
-
-
-
-
-
\ No newline at end of file