├── CMakeLists.txt ├── LICENSE ├── README.md ├── RUNNINGDATA └── tensor_networks │ ├── 111.meta │ └── mars-small128.ckpt-68577 ├── config ├── classes.txt └── deepsort_config.txt ├── src ├── app │ ├── include │ │ ├── VideoTracker.h │ │ ├── errmsg.h │ │ ├── param.h │ │ └── utility.h │ └── src │ │ ├── VideoTracker.cpp │ │ ├── errmsg.cpp │ │ ├── main.cpp │ │ └── param.cpp ├── features │ ├── CMakeLists.txt │ ├── include │ │ ├── FeatureTensor.h │ │ ├── dataType.h │ │ └── model.h │ └── src │ │ ├── FeatureTensor.cpp │ │ └── model.cpp ├── matching │ ├── CMakeLists.txt │ ├── include │ │ ├── kalmanfilter.h │ │ ├── linear_assignment.h │ │ ├── nn_matching.h │ │ ├── track.h │ │ └── tracker.h │ └── src │ │ ├── kalmanfilter.cpp │ │ ├── linear_assignment.cpp │ │ ├── nn_matching.cpp │ │ ├── track.cpp │ │ └── tracker.cpp └── thirdPart │ ├── CMakeLists.txt │ ├── include │ ├── adapter.h │ ├── boostmatrixadapter.h │ ├── hungarianoper.h │ ├── matrix.h │ └── munkres.h │ └── src │ ├── adapter.cpp │ ├── boostmatrixadapter.cpp │ ├── hungarianoper.cpp │ └── munkres.cpp └── tensorflow_cc ├── .gitignore ├── Dockerfiles ├── BAZEL_VERSION ├── archlinux-shared ├── archlinux-shared-cuda ├── archlinux-static ├── install-archlinux.sh ├── install-common.sh ├── install-ubuntu.sh ├── ubuntu-shared ├── ubuntu-shared-cuda └── ubuntu-static ├── LICENSE ├── README.md ├── example ├── CMakeLists.txt └── example.cpp └── tensorflow_cc ├── CMakeLists.txt ├── cmake ├── TensorflowBase.cmake ├── TensorflowCCConfig.cmake.in ├── TensorflowShared.cmake ├── TensorflowStatic.cmake ├── build_tensorflow.sh.in └── copy_links.sh └── patches ├── v1.15.0-Rename-gettid-functions.patch └── v1.15.0-workspace.bzl.patch /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | cmake_policy(SET CMP0060 NEW) 3 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -O3 -g") 4 | project(deep_sort) 5 | 6 | include(CheckCXXCompilerFlag) 7 | CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14) 8 | 9 | if(COMPILER_SUPPORTS_CXX14) 10 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -pthread") 11 | else() 12 | message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") 13 | endif() 14 | 15 | find_package(OpenCV REQUIRED) 16 | 17 | message(STATUS "OpenCV library status:") 18 | message(STATUS " version: ${OpenCV_VERSION}") 19 | message(STATUS " libraries: ${OpenCV_LIBS}") 20 | message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") 21 | 22 | find_package(OpenMP REQUIRED) 23 | if (OPENMP_FOUND) 24 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") 25 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") 26 | endif() 27 | 28 | find_package(Eigen3 REQUIRED) 29 | find_package(Boost COMPONENTS system) 30 | find_package(TensorflowCC COMPONENTS Shared) 31 | find_package(CUDA) 32 | 33 | include_directories(${EIGEN3_INCLUDE_DIR}) 34 | include_directories(${OpenCV_INCLUDE_DIRS}) 35 | include_directories(${Boost_INCLUDE_DIRS}) 36 | include_directories(${PROJECT_BINARY_DIR}/../src/matching/include/) 37 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/matching/include/) 38 | include_directories(${PROJECT_BINARY_DIR}/../src/thirdPart/include/) 39 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/thirdPart/include/) 40 | include_directories(${PROJECT_BINARY_DIR}/../src/features/include/) 41 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/features/include/) 42 | include_directories(${PROJECT_BINARY_DIR}/../src/app/include/) 43 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/app/include/) 44 | 45 | add_definitions(-Wuninitialized) 46 | add_definitions(-Wreturn-type) 47 | add_definitions(-Wsign-compare) 48 | add_definitions(-Wuninitialized) 49 | add_definitions(-Wunused-function) 50 | add_definitions(-Wunused-label) 51 | add_definitions(-Wunused-value) 52 | add_definitions(-Wunused-variable) 53 | 54 | set(EXECUTABLE_OUTPUT_PATH ../bin) 55 | set(LIBRARY_OUTPUT_PATH ../lib) 56 | file(GLOB_RECURSE SRC_FILES "src/app/src/*.cpp" "src/features/*.cpp" "src/matching/src/*.cpp" "src/thirdPart/src/*.cpp") 57 | 58 | 59 | #Library 60 | add_library(deepsort SHARED ${SRC_FILES}) 61 | target_link_libraries(deepsort ${OpenCV_LIBS} ${Boost_LIBRARIES} TensorflowCC::Shared ${CUDA_LIBRARIES}) 62 | 63 | add_executable(deep_sort ${SRC_FILES}) 64 | target_link_libraries(deep_sort deepsort) 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deep Sort 2 | 3 | A refactoring and tested version of DeepSort. 4 | 5 | ## Requirements 6 | 7 | * OpenCV (>= 3.4) 8 | * Eigen3 9 | * Boost 10 | * CUDA (>= 10.0) 11 | * Tensorflow ( = 1.14) 12 | 13 | ## Tensorflow Installation 14 | 15 | For installing the C++ API, I followed the following guide. I included the repository inside the folder *tensorflow_cc*, where I modified some file for installing the 1.14 version of tensorflow. 16 | 17 | For compiling it, after satysfying the requirements listed in the official repository, execute the following command: 18 | 19 | ``` 20 | cmake -DTENSORFLOW_STATIC=OFF -DTENSORFLOW_SHARED=ON .. 21 | make 22 | sudo make install 23 | ``` 24 | 25 | ## How to compile 26 | 27 | Deep Sort works under Linux environments. I recommend a so-called out of source build which can be achieved by the following command sequence: 28 | 29 | * mkdir build 30 | * cd build 31 | * cmake ../ 32 | * make -j 33 | 34 | ## How to use 35 | 36 | Go to the bin diretory and launch the program with the following commands: 37 | ```bash 38 | ./deep_sort /path/to/the/config/file 39 | e.g.: 40 | ./deep_sort ../config/deepsort_config.txt 41 | ``` 42 | 43 | If you want to use it as library, please add *tensorflow_framework* as well in the *target_link_libraries* command as showed in the CMakeLists file. 44 | 45 | ## Params 46 | 47 | The param file has to be created like the following one: 48 | ``` 49 | [DETECTION_FILE] 50 | /path/to/the/detection/file 51 | [IMAGE_DIRECTORY] 52 | /path/to/the/image/folder 53 | [METRIC_MODEL] 54 | /path/to/the/similarity/model 55 | [FEATURE_MODEL] 56 | /path/to/the/feature/extractor 57 | [ARGS_NN_BUDGET] 58 | 100 59 | [ARGS_MAX_COSINE_DISTANCE] 60 | 0.2 61 | [DT] 62 | 1.0 63 | [MAX_IOU_DISTANCE] 64 | 0.9 65 | [MAX_AGE] 66 | 30 67 | [N_INIT] 68 | 3 69 | [CLASSES] 70 | /path/to/the/class/file 71 | [SHOW_DETECTIONS] # 1 = true 0 = false 72 | 1 73 | ``` 74 | ### Detection File 75 | 76 | The detection file is a txt file containing the detections in the following format: 77 | 78 | ``` 79 | #frame_number,#top_left_x,#top_left_y,#width,#height,#class,#confidence 80 | e.g. 0,623,281,16,15,1,0.294832 81 | ``` 82 | 83 | 84 | ### Class File 85 | The class file has to include the names of all the classes detected by your detector. 86 | 87 | E.g.: 88 | ``` 89 | class1 90 | class2 91 | class3 92 | ... 93 | classN 94 | ``` 95 | 96 | Please, for any comment send me an email to andrea[dot]pennisi[at]gmail[dot]com. 97 | -------------------------------------------------------------------------------- /RUNNINGDATA/tensor_networks/111.meta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apennisi/deep_sort/2fefac0734197c99114055f4257668869b4f0834/RUNNINGDATA/tensor_networks/111.meta -------------------------------------------------------------------------------- /RUNNINGDATA/tensor_networks/mars-small128.ckpt-68577: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apennisi/deep_sort/2fefac0734197c99114055f4257668869b4f0834/RUNNINGDATA/tensor_networks/mars-small128.ckpt-68577 -------------------------------------------------------------------------------- /config/classes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apennisi/deep_sort/2fefac0734197c99114055f4257668869b4f0834/config/classes.txt -------------------------------------------------------------------------------- /config/deepsort_config.txt: -------------------------------------------------------------------------------- 1 | [DETECTION_FILE] 2 | /path/to/the/detection/file 3 | [IMAGE_DIRECTORY] 4 | /path/to/the/image/directory 5 | [METRIC_MODEL] 6 | ../RUNNINGDATA/tensor_networks/111.meta 7 | [FEATURE_MODEL] 8 | ../RUNNINGDATA/tensor_networks/mars-small128.ckpt-68577 9 | [ARGS_NN_BUDGET] 10 | 100 11 | [ARGS_MAX_COSINE_DISTANCE] 12 | 0.2 13 | [DT] 14 | 1.0 15 | [MAX_IOU_DISTANCE] 16 | 0.9 17 | [MAX_AGE] 18 | 30 19 | [N_INIT] 20 | 3 21 | [CLASSES] 22 | ../config/classes.txt 23 | [SHOW_DETECTIONS] # 1 = true 0 = false 24 | 1 25 | -------------------------------------------------------------------------------- /src/app/include/VideoTracker.h: -------------------------------------------------------------------------------- 1 | #ifndef _VIDEOTRACKER_H_ 2 | #define _VIDEOTRACKER_H_ 3 | 4 | #include 5 | #include 6 | #include "model.h" 7 | #include "param.h" 8 | 9 | /** 10 | * VideoTracker 11 | * 12 | * run: 13 | * -vpath: the video's path. 14 | * -showSwitch: whether show the tracking result. 15 | * 16 | * run_sequenceWithGT: 17 | * -motDir: the path of MOT directory. 18 | * -showSwitch: show or not. 19 | * 20 | * run_sequence: 21 | * -motDir: the path of MOT directory. 22 | * -showSwitch: show or not. 23 | */ 24 | class VideoTracker 25 | { 26 | public: 27 | VideoTracker(const DeepSortParam& tracker_params); 28 | bool run(); 29 | std::string showErrMsg(); 30 | 31 | private: 32 | DeepSortParam params; 33 | std::string errorMsg; 34 | std::shared_ptr modelDetection; 35 | }; 36 | 37 | 38 | #endif /* VIDEOTRACKER_H_ */ 39 | 40 | -------------------------------------------------------------------------------- /src/app/include/errmsg.h: -------------------------------------------------------------------------------- 1 | #ifndef ERRMSG_H 2 | #define ERRMSG_H 3 | #include 4 | #include 5 | 6 | class errMsg 7 | { 8 | public: 9 | static errMsg* getInstance(); 10 | void out(std::string file, 11 | std::string func, 12 | std::string msd, 13 | bool pause = true); 14 | private: 15 | errMsg(); 16 | errMsg(const errMsg&); 17 | errMsg& operator=(const errMsg&); 18 | 19 | static errMsg* instance; 20 | }; 21 | 22 | #endif // ERRMSG_H 23 | -------------------------------------------------------------------------------- /src/app/include/param.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARAM_H_ 2 | #define _PARAM_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | class DeepSortParam 12 | { 13 | public: 14 | DeepSortParam() { ; } 15 | void read(const std::string& filename); 16 | const std::string detections() const 17 | { 18 | return detection_file; 19 | } 20 | 21 | const std::string images() const 22 | { 23 | return image_directory; 24 | } 25 | 26 | const float dt() const 27 | { 28 | return dt_value; 29 | } 30 | 31 | const std::string metric_model() const 32 | { 33 | return metric_model_file; 34 | } 35 | 36 | const std::string feature_model() const 37 | { 38 | return feature_model_file; 39 | } 40 | 41 | const float args_nn_budget() const 42 | { 43 | return args_nn_budget_value; 44 | } 45 | 46 | const float args_max_cosine_distance() const 47 | { 48 | return args_max_cosine_distance_value; 49 | } 50 | 51 | const float max_iou_distance() const 52 | { 53 | return max_iou_distance_value; 54 | } 55 | 56 | const int max_age() const 57 | { 58 | return max_age_value; 59 | } 60 | 61 | const int n_init() const 62 | { 63 | return n_init_value; 64 | } 65 | 66 | const std::vector classes() const 67 | { 68 | return detection_classes; 69 | } 70 | 71 | const bool show_detections() const 72 | { 73 | return show_detection_value; 74 | } 75 | 76 | DeepSortParam& operator=(const DeepSortParam& _param) 77 | { 78 | this->detection_file = _param.detections(); 79 | this->image_directory = _param.images(); 80 | this->metric_model_file = _param.metric_model(); 81 | this->feature_model_file = _param.feature_model(); 82 | this->args_nn_budget_value = _param.args_nn_budget(); 83 | this->args_max_cosine_distance_value = _param.args_max_cosine_distance(); 84 | this->dt_value = _param.dt(); 85 | this->max_iou_distance_value = _param.max_iou_distance(); 86 | this->max_age_value = _param.max_age(); 87 | this->n_init_value = _param.n_init(); 88 | this->show_detection_value = _param.show_detections(); 89 | return *this; 90 | } 91 | 92 | const void print() const 93 | { 94 | std::cout << "[DETECTION_FILE]: " << detection_file << std::endl; 95 | std::cout << "[IMAGE_DIRECTORY]: " << image_directory << std::endl; 96 | std::cout << "[METRIC_MODEL]: " << metric_model_file << std::endl; 97 | std::cout << "[FEATURE_MODEL]: " << feature_model_file << std::endl; 98 | std::cout << "[ARGS_NN_BUDGET]: " << args_nn_budget_value << std::endl; 99 | std::cout << "[ARGS_MAX_COSINE_DISTANCE]: " << args_max_cosine_distance_value << std::endl; 100 | std::cout << "[DT]: " << dt_value << std::endl; 101 | std::cout << "[MAX_IOU_DISTANCE]: " << max_iou_distance_value << std::endl; 102 | std::cout << "[MAX_AGE]: " << max_age_value << std::endl; 103 | std::cout << "[N_INIT]: " << n_init_value << std::endl; 104 | if(detection_classes.size() != 0) 105 | { 106 | std::cout << "[CLASSES]: "; 107 | for(const auto& c : detection_classes) 108 | { 109 | std::cout << c << ", "; 110 | } 111 | std::cout << "total=" << detection_classes.size() << " classes" << std::endl; 112 | } 113 | std::cout << "[SHOW_DETECTIONS]: " << show_detection_value << std::endl; 114 | } 115 | 116 | private: 117 | std::string detection_file; 118 | std::string image_directory; 119 | std::string metric_model_file; 120 | std::string feature_model_file; 121 | float args_nn_budget_value; 122 | float args_max_cosine_distance_value; 123 | float dt_value; 124 | float max_iou_distance_value; 125 | int max_age_value; 126 | int n_init_value; 127 | bool show_detection_value; 128 | std::vector detection_classes; 129 | }; 130 | 131 | 132 | #endif -------------------------------------------------------------------------------- /src/app/include/utility.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_ 2 | #define _UTILS_ 3 | 4 | #include 5 | #include "dataType.h" 6 | 7 | class DETECTION_ROW 8 | { 9 | public: 10 | DETECTBOX tlwh; //np.float 11 | float confidence; //float 12 | int class_num; 13 | cv::Scalar color; 14 | FEATURE feature; //np.float32 15 | DETECTBOX to_xyah() const; 16 | DETECTBOX to_tlbr() const; 17 | }; 18 | 19 | typedef std::vector DETECTIONS; 20 | 21 | #endif -------------------------------------------------------------------------------- /src/app/src/VideoTracker.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * VideoTracker.cpp 3 | * 4 | * Created on: Dec 15, 2017 5 | * Author: zy 6 | */ 7 | #include "VideoTracker.h" 8 | #include "opencv2/opencv.hpp" 9 | #include "tracker.h" 10 | #include "FeatureTensor.h" 11 | 12 | using namespace cv; 13 | using namespace std; 14 | 15 | VideoTracker::VideoTracker(const DeepSortParam& tracker_params) : params(tracker_params) 16 | { 17 | modelDetection = std::shared_ptr(new ModelDetection(params.detections(), params.images())); 18 | } 19 | 20 | 21 | 22 | bool VideoTracker::run() 23 | { 24 | tracker mytracker(params); 25 | std::shared_ptr featureTensor(new FeatureTensor(params.metric_model(), params.feature_model())); 26 | 27 | while(true) 28 | { 29 | Mat frame; 30 | 31 | DETECTIONS detections; 32 | if(modelDetection->getFrameDetections(frame, detections) == false) 33 | { 34 | this->errorMsg = "No more frames!"; 35 | return false; 36 | } 37 | 38 | //modelDetection->dataMoreConf(args_min_confidence, detections); 39 | //modelDetection->dataPreprocessing(args_nms_max_overlap, detections); 40 | 41 | //TENSORFLOW get rect's feature. 42 | if(featureTensor->getRectsFeature(frame, detections) == false) 43 | { 44 | this->errorMsg = "Tensorflow get feature failed!"; 45 | return false; 46 | } 47 | 48 | mytracker.predict(); 49 | mytracker.update(detections); 50 | std::vector result; 51 | for(Track& track : mytracker.tracks) 52 | { 53 | if(!track.is_confirmed() || track.time_since_update > 1) continue; 54 | result.push_back(std::make_pair(std::make_pair(track.track_id, track.detection_class), std::make_pair(track.to_tlwh(), track.color))); 55 | } 56 | 57 | if(params.show_detections()) 58 | { 59 | for(unsigned int k = 0; k < detections.size(); k++) 60 | { 61 | DETECTBOX tmpbox = detections[k].tlwh; 62 | Rect rect(tmpbox(0), tmpbox(1), tmpbox(2), tmpbox(3)); 63 | rectangle(frame, rect, Scalar(0,0,255), 4); 64 | } 65 | } 66 | 67 | std::stringstream ss; 68 | for(unsigned int k = 0; k < result.size(); k++) 69 | { 70 | DETECTBOX tmp = result[k].second.first; 71 | std::string det_class = result[k].first.second; 72 | cv::Scalar color = result[k].second.second; 73 | Rect rect = Rect(tmp(0), tmp(1), tmp(2), tmp(3)); 74 | rectangle(frame, rect, color, 2); 75 | ss << result[k].first.first << " - " << det_class; 76 | putText(frame, ss.str(), Point(rect.x, rect.y), CV_FONT_HERSHEY_SIMPLEX, 0.8, color, 2); 77 | ss.str(""); 78 | } 79 | imshow("DeepSortTracking", frame); 80 | waitKey(1); 81 | }//end while; 82 | return true; 83 | } 84 | 85 | std::string VideoTracker::showErrMsg() 86 | { 87 | return this->errorMsg; 88 | } -------------------------------------------------------------------------------- /src/app/src/errmsg.cpp: -------------------------------------------------------------------------------- 1 | #include "errmsg.h" 2 | #include 3 | 4 | errMsg* errMsg::instance = NULL; 5 | errMsg *errMsg::getInstance() 6 | { 7 | if(instance == NULL) instance = new errMsg(); 8 | return instance; 9 | } 10 | 11 | errMsg::errMsg() 12 | { 13 | } 14 | 15 | void errMsg::out( 16 | std::string file, 17 | std::string func, 18 | std::string msg, bool pause) 19 | { 20 | std::cout << "IN file<" << file << "> " 21 | << func << " : " << msg << std::endl; 22 | if(pause) exit(0); 23 | } 24 | -------------------------------------------------------------------------------- /src/app/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "VideoTracker.h" 3 | #include "param.h" 4 | 5 | int main(int argc, char **argv) 6 | { 7 | if(argc != 2) 8 | { 9 | std::cerr << "Usage: " << argv[0] << "/path/to/the/config/file" << std::endl; 10 | exit(-1); 11 | } 12 | 13 | DeepSortParam params; 14 | params.read(argv[1]); 15 | 16 | VideoTracker t(params); 17 | if(t.run() == false) 18 | { 19 | std::cout << t.showErrMsg() << std::endl; 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /src/app/src/param.cpp: -------------------------------------------------------------------------------- 1 | #include "param.h" 2 | 3 | 4 | void DeepSortParam::read(const std::string& filename) 5 | { 6 | std::ifstream file; 7 | 8 | try 9 | { 10 | file.open(filename); 11 | } 12 | catch(...) 13 | { 14 | std::cerr << "Cannot open " << filename << std::endl; 15 | file.close(); 16 | exit(-1); 17 | } 18 | 19 | if(!file.is_open()) 20 | { 21 | std::cerr << "Error: file " << filename << " not found!" << std::endl; 22 | exit(-1); 23 | } 24 | 25 | 26 | std::string line; 27 | while(std::getline(file, line)) 28 | { 29 | std::remove_if(line.begin(), line.end(), isspace); 30 | if(line.empty()) 31 | { 32 | continue; 33 | } 34 | else if(line.find("[DETECTION_FILE]") != std::string::npos) 35 | { 36 | std::getline(file, line); 37 | try 38 | { 39 | detection_file = line; 40 | } 41 | catch(...) 42 | { 43 | std::cerr << "Error in converting the DETECTION_FILE: " << line << std::endl; 44 | exit(-1); 45 | } 46 | } 47 | else if(line.find("[IMAGE_DIRECTORY]") != std::string::npos) 48 | { 49 | std::getline(file, line); 50 | try 51 | { 52 | image_directory = line.c_str(); 53 | } 54 | catch(...) 55 | { 56 | std::cerr << "Error in converting the IMAGE_DIRECTORY: " << line << std::endl; 57 | exit(-1); 58 | } 59 | } 60 | else if(line.find("[METRIC_MODEL]") != std::string::npos) 61 | { 62 | std::getline(file, line); 63 | try 64 | { 65 | metric_model_file = line.c_str(); 66 | } 67 | catch(...) 68 | { 69 | std::cerr << "Error in converting the METRIC_MODEL: " << line << std::endl; 70 | exit(-1); 71 | } 72 | } 73 | else if(line.find("[FEATURE_MODEL]") != std::string::npos) 74 | { 75 | std::getline(file, line); 76 | try 77 | { 78 | feature_model_file = line.c_str(); 79 | } 80 | catch(...) 81 | { 82 | std::cerr << "Error in converting the FEATURE_MODEL: " << line << std::endl; 83 | exit(-1); 84 | } 85 | } 86 | else if(line.find("[ARGS_NN_BUDGET]") != std::string::npos) 87 | { 88 | std::getline(file, line); 89 | try 90 | { 91 | args_nn_budget_value = atof(line.c_str()); 92 | } 93 | catch(...) 94 | { 95 | std::cerr << "Error in converting the ARGS_NN_BUDGET: " << line << std::endl; 96 | exit(-1); 97 | } 98 | } 99 | else if(line.find("[ARGS_MAX_COSINE_DISTANCE]") != std::string::npos) 100 | { 101 | std::getline(file, line); 102 | try 103 | { 104 | args_max_cosine_distance_value = atof(line.c_str()); 105 | } 106 | catch(...) 107 | { 108 | std::cerr << "Error in converting the ARGS_MAX_COSINE_DISTANCE: " << line << std::endl; 109 | exit(-1); 110 | } 111 | } 112 | else if(line.find("[DT]") != std::string::npos) 113 | { 114 | std::getline(file, line); 115 | try 116 | { 117 | dt_value = atof(line.c_str()); 118 | } 119 | catch(...) 120 | { 121 | std::cerr << "Error in converting the DT: " << line << std::endl; 122 | exit(-1); 123 | } 124 | } 125 | else if(line.find("[MAX_IOU_DISTANCE]") != std::string::npos) 126 | { 127 | std::getline(file, line); 128 | try 129 | { 130 | max_iou_distance_value = atof(line.c_str()); 131 | } 132 | catch(...) 133 | { 134 | std::cerr << "Error in converting the MAX_IOU_DISTANCE: " << line << std::endl; 135 | exit(-1); 136 | } 137 | } 138 | else if(line.find("[MAX_AGE]") != std::string::npos) 139 | { 140 | std::getline(file, line); 141 | try 142 | { 143 | max_age_value = atoi(line.c_str()); 144 | } 145 | catch(...) 146 | { 147 | std::cerr << "Error in converting the MAX_AGE: " << line << std::endl; 148 | exit(-1); 149 | } 150 | } 151 | else if(line.find("[N_INIT]") != std::string::npos) 152 | { 153 | std::getline(file, line); 154 | try 155 | { 156 | n_init_value = atoi(line.c_str()); 157 | } 158 | catch(...) 159 | { 160 | std::cerr << "Error in converting the N_INIT: " << line << std::endl; 161 | exit(-1); 162 | } 163 | } 164 | else if(line.find("[SHOW_DETECTIONS]") != std::string::npos) 165 | { 166 | std::getline(file, line); 167 | try 168 | { 169 | show_detection_value = atoi(line.c_str()); 170 | } 171 | catch(...) 172 | { 173 | std::cerr << "Error in converting the SHOW_DETECTIONS: " << line << std::endl; 174 | exit(-1); 175 | } 176 | } 177 | else if(line.find("[CLASSES]") != std::string::npos) 178 | { 179 | std::getline(file, line); 180 | try 181 | { 182 | std::ifstream class_file; 183 | try 184 | { 185 | class_file.open(line); 186 | } 187 | catch(...) 188 | { 189 | std::cerr << "Cannot open " << line << std::endl; 190 | file.close(); 191 | exit(-1); 192 | } 193 | 194 | if(!class_file.is_open()) 195 | { 196 | std::cerr << "Error: file " << line << " not found!" << std::endl; 197 | exit(-1); 198 | } 199 | 200 | 201 | std::string class_line; 202 | while(std::getline(class_file, class_line)) 203 | { 204 | detection_classes.push_back(class_line); 205 | } 206 | 207 | class_file.close(); 208 | } 209 | catch(...) 210 | { 211 | std::cerr << "Error in converting the N_INIT: " << line << std::endl; 212 | exit(-1); 213 | } 214 | } 215 | } 216 | 217 | file.close(); 218 | 219 | print(); 220 | } 221 | -------------------------------------------------------------------------------- /src/features/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | function(featuregetter) 2 | include_directories(${PROJECT_BINARY_DIR}/../src/feature/include/) 3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/feature/include/) 4 | 5 | file(GLOB_RECURSE FEATURE_SRC "src/feature/src/*") 6 | 7 | add_library(featuregetter SHARED ${FEATURE_SRC}) 8 | target_link_libraries(featuregetter ${OpenCV_LIBS} TensorflowCC::Shared tensorflow_framework ${CUDA_LIBRARIES}) 9 | 10 | endfunction() -------------------------------------------------------------------------------- /src/features/include/FeatureTensor.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "utility.h" 12 | 13 | 14 | typedef unsigned char uint8; 15 | 16 | class FeatureTensor 17 | { 18 | public: 19 | // FeatureTensor(); 20 | FeatureTensor(const std::string& model_meta, const std::string& model_data); 21 | FeatureTensor(const FeatureTensor&); 22 | FeatureTensor& operator = (const FeatureTensor&); 23 | bool getRectsFeature(const cv::Mat& img, DETECTIONS& d); 24 | ~FeatureTensor(); 25 | 26 | private: 27 | bool init(); 28 | 29 | void tobuffer(const std::vector &imgs, uint8 *buf); 30 | 31 | int feature_dim; 32 | std::shared_ptr session; 33 | std::vector output_tensors; 34 | std::vector outnames; 35 | tensorflow::string input_layer; 36 | std::string tf_model_meta; 37 | std::string tf_model_data; 38 | }; 39 | -------------------------------------------------------------------------------- /src/features/include/dataType.h: -------------------------------------------------------------------------------- 1 | #ifndef _DATATYPE_H_ 2 | #define _DATATYPE_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef Eigen::Matrix DETECTBOX; 10 | typedef Eigen::Matrix DETECTBOXSS; 11 | typedef Eigen::Matrix FEATURE; 12 | typedef Eigen::Matrix FEATURESS; 13 | 14 | //Kalmanfilter 15 | //typedef Eigen::Matrix KAL_FILTER; 16 | typedef Eigen::Matrix KAL_MEAN; 17 | typedef Eigen::Matrix KAL_COVA; 18 | typedef Eigen::Matrix KAL_HMEAN; 19 | typedef Eigen::Matrix KAL_HCOVA; 20 | using KAL_DATA = std::pair; 21 | using KAL_HDATA = std::pair; 22 | 23 | //main 24 | using RESULT_DATA = std::pair< std::pair, std::pair >; 25 | 26 | //tracker: 27 | using TRACKER_DATA = std::pair; 28 | using MATCH_DATA = std::pair; 29 | typedef struct t{ 30 | std::vector matches; 31 | std::vector unmatched_tracks; 32 | std::vector unmatched_detections; 33 | }TRACHER_MATCHD; 34 | 35 | //linear_assignment: 36 | typedef Eigen::Matrix DYNAMICM; 37 | 38 | 39 | #endif // DATATYPE_H 40 | -------------------------------------------------------------------------------- /src/features/include/model.h: -------------------------------------------------------------------------------- 1 | #ifndef MODEL_H 2 | #define MODEL_H 3 | #include "dataType.h" 4 | #include "utility.h" 5 | #include 6 | #include 7 | 8 | /** 9 | * Get each image's rects & corresponding features. 10 | * Method of filter conf. 11 | * Method of preprocessing. 12 | */ 13 | class ModelDetection 14 | { 15 | 16 | public: 17 | ModelDetection() { ; } 18 | ModelDetection(const std::string& txt_filename, const std::string& img_path); 19 | ModelDetection(const ModelDetection&); 20 | ModelDetection& operator =(const ModelDetection&); 21 | bool getFrameDetections(int frame_idx, DETECTIONS& res); 22 | bool getFrameDetections(cv::Mat& frame, DETECTIONS& res); 23 | void dataMoreConf(float min_confidence, DETECTIONS& d); 24 | void dataPreprocessing(float max_bbox_overlap, DETECTIONS& d); 25 | 26 | private: 27 | void ReadFileContent(const std::string &file, std::string &content); 28 | void ReadRcFileTotal(const std::string &file); 29 | 30 | private: 31 | using AREAPAIR = std::pair; 32 | struct cmp { 33 | bool operator()(const AREAPAIR a, const AREAPAIR b) 34 | { 35 | return a.second < b.second; 36 | } 37 | }; 38 | 39 | private: 40 | 41 | std::map data; 42 | std::vector names; 43 | void _Qsort(DETECTIONS d, std::vector& a, int low, int high); 44 | bool loadFromFile; 45 | std::string imgFolder; 46 | int maxImgNum; 47 | int counter = 0; 48 | }; 49 | 50 | #endif // MODEL_H 51 | -------------------------------------------------------------------------------- /src/features/src/FeatureTensor.cpp: -------------------------------------------------------------------------------- 1 | #include "FeatureTensor.h" 2 | 3 | using namespace tensorflow; 4 | 5 | FeatureTensor::FeatureTensor(const std::string& model_meta, const std::string& model_data) 6 | : tf_model_meta(model_meta), tf_model_data(model_data) 7 | { 8 | //prepare model: 9 | bool status = init(); 10 | if(status == false) exit(1); 11 | } 12 | 13 | FeatureTensor::~FeatureTensor() 14 | { 15 | session->Close(); 16 | output_tensors.clear(); 17 | outnames.clear(); 18 | } 19 | 20 | bool FeatureTensor::init() { 21 | 22 | tensorflow::SessionOptions sessOptions; 23 | sessOptions.config.mutable_gpu_options()->set_allow_growth(true); 24 | session = std::shared_ptr(NewSession(sessOptions)); 25 | if(session == nullptr) return false; 26 | 27 | // const tensorflow::string pathToGraph = TENSORFLOW_MODEL_META; 28 | const tensorflow::string pathToGraph = tf_model_meta; 29 | Status status; 30 | MetaGraphDef graph_def; 31 | status = ReadBinaryProto(tensorflow::Env::Default(), pathToGraph, &graph_def); 32 | if(status.ok() == false) return false; 33 | 34 | status = session->Create(graph_def.graph_def()); 35 | if(status.ok() == false) return false; 36 | 37 | // const tensorflow::string checkpointPath = TENSORFLOW_MODEL; 38 | const tensorflow::string checkpointPath = tf_model_data; 39 | Tensor checkpointTensor(DT_STRING, TensorShape()); 40 | checkpointTensor.scalar()() = checkpointPath; 41 | status = session->Run( 42 | { {graph_def.saver_def().filename_tensor_name(), checkpointTensor}, }, 43 | {}, {graph_def.saver_def().restore_op_name()}, nullptr ); 44 | if(status.ok() == false) return false; 45 | 46 | input_layer = "Placeholder:0"; 47 | outnames.push_back("truediv:0"); 48 | feature_dim = 128; 49 | return true; 50 | } 51 | 52 | bool FeatureTensor::getRectsFeature(const cv::Mat& img, DETECTIONS& d) 53 | { 54 | std::vector mats; 55 | for(auto& dbox : d) 56 | { 57 | auto rc = cv::Rect(int(dbox.tlwh(0)), int(dbox.tlwh(1)), 58 | int(dbox.tlwh(2)), int(dbox.tlwh(3))); 59 | 60 | if(rc.x < 0) 61 | { 62 | rc.width -= rc.x; 63 | rc.x = 0; 64 | } 65 | 66 | if(rc.y < 0) 67 | { 68 | rc.height -= rc.y; 69 | rc.y = 0; 70 | } 71 | 72 | if(rc.width + rc.x >= img.cols) 73 | { 74 | rc.width -= (rc.width + rc.x - img.cols); 75 | } 76 | 77 | if(rc.height + rc.y >= img.rows) 78 | { 79 | rc.height -= (rc.height + rc.y - img.rows); 80 | } 81 | 82 | cv::Mat mattmp = img(rc).clone(); 83 | cv::resize(mattmp, mattmp, cv::Size(64, 128)); 84 | mats.push_back(mattmp); 85 | } 86 | 87 | int count = mats.size(); 88 | 89 | Tensor input_tensor(DT_UINT8, TensorShape({count, 128, 64, 3})); 90 | tobuffer(mats, input_tensor.flat().data()); 91 | std::vector> feed_dict = { 92 | {input_layer, input_tensor}, 93 | }; 94 | Status status = session->Run(feed_dict, outnames, {}, &output_tensors); 95 | if(status.ok() == false) return false; 96 | float* tensor_buffer = output_tensors[0].flat().data(); 97 | int i = 0; 98 | 99 | for(auto& dbox : d) 100 | { 101 | for(int j = 0; j < feature_dim; j++) 102 | { 103 | dbox.feature[j] = tensor_buffer[i*feature_dim+j]; 104 | } 105 | i++; 106 | } 107 | return true; 108 | } 109 | 110 | void FeatureTensor::tobuffer(const std::vector &imgs, uint8 *buf) 111 | { 112 | int pos = 0; 113 | for(const cv::Mat& img : imgs) 114 | { 115 | int Lenth = img.rows * img.cols * 3; 116 | int nr = img.rows; 117 | int nc = img.cols; 118 | if(img.isContinuous()) 119 | { 120 | nr = 1; 121 | nc = Lenth; 122 | } 123 | for(int i = 0; i < nr; i++) 124 | { 125 | const uchar* inData = img.ptr(i); 126 | for(int j = 0; j < nc; j++) 127 | { 128 | buf[pos] = *inData++; 129 | pos++; 130 | } 131 | }//end for 132 | }//end imgs; 133 | } 134 | -------------------------------------------------------------------------------- /src/features/src/model.cpp: -------------------------------------------------------------------------------- 1 | #include "model.h" 2 | #include 3 | 4 | 5 | enum DETECTBOX_IDX {IDX_X = 0, IDX_Y, IDX_W, IDX_H }; 6 | 7 | static void splitStr(const std::string& inputStr, const std::string &key, std::vector& outStrVec) { 8 | if (inputStr == "") { 9 | return; 10 | } 11 | int pos = inputStr.find(key); 12 | int oldpos = 0; 13 | if (pos > 0) { 14 | std::string tmp = inputStr.substr(0, pos); 15 | outStrVec.push_back(tmp); 16 | } 17 | while (1) 18 | { 19 | if (pos < 0) 20 | { 21 | break; 22 | } 23 | oldpos = pos; 24 | int newpos = inputStr.find(key, pos + key.length()); 25 | std::string tmp = inputStr.substr(pos + key.length(), newpos - pos - key.length()); 26 | outStrVec.push_back(tmp); 27 | pos = newpos; 28 | } 29 | int tmplen = 0; 30 | if (outStrVec.size() > 0) 31 | { 32 | tmplen = outStrVec.at(outStrVec.size() - 1).length(); 33 | } 34 | 35 | if (oldpos + tmplen < int(inputStr.length()) - 1) 36 | { 37 | std::string tmp = inputStr.substr(oldpos + key.length()); 38 | outStrVec.push_back(tmp); 39 | } 40 | } 41 | 42 | static std::string trim(std::string &s) 43 | { 44 | if (s.empty()) 45 | { 46 | return s; 47 | } 48 | 49 | s.erase(0, s.find_first_not_of(" ")); 50 | s.erase(s.find_last_not_of(" ") + 1); 51 | return s; 52 | } 53 | 54 | static int toInt(const std::string &in) 55 | { 56 | int re = 0; 57 | sscanf(in.c_str(), "%d", &re); 58 | return re; 59 | } 60 | 61 | static float toFloat(const std::string &in) 62 | { 63 | float re = 0; 64 | sscanf(in.c_str(), "%f", &re); 65 | return re; 66 | } 67 | 68 | bool 69 | ModelDetection::getFrameDetections(cv::Mat& frame, DETECTIONS& res) 70 | { 71 | if(loadFromFile && counter < maxImgNum) 72 | { 73 | res = data[counter]; 74 | std::stringstream ss; 75 | ss << imgFolder << "/" << counter << ".jpg"; 76 | frame = cv::imread(ss.str()); 77 | counter++; 78 | return true; 79 | } 80 | return false; 81 | } 82 | 83 | bool 84 | ModelDetection::getFrameDetections(int frame_idx, DETECTIONS& res) 85 | { 86 | if(loadFromFile == true) 87 | { 88 | res = data[frame_idx]; 89 | return true; 90 | } 91 | return false; 92 | } 93 | 94 | 95 | void ModelDetection::dataMoreConf(float min_confidence, DETECTIONS &d) 96 | { 97 | DETECTIONS::iterator it; 98 | for(it = d.begin(); it != d.end();) { 99 | if((*it).confidence < min_confidence) it = d.erase(it); 100 | else ++it; 101 | } 102 | } 103 | 104 | void ModelDetection::dataPreprocessing(float max_bbox_overlap, DETECTIONS &d) 105 | { 106 | int size = int(d.size()); 107 | if(size == 0) return; 108 | 109 | //generate idx: 110 | std::vector idxs; 111 | idxs.reserve(size); 112 | 113 | std::vector idx_status; 114 | idx_status.reserve(size); 115 | for(auto i = 0; i < size; ++i) 116 | { 117 | idxs.push_back(int(i)); 118 | idx_status.push_back(false); 119 | } 120 | 121 | //get areas: 122 | std::vector areas; 123 | areas.reserve(size); 124 | for(auto i = 0; i < size; ++i) { 125 | double tmp = (d[i].tlwh(IDX_W)+1)*(d[i].tlwh(IDX_H)+1); 126 | areas.push_back(tmp); 127 | } 128 | 129 | //sort idxs by scores ==>quick sort: 130 | _Qsort(d, idxs, 0, size-1); 131 | 132 | //get delete detections: 133 | std::vector delIdxs; 134 | while(true) {//get compare idx; 135 | int i = -1; 136 | for(int j = size-1; j>0; --j) { 137 | if(idx_status[j] == false) { 138 | i = j; 139 | idx_status[i] = true; 140 | } 141 | } 142 | if(i == -1) break; //end circle 143 | 144 | //get standard area: 145 | int xx1 = d[idxs[i]].tlwh(IDX_X); //max 146 | int yy1 = d[idxs[i]].tlwh(IDX_Y); //max 147 | int xx2 = d[idxs[i]].tlwh(IDX_X) + d[idxs[i]].tlwh(IDX_W); //min 148 | int yy2 = d[idxs[i]].tlwh(IDX_Y) + d[idxs[i]].tlwh(IDX_H);//min 149 | for(auto j = 0; j < size; j++) 150 | { 151 | if(idx_status[j] == true) continue; 152 | xx1 = int(d[idxs[j]].tlwh(IDX_X) > xx1?d[idxs[j]].tlwh(IDX_X):xx1); 153 | yy1 = int(d[idxs[j]].tlwh(IDX_Y) > yy1?d[idxs[j]].tlwh(IDX_Y):yy1); 154 | int tmp = d[idxs[j]].tlwh(IDX_X) + d[idxs[j]].tlwh(IDX_W); 155 | xx2 = (tmp < xx2? tmp:xx2); 156 | tmp = d[idxs[j]].tlwh(IDX_Y) + d[idxs[j]].tlwh(IDX_H); 157 | yy2 = (tmp < yy2?tmp:yy2); 158 | } 159 | //standard area = w*h; 160 | int w = xx2-xx1+1; w = (w > 0?w:0); 161 | int h = yy2-yy1+1; h = (h > 0?h:0); 162 | //get delIdx; 163 | for(auto j = 0; j < size; j++) 164 | { 165 | if(idx_status[j] == true) continue; 166 | double tmp = w*h*1.0/areas[idxs[j]]; 167 | if(tmp > max_bbox_overlap) 168 | { 169 | delIdxs.push_back(idxs[j]); 170 | idx_status[j] = true; 171 | } 172 | }//end 173 | } 174 | //delete from detections: 175 | for(size_t i = 0; i < delIdxs.size(); ++i) 176 | { 177 | DETECTIONS::iterator it = d.begin() + delIdxs[i]; 178 | d.erase(it); 179 | } 180 | } 181 | 182 | void ModelDetection::ReadFileContent(const std::string &file, std::string &content) 183 | { 184 | FILE *fl = fopen(file.c_str(), "rb"); 185 | if(fl == NULL) 186 | { 187 | return; 188 | } 189 | fseek(fl, 0, SEEK_END); 190 | int len = ftell(fl); 191 | if(len <= 0) 192 | { 193 | return; 194 | } 195 | fseek(fl, 0, SEEK_SET); 196 | char *buf = new char[len+1]; 197 | memset(buf, 0, len+1); 198 | fread(buf, 1, len, fl); 199 | content = std::string(buf); 200 | delete []buf; 201 | fclose(fl); 202 | } 203 | 204 | void ModelDetection::ReadRcFileTotal(const std::string &file) 205 | { 206 | std::string content = ""; 207 | ReadFileContent(file, content); 208 | 209 | 210 | std::vector lines; 211 | splitStr(content, "\n", lines); 212 | DETECTIONS rcs; 213 | int num = -1; 214 | int tmpNum = -1; 215 | for (size_t i = 0; i < lines.size(); i++) 216 | { 217 | std::vector cols; 218 | // std::cout << lines[i] << std::endl; 219 | splitStr(lines[i], ",", cols); 220 | if (cols.size() < 6) { 221 | continue; 222 | } 223 | tmpNum = toInt(trim(cols[0])); 224 | if (num!=-1 && tmpNum!=num) 225 | { 226 | data.insert(std::make_pair(num, rcs)); 227 | rcs.clear(); 228 | num = tmpNum; 229 | } 230 | if (num == -1) 231 | { 232 | num = tmpNum; 233 | } 234 | 235 | DETECTION_ROW tmpRow; 236 | tmpRow.class_num = toInt(trim(cols[5])); 237 | tmpRow.confidence = toFloat(trim(cols[6])); 238 | tmpRow.tlwh = DETECTBOX(toInt(trim(cols[1])), toInt(trim(cols[2])), toInt(trim(cols[3])), toInt(trim(cols[4]))); 239 | 240 | rcs.push_back(tmpRow); 241 | } 242 | 243 | if (!rcs.empty()) 244 | { 245 | data.insert(std::make_pair(tmpNum, rcs)); 246 | } 247 | } 248 | 249 | 250 | //load detection data from outer file 251 | ModelDetection::ModelDetection(const std::string& txt_filename, const std::string& img_path) 252 | { 253 | ReadRcFileTotal(txt_filename); 254 | maxImgNum = data.size(); 255 | counter = 0; 256 | imgFolder = img_path; 257 | loadFromFile = true; 258 | } 259 | 260 | void ModelDetection::_Qsort(DETECTIONS d, std::vector& a, int low, int high) 261 | { 262 | if(low >= high) return; 263 | int first = low; 264 | int last = high; 265 | 266 | int key_idx = a[first]; 267 | while(first < last) 268 | { 269 | while(first < last && d[a[last]].confidence >= d[key_idx].confidence) 270 | --last; 271 | a[first] = a[last]; 272 | while(first < last && d[a[first]].confidence <= d[key_idx].confidence) 273 | ++first; 274 | a[last] = a[first]; 275 | } 276 | a[first] = key_idx; 277 | _Qsort(d, a, low, first-1); 278 | _Qsort(d, a, first+1, high); 279 | } 280 | 281 | 282 | DETECTBOX DETECTION_ROW::to_xyah() const 283 | {//(centerx, centery, ration, h) 284 | DETECTBOX ret = tlwh; 285 | ret(0,IDX_X) += (ret(0, IDX_W)*0.5); 286 | ret(0, IDX_Y) += (ret(0, IDX_H)*0.5); 287 | ret(0, IDX_W) /= ret(0, IDX_H); 288 | return ret; 289 | } 290 | 291 | DETECTBOX DETECTION_ROW::to_tlbr() const 292 | {//(x,y,xx,yy) 293 | DETECTBOX ret = tlwh; 294 | ret(0, IDX_X) += ret(0, IDX_W); 295 | ret(0, IDX_Y) += ret(0, IDX_H); 296 | return ret; 297 | } 298 | 299 | -------------------------------------------------------------------------------- /src/matching/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | function(matching) 2 | include_directories(${PROJECT_BINARY_DIR}/../src/matching/) 3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/matching/) 4 | #add_definitions(-DUSE_FACE_NET) 5 | 6 | file(GLOB_RECURSE MATCHING_SRC "src/matching/*.cpp") 7 | 8 | add_library(matching SHARED ${MATCHING_SRC}) 9 | target_link_libraries(matching ${OpenCV_LIBS}) 10 | 11 | endfunction() -------------------------------------------------------------------------------- /src/matching/include/kalmanfilter.h: -------------------------------------------------------------------------------- 1 | #ifndef KALMANFILTER_H 2 | #define KALMANFILTER_H 3 | 4 | #include "dataType.h" 5 | 6 | class KalmanFilter 7 | { 8 | public: 9 | static const double chi2inv95[10]; 10 | KalmanFilter(const double& dt = 1.); 11 | KAL_DATA initiate(const DETECTBOX& measurement); 12 | void predict(KAL_MEAN& mean, KAL_COVA& covariance); 13 | KAL_HDATA project(const KAL_MEAN& mean, const KAL_COVA& covariance); 14 | KAL_DATA update(const KAL_MEAN& mean, 15 | const KAL_COVA& covariance, 16 | const DETECTBOX& measurement); 17 | 18 | Eigen::Matrix gating_distance( 19 | const KAL_MEAN& mean, 20 | const KAL_COVA& covariance, 21 | const std::vector& measurements, 22 | bool only_position = false); 23 | 24 | void set_dt(const float& dt); 25 | 26 | private: 27 | Eigen::Matrix _motion_mat; 28 | Eigen::Matrix _update_mat; 29 | float _std_weight_position; 30 | float _std_weight_velocity; 31 | }; 32 | 33 | #endif // KALMANFILTER_H 34 | -------------------------------------------------------------------------------- /src/matching/include/linear_assignment.h: -------------------------------------------------------------------------------- 1 | #ifndef _LINEAR_ASSIGNMENT_H_ 2 | #define _LINEAR_ASSIGNMENT_H_ 3 | #include "dataType.h" 4 | #include "tracker.h" 5 | #include 6 | #include 7 | #include 8 | 9 | #define INFTY_COST 1e5 10 | class tracker; 11 | //for matching; 12 | class linear_assignment 13 | { 14 | linear_assignment(); 15 | linear_assignment(const linear_assignment& ); 16 | linear_assignment& operator=(const linear_assignment&); 17 | static linear_assignment* instance; 18 | 19 | public: 20 | static linear_assignment* getInstance(); 21 | TRACHER_MATCHD matching_cascade(tracker* distance_metric, 22 | tracker::GATED_METRIC_FUNC distance_metric_func, 23 | float max_distance, 24 | int cascade_depth, 25 | std::vector& tracks, 26 | const DETECTIONS& detections, 27 | std::vector &track_indices, 28 | std::vector detection_indices = std::vector()); 29 | TRACHER_MATCHD min_cost_matching( 30 | tracker* distance_metric, 31 | tracker::GATED_METRIC_FUNC distance_metric_func, 32 | float max_distance, 33 | std::vector& tracks, 34 | const DETECTIONS& detections, 35 | std::vector& track_indices, 36 | std::vector& detection_indices); 37 | DYNAMICM gate_cost_matrix( 38 | std::shared_ptr & kf, 39 | DYNAMICM& cost_matrix, 40 | std::vector& tracks, 41 | const DETECTIONS& detections, 42 | const std::vector& track_indices, 43 | const std::vector& detection_indices, 44 | float gated_cost = INFTY_COST, 45 | bool only_position = false); 46 | }; 47 | 48 | #endif // LINEAR_ASSIGNMENT_H 49 | -------------------------------------------------------------------------------- /src/matching/include/nn_matching.h: -------------------------------------------------------------------------------- 1 | #ifndef NN_MATCHING_H 2 | #define NN_MATCHING_H 3 | 4 | #include "dataType.h" 5 | 6 | #include 7 | 8 | //A tool to calculate distance; 9 | class NearNeighborDisMetric{ 10 | public: 11 | enum METRIC_TYPE{euclidean=1, cosine}; 12 | NearNeighborDisMetric(METRIC_TYPE metric, 13 | float matching_threshold, 14 | int budget); 15 | DYNAMICM distance(const FEATURESS& features, const std::vector &targets); 16 | // void partial_fit(FEATURESS& features, std::vector targets, std::vector active_targets); 17 | void partial_fit(std::vector& tid_feats, std::vector& active_targets); 18 | float mating_threshold; 19 | 20 | private: 21 | typedef Eigen::VectorXf (NearNeighborDisMetric::*PTRFUN)(const FEATURESS&, const FEATURESS&); 22 | Eigen::VectorXf _nncosine_distance(const FEATURESS& x, const FEATURESS& y); 23 | Eigen::VectorXf _nneuclidean_distance(const FEATURESS& x, const FEATURESS& y); 24 | 25 | Eigen::MatrixXf _pdist(const FEATURESS& x, const FEATURESS& y); 26 | Eigen::MatrixXf _cosine_distance(const FEATURESS & a, const FEATURESS& b, bool data_is_normalized = false); 27 | private: 28 | PTRFUN _metric; 29 | int budget; 30 | std::map samples; 31 | }; 32 | 33 | #endif // NN_MATCHING_H 34 | -------------------------------------------------------------------------------- /src/matching/include/track.h: -------------------------------------------------------------------------------- 1 | #ifndef TRACK_H 2 | #define TRACK_H 3 | 4 | #include 5 | 6 | #include "dataType.h" 7 | #include "utility.h" 8 | 9 | #include "kalmanfilter.h" 10 | 11 | class Track 12 | { 13 | /*""" 14 | A single target track with state space `(x, y, a, h)` and associated 15 | velocities, where `(x, y)` is the center of the bounding box, `a` is the 16 | aspect ratio and `h` is the height. 17 | 18 | Parameters 19 | ---------- 20 | mean : ndarray 21 | Mean vector of the initial state distribution. 22 | covariance : ndarray 23 | Covariance matrix of the initial state distribution. 24 | track_id : int 25 | A unique track identifier. 26 | n_init : int 27 | Number of consecutive detections before the track is confirmed. The 28 | track state is set to `Deleted` if a miss occurs within the first 29 | `n_init` frames. 30 | max_age : int 31 | The maximum number of consecutive misses before the track state is 32 | set to `Deleted`. 33 | feature : Optional[ndarray] 34 | Feature vector of the detection this track originates from. If not None, 35 | this feature is added to the `features` cache. 36 | 37 | Attributes 38 | ---------- 39 | mean : ndarray 40 | Mean vector of the initial state distribution. 41 | covariance : ndarray 42 | Covariance matrix of the initial state distribution. 43 | track_id : int 44 | A unique track identifier. 45 | hits : int 46 | Total number of measurement updates. 47 | age : int 48 | Total number of frames since first occurance. 49 | time_since_update : int 50 | Total number of frames since last measurement update. 51 | state : TrackState 52 | The current track state. 53 | features : List[ndarray] 54 | A cache of features. On each measurement update, the associated feature 55 | vector is added to this list. 56 | 57 | """*/ 58 | enum TrackState {Tentative = 1, Confirmed, Deleted}; 59 | 60 | public: 61 | Track(KAL_MEAN& mean, KAL_COVA& covariance, int track_id, 62 | int n_init, int max_age, const FEATURE& feature, 63 | const std::string& det_class = "", const cv::Scalar& col = cv::Scalar()); 64 | void predit(std::shared_ptr &kf); 65 | void update(std::shared_ptr & kf, const DETECTION_ROW &detection); 66 | void set_dt(std::shared_ptr &kf, const float& dt); 67 | void mark_missed(); 68 | bool is_confirmed(); 69 | bool is_deleted(); 70 | bool is_tentative(); 71 | DETECTBOX to_tlwh(); 72 | DETECTBOX to_xyah(); 73 | int time_since_update; 74 | int track_id; 75 | std::string detection_class; 76 | cv::Scalar color; 77 | FEATURESS features; 78 | KAL_MEAN mean; 79 | KAL_COVA covariance; 80 | 81 | int hits; 82 | int age; 83 | int _n_init; 84 | int _max_age; 85 | TrackState state; 86 | private: 87 | void featuresAppendOne(const FEATURE& f); 88 | }; 89 | 90 | #endif // TRACK_H 91 | -------------------------------------------------------------------------------- /src/matching/include/tracker.h: -------------------------------------------------------------------------------- 1 | #ifndef TRACKER_H 2 | #define TRACKER_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "kalmanfilter.h" 9 | #include "track.h" 10 | #include "utility.h" 11 | #include "param.h" 12 | 13 | class NearNeighborDisMetric; 14 | 15 | class tracker 16 | { 17 | public: 18 | std::shared_ptr metric; 19 | float max_iou_distance; 20 | int max_age; 21 | int n_init; 22 | std::shared_ptr kf; 23 | int _next_idx; 24 | float dt; 25 | private: 26 | std::vector detection_classes; 27 | std::map color_map; 28 | public: 29 | std::vector tracks; 30 | tracker(float max_cosine_distance, int nn_budget, 31 | float max_iou_distance = 0.9, 32 | int max_age = 15, int n_init=5, float dt = 1.); 33 | tracker(const DeepSortParam& params); 34 | void predict(); 35 | void update(const DETECTIONS& detections); 36 | typedef DYNAMICM (tracker::* GATED_METRIC_FUNC)( 37 | std::vector& tracks, 38 | const DETECTIONS& dets, 39 | const std::vector& track_indices, 40 | const std::vector& detection_indices); 41 | private: 42 | void _match(const DETECTIONS& detections, TRACHER_MATCHD& res); 43 | void _initiate_track(const DETECTION_ROW& detection); 44 | void _init(float max_cosine_distance, int nn_budget, 45 | float max_iou_distance = 0.9, 46 | int max_age = 15, int n_init=5, float dt = 1., 47 | const std::vector& classes = std::vector()); 48 | public: 49 | DYNAMICM gated_matric( 50 | std::vector& tracks, 51 | const DETECTIONS& dets, 52 | const std::vector& track_indices, 53 | const std::vector& detection_indices); 54 | DYNAMICM iou_cost( 55 | std::vector& tracks, 56 | const DETECTIONS& dets, 57 | const std::vector& track_indices, 58 | const std::vector& detection_indices); 59 | Eigen::VectorXf iou(DETECTBOX& bbox, 60 | DETECTBOXSS &candidates); 61 | }; 62 | 63 | #endif // TRACKER_H 64 | -------------------------------------------------------------------------------- /src/matching/src/kalmanfilter.cpp: -------------------------------------------------------------------------------- 1 | #include "kalmanfilter.h" 2 | #include 3 | 4 | const double KalmanFilter::chi2inv95[10] = { 5 | 0, 6 | 3.8415, 7 | 5.9915, 8 | 7.8147, 9 | 9.4877, 10 | 11.070, 11 | 12.592, 12 | 14.067, 13 | 15.507, 14 | 16.919 15 | }; 16 | KalmanFilter::KalmanFilter(const double& dt) 17 | { 18 | int ndim = 4; 19 | 20 | _motion_mat = Eigen::MatrixXf::Identity(8, 8); 21 | for(int i = 0; i < ndim; i++) 22 | { 23 | _motion_mat(i, ndim+i) = dt; 24 | } 25 | _update_mat = Eigen::MatrixXf::Identity(4, 8); 26 | 27 | this->_std_weight_position = 1. / 20; 28 | this->_std_weight_velocity = 1. / 160; 29 | } 30 | 31 | KAL_DATA KalmanFilter::initiate(const DETECTBOX &measurement) 32 | { 33 | DETECTBOX mean_pos = measurement; 34 | DETECTBOX mean_vel; 35 | for(int i = 0; i < 4; i++) mean_vel(i) = 0; 36 | 37 | KAL_MEAN mean; 38 | for(int i = 0; i < 8; i++){ 39 | if(i < 4) mean(i) = mean_pos(i); 40 | else mean(i) = mean_vel(i - 4); 41 | } 42 | 43 | KAL_MEAN std; 44 | std(0) = 2 * _std_weight_position * measurement[3]; 45 | std(1) = 2 * _std_weight_position * measurement[3]; 46 | std(2) = 1e-2; 47 | std(3) = 2 * _std_weight_position * measurement[3]; 48 | std(4) = 10 * _std_weight_velocity * measurement[3]; 49 | std(5) = 10 * _std_weight_velocity * measurement[3]; 50 | std(6) = 1e-5; 51 | std(7) = 10 * _std_weight_velocity * measurement[3]; 52 | 53 | KAL_MEAN tmp = std.array().square(); 54 | KAL_COVA var = tmp.asDiagonal(); 55 | return std::make_pair(mean, var); 56 | } 57 | 58 | void KalmanFilter::predict(KAL_MEAN &mean, KAL_COVA &covariance) 59 | { 60 | //revise the data; 61 | DETECTBOX std_pos; 62 | std_pos << _std_weight_position * mean(3), 63 | _std_weight_position * mean(3), 64 | 1e-2, 65 | _std_weight_position * mean(3); 66 | DETECTBOX std_vel; 67 | std_vel << _std_weight_velocity * mean(3), 68 | _std_weight_velocity * mean(3), 69 | 1e-5, 70 | _std_weight_velocity * mean(3); 71 | KAL_MEAN tmp; 72 | tmp.block<1,4>(0,0) = std_pos; 73 | tmp.block<1,4>(0,4) = std_vel; 74 | tmp = tmp.array().square(); 75 | KAL_COVA motion_cov = tmp.asDiagonal(); 76 | KAL_MEAN mean1 = this->_motion_mat * mean.transpose(); 77 | KAL_COVA covariance1 = this->_motion_mat * covariance *(_motion_mat.transpose()); 78 | covariance1 += motion_cov; 79 | 80 | mean = mean1; 81 | covariance = covariance1; 82 | } 83 | 84 | KAL_HDATA KalmanFilter::project(const KAL_MEAN &mean, const KAL_COVA &covariance) 85 | { 86 | DETECTBOX std; 87 | std << _std_weight_position * mean(3), _std_weight_position * mean(3), 88 | 1e-1, _std_weight_position * mean(3); 89 | KAL_HMEAN mean1 = _update_mat * mean.transpose(); 90 | KAL_HCOVA covariance1 = _update_mat * covariance * (_update_mat.transpose()); 91 | Eigen::Matrix diag = std.asDiagonal(); 92 | diag = diag.array().square().matrix(); 93 | covariance1 += diag; 94 | // covariance1.diagonal() << diag; 95 | return std::make_pair(mean1, covariance1); 96 | } 97 | 98 | KAL_DATA 99 | KalmanFilter::update( 100 | const KAL_MEAN &mean, 101 | const KAL_COVA &covariance, 102 | const DETECTBOX &measurement) 103 | { 104 | KAL_HDATA pa = project(mean, covariance); 105 | KAL_HMEAN projected_mean = pa.first; 106 | KAL_HCOVA projected_cov = pa.second; 107 | 108 | //chol_factor, lower = 109 | //scipy.linalg.cho_factor(projected_cov, lower=True, check_finite=False) 110 | //kalmain_gain = 111 | //scipy.linalg.cho_solve((cho_factor, lower), 112 | //np.dot(covariance, self._upadte_mat.T).T, 113 | //check_finite=False).T 114 | Eigen::Matrix B = (covariance * (_update_mat.transpose())).transpose(); 115 | Eigen::Matrix kalman_gain = (projected_cov.llt().solve(B)).transpose(); // eg.8x4 116 | Eigen::Matrix innovation = measurement - projected_mean; //eg.1x4 117 | auto tmp = innovation*(kalman_gain.transpose()); 118 | KAL_MEAN new_mean = (mean.array() + tmp.array()).matrix(); 119 | KAL_COVA new_covariance = covariance - kalman_gain*projected_cov*(kalman_gain.transpose()); 120 | return std::make_pair(new_mean, new_covariance); 121 | } 122 | 123 | Eigen::Matrix 124 | KalmanFilter::gating_distance( 125 | const KAL_MEAN &mean, 126 | const KAL_COVA &covariance, 127 | const std::vector &measurements, 128 | bool only_position) 129 | { 130 | KAL_HDATA pa = this->project(mean, covariance); 131 | if(only_position) { 132 | printf("not implement!"); 133 | exit(0); 134 | } 135 | KAL_HMEAN mean1 = pa.first; 136 | KAL_HCOVA covariance1 = pa.second; 137 | 138 | // Eigen::Matrix d(size, 4); 139 | DETECTBOXSS d(measurements.size(), 4); 140 | int pos = 0; 141 | for(DETECTBOX box:measurements) { 142 | d.row(pos++) = box - mean1; 143 | } 144 | Eigen::Matrix factor = covariance1.llt().matrixL(); 145 | Eigen::Matrix z = factor.triangularView().solve(d).transpose(); 146 | auto zz = ((z.array())*(z.array())).matrix(); 147 | auto square_maha = zz.colwise().sum(); 148 | return square_maha; 149 | } 150 | 151 | -------------------------------------------------------------------------------- /src/matching/src/linear_assignment.cpp: -------------------------------------------------------------------------------- 1 | #include "linear_assignment.h" 2 | #include "hungarianoper.h" 3 | 4 | linear_assignment *linear_assignment::instance = NULL; 5 | linear_assignment::linear_assignment() 6 | { 7 | } 8 | 9 | linear_assignment *linear_assignment::getInstance() 10 | { 11 | if(instance == NULL) instance = new linear_assignment(); 12 | return instance; 13 | } 14 | 15 | TRACHER_MATCHD 16 | linear_assignment::matching_cascade( 17 | tracker *distance_metric, 18 | tracker::GATED_METRIC_FUNC distance_metric_func, 19 | float max_distance, 20 | int cascade_depth, 21 | std::vector &tracks, 22 | const DETECTIONS &detections, 23 | std::vector& track_indices, 24 | std::vector detection_indices) 25 | { 26 | TRACHER_MATCHD res; 27 | //!!!python diff: track_indices will never be None. 28 | // if(track_indices.empty() == true) { 29 | // for(size_t i = 0; i < tracks.size(); i++) { 30 | // track_indices.push_back(i); 31 | // } 32 | // } 33 | 34 | //!!!python diff: detection_indices will always be None. 35 | for(size_t i = 0; i < detections.size(); i++) { 36 | detection_indices.push_back(int(i)); 37 | } 38 | 39 | std::vector unmatched_detections; 40 | unmatched_detections.assign(detection_indices.begin(), detection_indices.end()); 41 | res.matches.clear(); 42 | std::vector track_indices_l; 43 | 44 | std::map matches_trackid; 45 | for(int level = 0; level < cascade_depth; level++) { 46 | if(unmatched_detections.size() == 0) break; //No detections left; 47 | 48 | track_indices_l.clear(); 49 | for(int k:track_indices) { 50 | if(tracks[k].time_since_update == 1+level) 51 | track_indices_l.push_back(k); 52 | } 53 | if(track_indices_l.size() == 0) continue; //Nothing to match at this level. 54 | 55 | TRACHER_MATCHD tmp = min_cost_matching( 56 | distance_metric, distance_metric_func, 57 | max_distance, tracks, detections, track_indices_l, 58 | unmatched_detections); 59 | unmatched_detections.assign(tmp.unmatched_detections.begin(), tmp.unmatched_detections.end()); 60 | for(size_t i = 0; i < tmp.matches.size(); i++) { 61 | MATCH_DATA pa = tmp.matches[i]; 62 | res.matches.push_back(pa); 63 | matches_trackid.insert(pa); 64 | } 65 | } 66 | res.unmatched_detections.assign(unmatched_detections.begin(), unmatched_detections.end()); 67 | for(size_t i = 0; i < track_indices.size(); i++) { 68 | int tid = track_indices[i]; 69 | if(matches_trackid.find(tid) == matches_trackid.end()) 70 | res.unmatched_tracks.push_back(tid); 71 | } 72 | return res; 73 | } 74 | 75 | TRACHER_MATCHD 76 | linear_assignment::min_cost_matching(tracker *distance_metric, 77 | tracker::GATED_METRIC_FUNC distance_metric_func, 78 | float max_distance, 79 | std::vector &tracks, 80 | const DETECTIONS &detections, 81 | std::vector &track_indices, 82 | std::vector &detection_indices) 83 | { 84 | TRACHER_MATCHD res; 85 | //!!!python diff: track_indices && detection_indices will never be None. 86 | // if(track_indices.empty() == true) { 87 | // for(size_t i = 0; i < tracks.size(); i++) { 88 | // track_indices.push_back(i); 89 | // } 90 | // } 91 | // if(detection_indices.empty() == true) { 92 | // for(size_t i = 0; i < detections.size(); i++) { 93 | // detection_indices.push_back(int(i)); 94 | // } 95 | // } 96 | if((detection_indices.size() == 0) || (track_indices.size() == 0)) { 97 | res.matches.clear(); 98 | res.unmatched_tracks.assign(track_indices.begin(), track_indices.end()); 99 | res.unmatched_detections.assign(detection_indices.begin(), detection_indices.end()); 100 | return res; 101 | } 102 | DYNAMICM cost_matrix = (distance_metric->*(distance_metric_func))( 103 | tracks, detections, track_indices, detection_indices); 104 | for(int i = 0; i < cost_matrix.rows(); i++) { 105 | for(int j = 0; j < cost_matrix.cols(); j++) { 106 | float tmp = cost_matrix(i,j); 107 | if(tmp > max_distance) cost_matrix(i,j) = max_distance + 1e-5; 108 | } 109 | } 110 | Eigen::Matrix indices = HungarianOper::Solve(cost_matrix); 111 | res.matches.clear(); 112 | res.unmatched_tracks.clear(); 113 | res.unmatched_detections.clear(); 114 | for(size_t col = 0; col < detection_indices.size(); col++) { 115 | bool flag = false; 116 | for(int i = 0; i < indices.rows(); i++) 117 | if(indices(i, 1) == col) { flag = true; break;} 118 | if(flag == false)res.unmatched_detections.push_back(detection_indices[col]); 119 | } 120 | for(size_t row = 0; row < track_indices.size(); row++) { 121 | bool flag = false; 122 | for(int i = 0; i < indices.rows(); i++) 123 | if(indices(i, 0) == row) { flag = true; break; } 124 | if(flag == false) res.unmatched_tracks.push_back(track_indices[row]); 125 | } 126 | for(int i = 0; i < indices.rows(); i++) { 127 | int row = indices(i, 0); 128 | int col = indices(i, 1); 129 | 130 | int track_idx = track_indices[row]; 131 | int detection_idx = detection_indices[col]; 132 | if(cost_matrix(row, col) > max_distance) { 133 | res.unmatched_tracks.push_back(track_idx); 134 | res.unmatched_detections.push_back(detection_idx); 135 | } else res.matches.push_back(std::make_pair(track_idx, detection_idx)); 136 | } 137 | return res; 138 | } 139 | 140 | DYNAMICM 141 | linear_assignment::gate_cost_matrix( 142 | std::shared_ptr &kf, 143 | DYNAMICM &cost_matrix, 144 | std::vector &tracks, 145 | const DETECTIONS &detections, 146 | const std::vector &track_indices, 147 | const std::vector &detection_indices, 148 | float gated_cost, bool only_position) 149 | { 150 | int gating_dim = (only_position == true?2:4); 151 | double gating_threshold = KalmanFilter::chi2inv95[gating_dim]; 152 | std::vector measurements; 153 | for(int i:detection_indices) { 154 | DETECTION_ROW t = detections[i]; 155 | measurements.push_back(t.to_xyah()); 156 | } 157 | for(size_t i = 0; i < track_indices.size(); i++) { 158 | Track& track = tracks[track_indices[i]]; 159 | Eigen::Matrix gating_distance = kf->gating_distance( 160 | track.mean, track.covariance, measurements, only_position); 161 | for (int j = 0; j < gating_distance.cols(); j++) { 162 | if (gating_distance(0, j) > gating_threshold) cost_matrix(i, j) = gated_cost; 163 | } 164 | } 165 | return cost_matrix; 166 | } 167 | 168 | -------------------------------------------------------------------------------- /src/matching/src/nn_matching.cpp: -------------------------------------------------------------------------------- 1 | #include "nn_matching.h" 2 | #include "errmsg.h" 3 | 4 | using namespace Eigen; 5 | 6 | NearNeighborDisMetric::NearNeighborDisMetric( 7 | NearNeighborDisMetric::METRIC_TYPE metric, 8 | float matching_threshold, int budget) 9 | { 10 | if(metric == euclidean) { 11 | _metric = &NearNeighborDisMetric::_nneuclidean_distance; 12 | } else if (metric == cosine) { 13 | _metric = &NearNeighborDisMetric::_nncosine_distance; 14 | } else { 15 | errMsg::getInstance()->out( 16 | "nn_matching.cpp", 17 | "NearestNeighborDistanceMetric::NearestNeighborDistanceMetric", 18 | "Invalid metric; must be either 'euclidean' or 'cosine'", true); 19 | } 20 | this->mating_threshold = matching_threshold; 21 | this->budget = budget; 22 | this->samples.clear(); 23 | } 24 | 25 | /* 26 | void 27 | NearNeighborDisMetric::partial_fit( 28 | FEATURESS& features, 29 | std::vector targets, 30 | std::vector active_targets) 31 | { 32 | int size = targets.size(); 33 | for(int i = 0; i < size; i++) { 34 | FEATURE feature = features.row(i); 35 | int target = targets[i]; 36 | 37 | bool isActive = false; 38 | for(int k:active_targets) { 39 | if(k == target) { 40 | isActive = true; 41 | break; 42 | } 43 | } 44 | if(samples.find(target) != samples.end()) {//exist 45 | } else {//not exist 46 | // 47 | } 48 | }//each (feature,target) 49 | }*/ 50 | 51 | DYNAMICM 52 | NearNeighborDisMetric::distance( 53 | const FEATURESS &features, 54 | const std::vector& targets) 55 | { 56 | DYNAMICM cost_matrix = Eigen::MatrixXf::Zero(targets.size(), features.rows()); 57 | int idx = 0; 58 | for(int target:targets) { 59 | cost_matrix.row(idx) = (this->*_metric)(this->samples[target], features); 60 | idx++; 61 | } 62 | return cost_matrix; 63 | } 64 | 65 | void 66 | NearNeighborDisMetric::partial_fit( 67 | std::vector &tid_feats, 68 | std::vector &active_targets) 69 | { 70 | /*python code: 71 | * let feature(target_id) append to samples; 72 | * && delete not comfirmed target_id from samples. 73 | * update samples; 74 | */ 75 | for(TRACKER_DATA& data:tid_feats) { 76 | int track_id = data.first; 77 | FEATURESS newFeatOne = data.second; 78 | 79 | if(samples.find(track_id) != samples.end()) {//append 80 | int oldSize = samples[track_id].rows(); 81 | int addSize = newFeatOne.rows(); 82 | int newSize = oldSize + addSize; 83 | 84 | if(newSize <= this->budget) { 85 | FEATURESS newSampleFeatures(newSize, 128); 86 | newSampleFeatures.block(0,0, oldSize, 128) = samples[track_id]; 87 | newSampleFeatures.block(oldSize, 0, addSize, 128) = newFeatOne; 88 | samples[track_id] = newSampleFeatures; 89 | } else { 90 | if(oldSize < this->budget) {//original space is not enough; 91 | FEATURESS newSampleFeatures(this->budget, 128); 92 | if(addSize >= this->budget) { 93 | newSampleFeatures = newFeatOne.block(0, 0, this->budget, 128); 94 | } else { 95 | newSampleFeatures.block(0, 0, this->budget-addSize, 128) = 96 | samples[track_id].block(addSize-1, 0, this->budget-addSize, 128).eval(); 97 | newSampleFeatures.block(this->budget-addSize, 0, addSize, 128) = newFeatOne; 98 | } 99 | samples[track_id] = newSampleFeatures; 100 | } else {//original space is ok; 101 | if(addSize >= this->budget) { 102 | samples[track_id] = newFeatOne.block(0,0, this->budget, 128); 103 | } else { 104 | samples[track_id].block(0, 0, this->budget-addSize, 128) = 105 | samples[track_id].block(addSize-1, 0, this->budget-addSize, 128).eval(); 106 | samples[track_id].block(this->budget-addSize, 0, addSize, 128) = newFeatOne; 107 | } 108 | } 109 | } 110 | } else {//not exit, create new one; 111 | samples[track_id] = newFeatOne; 112 | } 113 | }//add features; 114 | 115 | //erase the samples which not in active_targets; 116 | for(std::map::iterator i = samples.begin(); i != samples.end();) { 117 | bool flag = false; 118 | for(int j:active_targets) if(j == i->first) { flag=true; break; } 119 | if(flag == false) samples.erase(i++); 120 | else i++; 121 | } 122 | } 123 | 124 | Eigen::VectorXf 125 | NearNeighborDisMetric::_nncosine_distance( 126 | const FEATURESS &x, const FEATURESS &y) 127 | { 128 | MatrixXf distances = _cosine_distance(x,y); 129 | VectorXf res = distances.colwise().minCoeff().transpose(); 130 | return res; 131 | } 132 | 133 | Eigen::VectorXf 134 | NearNeighborDisMetric::_nneuclidean_distance( 135 | const FEATURESS &x, const FEATURESS &y) 136 | { 137 | MatrixXf distances = _pdist(x,y); 138 | VectorXf res = distances.colwise().maxCoeff().transpose(); 139 | res = res.array().max(VectorXf::Zero(res.rows()).array()); 140 | return res; 141 | } 142 | 143 | Eigen::MatrixXf 144 | NearNeighborDisMetric::_pdist(const FEATURESS &x, const FEATURESS &y) 145 | { 146 | int len1 = x.rows(), len2 = y.rows(); 147 | if(len1 == 0 || len2 == 0) { 148 | return Eigen::MatrixXf::Zero(len1, len2); 149 | } 150 | MatrixXf res = x * y.transpose()* -2; 151 | res = res.colwise() + x.rowwise().squaredNorm(); 152 | res = res.rowwise() + y.rowwise().squaredNorm().transpose(); 153 | res = res.array().max(MatrixXf::Zero(res.rows(), res.cols()).array()); 154 | return res; 155 | } 156 | 157 | Eigen::MatrixXf 158 | NearNeighborDisMetric::_cosine_distance( 159 | const FEATURESS & a, 160 | const FEATURESS& b, bool data_is_normalized) { 161 | if(data_is_normalized == true) { 162 | //undo: 163 | assert(false); 164 | } 165 | MatrixXf res = 1. - (a*b.transpose()).array(); 166 | return res; 167 | } 168 | -------------------------------------------------------------------------------- /src/matching/src/track.cpp: -------------------------------------------------------------------------------- 1 | #include "track.h" 2 | 3 | Track::Track(KAL_MEAN& mean, KAL_COVA& covariance, int track_id, int n_init, int max_age, const FEATURE& feature, const std::string& det_class, const cv::Scalar& col) 4 | { 5 | this->mean = mean; 6 | this->covariance = covariance; 7 | this->track_id = track_id; 8 | this->hits = 1; 9 | this->age = 1; 10 | this->time_since_update = 0; 11 | this->state = TrackState::Tentative; 12 | features = FEATURESS(1, 128); 13 | features.row(0) = feature;//features.rows() must = 0; 14 | this->detection_class = det_class; 15 | this->_n_init = n_init; 16 | this->_max_age = max_age; 17 | this->color = col; 18 | } 19 | 20 | void Track::predit(std::shared_ptr &kf) 21 | { 22 | /*Propagate the state distribution to the current time step using a 23 | Kalman filter prediction step. 24 | 25 | Parameters 26 | ---------- 27 | kf : kalman_filter.KalmanFilter 28 | The Kalman filter. 29 | */ 30 | 31 | kf->predict(this->mean, this->covariance); 32 | this->age += 1; 33 | this->time_since_update += 1; 34 | } 35 | 36 | void Track::update(std::shared_ptr &kf, const DETECTION_ROW& detection) 37 | { 38 | KAL_DATA pa = kf->update(this->mean, this->covariance, detection.to_xyah()); 39 | this->mean = pa.first; 40 | this->covariance = pa.second; 41 | 42 | featuresAppendOne(detection.feature); 43 | // this->features.row(features.rows()) = detection.feature; 44 | this->hits += 1; 45 | this->time_since_update = 0; 46 | if(this->state == TrackState::Tentative && this->hits >= this->_n_init) { 47 | this->state = TrackState::Confirmed; 48 | } 49 | } 50 | 51 | void Track::mark_missed() 52 | { 53 | if(this->state == TrackState::Tentative) { 54 | this->state = TrackState::Deleted; 55 | } else if(this->time_since_update > this->_max_age) { 56 | this->state = TrackState::Deleted; 57 | } 58 | } 59 | 60 | bool Track::is_confirmed() 61 | { 62 | return this->state == TrackState::Confirmed; 63 | } 64 | 65 | bool Track::is_deleted() 66 | { 67 | return this->state == TrackState::Deleted; 68 | } 69 | 70 | bool Track::is_tentative() 71 | { 72 | return this->state == TrackState::Tentative; 73 | } 74 | 75 | DETECTBOX Track::to_tlwh() 76 | { 77 | DETECTBOX ret = mean.leftCols(4); 78 | ret(2) *= ret(3); 79 | ret.leftCols(2) -= (ret.rightCols(2)/2); 80 | return ret; 81 | } 82 | 83 | void Track::featuresAppendOne(const FEATURE &f) 84 | { 85 | int size = this->features.rows(); 86 | FEATURESS newfeatures = FEATURESS(size+1, 128); 87 | newfeatures.block(0, 0, size, 128) = this->features; 88 | newfeatures.row(size) = f; 89 | features = newfeatures; 90 | } 91 | -------------------------------------------------------------------------------- /src/matching/src/tracker.cpp: -------------------------------------------------------------------------------- 1 | #include "tracker.h" 2 | #include "nn_matching.h" 3 | #include "model.h" 4 | #include "linear_assignment.h" 5 | using namespace std; 6 | 7 | //#define MY_inner_DEBUG 8 | #ifdef MY_inner_DEBUG 9 | #include 10 | #include 11 | #endif 12 | 13 | cv::RNG rng(12345); 14 | 15 | tracker::tracker(float max_cosine_distance, int nn_budget, 16 | float max_iou_distance, int max_age, int n_init, float dt) 17 | { 18 | _init(max_cosine_distance, nn_budget, max_iou_distance, max_age, n_init, dt); 19 | } 20 | 21 | 22 | tracker::tracker(const DeepSortParam& params) 23 | { 24 | _init(params.args_max_cosine_distance(), params.args_nn_budget(), params.max_iou_distance(), 25 | params.max_age(), params.n_init(), params.dt(), params.classes()); 26 | } 27 | 28 | void tracker::_init(float max_cosine_distance, int nn_budget, 29 | float max_iou_distance, int max_age, int n_init, float dt, const std::vector& classes) 30 | { 31 | this->metric = std::shared_ptr (new NearNeighborDisMetric( 32 | NearNeighborDisMetric::METRIC_TYPE::cosine, 33 | max_cosine_distance, nn_budget)); 34 | this->max_iou_distance = max_iou_distance; 35 | this->max_age = max_age; 36 | this->n_init = n_init; 37 | this->dt = dt; 38 | 39 | this->kf = std::shared_ptr(new KalmanFilter(double(dt))); 40 | this->tracks.clear(); 41 | this->_next_idx = 1; 42 | this->detection_classes = classes; 43 | 44 | for(const auto& c : classes) 45 | { 46 | color_map.insert(std::make_pair(c, cv::Scalar(rng.uniform(0,255), rng.uniform(0, 255), rng.uniform(0, 255)))); 47 | } 48 | } 49 | 50 | void tracker::predict() 51 | { 52 | for(Track& track:tracks) { 53 | track.predit(kf); 54 | } 55 | } 56 | 57 | void tracker::update(const DETECTIONS &detections) 58 | { 59 | TRACHER_MATCHD res; 60 | _match(detections, res); 61 | 62 | vector& matches = res.matches; 63 | 64 | for(MATCH_DATA& data:matches) 65 | { 66 | int track_idx = data.first; 67 | int detection_idx = data.second; 68 | tracks[track_idx].update(this->kf, detections[detection_idx]); 69 | } 70 | vector& unmatched_tracks = res.unmatched_tracks; 71 | 72 | for(int& track_idx:unmatched_tracks) 73 | { 74 | this->tracks[track_idx].mark_missed(); 75 | } 76 | vector& unmatched_detections = res.unmatched_detections; 77 | 78 | for(int& detection_idx:unmatched_detections) 79 | { 80 | this->_initiate_track(detections[detection_idx]); 81 | } 82 | 83 | vector::iterator it; 84 | for(it = tracks.begin(); it != tracks.end();) 85 | { 86 | if((*it).is_deleted()) it = tracks.erase(it); 87 | else ++it; 88 | } 89 | 90 | vector active_targets; 91 | vector tid_features; 92 | for (Track& track:tracks) 93 | { 94 | if(track.is_confirmed() == false) continue; 95 | active_targets.push_back(track.track_id); 96 | tid_features.push_back(std::make_pair(track.track_id, track.features)); 97 | FEATURESS t = FEATURESS(0, 128); 98 | track.features = t; 99 | } 100 | this->metric->partial_fit(tid_features, active_targets); 101 | } 102 | 103 | void tracker::_match(const DETECTIONS &detections, TRACHER_MATCHD &res) 104 | { 105 | vector confirmed_tracks; 106 | vector unconfirmed_tracks; 107 | int idx = 0; 108 | for(Track& t:tracks) 109 | { 110 | if(t.is_confirmed()) confirmed_tracks.push_back(idx); 111 | else unconfirmed_tracks.push_back(idx); 112 | idx++; 113 | } 114 | 115 | TRACHER_MATCHD matcha = linear_assignment::getInstance()->matching_cascade( 116 | this, &tracker::gated_matric, 117 | this->metric->mating_threshold, 118 | this->max_age, 119 | this->tracks, 120 | detections, 121 | confirmed_tracks); 122 | vector iou_track_candidates; 123 | iou_track_candidates.assign(unconfirmed_tracks.begin(), unconfirmed_tracks.end()); 124 | 125 | vector::iterator it; 126 | for(it = matcha.unmatched_tracks.begin(); it != matcha.unmatched_tracks.end();) 127 | { 128 | int idx = *it; 129 | if(tracks[idx].time_since_update == 1) //push into unconfirmed 130 | { 131 | iou_track_candidates.push_back(idx); 132 | it = matcha.unmatched_tracks.erase(it); 133 | continue; 134 | } 135 | ++it; 136 | } 137 | 138 | TRACHER_MATCHD matchb = linear_assignment::getInstance()->min_cost_matching( 139 | this, &tracker::iou_cost, 140 | this->max_iou_distance, 141 | this->tracks, 142 | detections, 143 | iou_track_candidates, 144 | matcha.unmatched_detections); 145 | //get result: 146 | res.matches.assign(matcha.matches.begin(), matcha.matches.end()); 147 | res.matches.insert(res.matches.end(), matchb.matches.begin(), matchb.matches.end()); 148 | //unmatched_tracks; 149 | res.unmatched_tracks.assign( 150 | matcha.unmatched_tracks.begin(), 151 | matcha.unmatched_tracks.end()); 152 | res.unmatched_tracks.insert( 153 | res.unmatched_tracks.end(), 154 | matchb.unmatched_tracks.begin(), 155 | matchb.unmatched_tracks.end()); 156 | res.unmatched_detections.assign( 157 | matchb.unmatched_detections.begin(), 158 | matchb.unmatched_detections.end()); 159 | } 160 | 161 | void tracker::_initiate_track(const DETECTION_ROW &detection) 162 | { 163 | KAL_DATA data = kf->initiate(detection.to_xyah()); 164 | KAL_MEAN mean = data.first; 165 | KAL_COVA covariance = data.second; 166 | std::string detection_class = ""; 167 | cv::Scalar color = cv::Scalar(255, 255, 0); 168 | 169 | if(detection_classes.size() !=0) 170 | { 171 | int size = int(detection_classes.size()); 172 | if(detection.class_num < size) 173 | { 174 | detection_class = detection_classes[detection.class_num]; 175 | color = color_map[detection_class]; 176 | } 177 | } 178 | 179 | this->tracks.push_back(Track(mean, covariance, this->_next_idx, this->n_init, 180 | this->max_age, detection.feature, detection_class, color)); 181 | _next_idx += 1; 182 | } 183 | 184 | DYNAMICM tracker::gated_matric( 185 | std::vector &tracks, 186 | const DETECTIONS &dets, 187 | const std::vector& track_indices, 188 | const std::vector& detection_indices) 189 | { 190 | FEATURESS features(detection_indices.size(), 128); 191 | int pos = 0; 192 | for(int i:detection_indices) { 193 | features.row(pos++) = dets[i].feature; 194 | } 195 | vector targets; 196 | for(int i:track_indices) { 197 | targets.push_back(tracks[i].track_id); 198 | } 199 | DYNAMICM cost_matrix = this->metric->distance(features, targets); 200 | DYNAMICM res = linear_assignment::getInstance()->gate_cost_matrix( 201 | this->kf, cost_matrix, tracks, dets, track_indices, 202 | detection_indices); 203 | return res; 204 | } 205 | 206 | DYNAMICM 207 | tracker::iou_cost( 208 | std::vector &tracks, 209 | const DETECTIONS &dets, 210 | const std::vector& track_indices, 211 | const std::vector& detection_indices) 212 | { 213 | int rows = track_indices.size(); 214 | int cols = detection_indices.size(); 215 | DYNAMICM cost_matrix = Eigen::MatrixXf::Zero(rows, cols); 216 | for(int i = 0; i < rows; i++) { 217 | int track_idx = track_indices[i]; 218 | if(tracks[track_idx].time_since_update > 1) { 219 | cost_matrix.row(i) = Eigen::RowVectorXf::Constant(cols, INFTY_COST); 220 | continue; 221 | } 222 | DETECTBOX bbox = tracks[track_idx].to_tlwh(); 223 | int csize = detection_indices.size(); 224 | DETECTBOXSS candidates(csize, 4); 225 | for(int k = 0; k < csize; k++) candidates.row(k) = dets[detection_indices[k]].tlwh; 226 | Eigen::RowVectorXf rowV = (1. - iou(bbox, candidates).array()).matrix().transpose(); 227 | cost_matrix.row(i) = rowV; 228 | } 229 | return cost_matrix; 230 | } 231 | 232 | Eigen::VectorXf 233 | tracker::iou(DETECTBOX& bbox, DETECTBOXSS& candidates) 234 | { 235 | float bbox_tl_1 = bbox[0]; 236 | float bbox_tl_2 = bbox[1]; 237 | float bbox_br_1 = bbox[0] + bbox[2]; 238 | float bbox_br_2 = bbox[1] + bbox[3]; 239 | float area_bbox = bbox[2] * bbox[3]; 240 | 241 | Eigen::Matrix candidates_tl; 242 | Eigen::Matrix candidates_br; 243 | candidates_tl = candidates.leftCols(2) ; 244 | candidates_br = candidates.rightCols(2) + candidates_tl; 245 | 246 | int size = int(candidates.rows()); 247 | // Eigen::VectorXf area_intersection(size); 248 | // Eigen::VectorXf area_candidates(size); 249 | Eigen::VectorXf res(size); 250 | for(int i = 0; i < size; i++) 251 | { 252 | float tl_1 = std::max(bbox_tl_1, candidates_tl(i, 0)); 253 | float tl_2 = std::max(bbox_tl_2, candidates_tl(i, 1)); 254 | float br_1 = std::min(bbox_br_1, candidates_br(i, 0)); 255 | float br_2 = std::min(bbox_br_2, candidates_br(i, 1)); 256 | 257 | float w = br_1 - tl_1; w = (w < 0? 0: w); 258 | float h = br_2 - tl_2; h = (h < 0? 0: h); 259 | float area_intersection = w * h; 260 | float area_candidates = candidates(i, 2) * candidates(i, 3); 261 | res[i] = area_intersection/(area_bbox + area_candidates - area_intersection); 262 | } 263 | //#ifdef MY_inner_DEBUG 264 | // std::cout << res << std::endl; 265 | //#endif 266 | return res; 267 | } 268 | 269 | -------------------------------------------------------------------------------- /src/thirdPart/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | function(thirdpart) 2 | include_directories(${PROJECT_BINARY_DIR}/../src/thirdPart/) 3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/thirdPart/) 4 | #add_definitions(-DUSE_FACE_NET) 5 | 6 | file(GLOB_RECURSE THIRD_PART_SRC "src/thirdPart/*.cpp" "src/thirdPart/munkres/*.cpp" "src/thirdPart/munkres/adapters*.cpp") 7 | 8 | add_library(thirdpart SHARED ${THIRD_PART_SRC}) 9 | target_link_libraries(thirdpart ${Boost_LIBRARIES}) 10 | 11 | endfunction() -------------------------------------------------------------------------------- /src/thirdPart/include/adapter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Miroslav Krajicek 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef _ADAPTER_H_ 20 | #define _ADAPTER_H_ 21 | 22 | #include "matrix.h" 23 | #include "munkres.h" 24 | 25 | template class Adapter 26 | { 27 | public: 28 | virtual Matrix convertToMatrix(const Container &con) const = 0; 29 | virtual void convertFromMatrix(Container &con, const Matrix &matrix) const = 0; 30 | virtual void solve(Container &con) 31 | { 32 | auto matrix = convertToMatrix(con); 33 | m_munkres.solve(matrix); 34 | convertFromMatrix(con, matrix); 35 | } 36 | protected: 37 | Munkres m_munkres; 38 | }; 39 | 40 | #endif /* _ADAPTER_H_ */ 41 | -------------------------------------------------------------------------------- /src/thirdPart/include/boostmatrixadapter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Miroslav Krajicek 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef _BOOSTMATRIXADAPTER_H_ 20 | #define _BOOSTMATRIXADAPTER_H_ 21 | 22 | #include "adapter.h" 23 | #ifndef WIN32 24 | #include 25 | #endif 26 | #include 27 | 28 | template class BoostMatrixAdapter : public Adapter > 29 | { 30 | public: 31 | virtual Matrix convertToMatrix(const boost::numeric::ublas::matrix &boost_matrix) const override 32 | { 33 | const auto rows = boost_matrix.size1 (); 34 | const auto columns = boost_matrix.size2 (); 35 | Matrix matrix (rows, columns); 36 | for (int i = 0; i < rows; ++i) { 37 | for (int j = 0; j < columns; ++j) { 38 | matrix (i, j) = boost_matrix (i, j); 39 | } 40 | } 41 | return matrix; 42 | } 43 | 44 | virtual void convertFromMatrix(boost::numeric::ublas::matrix &boost_matrix,const Matrix &matrix) const override 45 | { 46 | const auto rows = matrix.rows(); 47 | const auto columns = matrix.columns(); 48 | for (int i = 0; i < rows; ++i) { 49 | for (int j = 0; j < columns; ++j) { 50 | boost_matrix (i, j) = matrix (i, j); 51 | } 52 | } 53 | } 54 | }; 55 | 56 | #endif /* _BOOSTMATRIXADAPTER_H_ */ 57 | -------------------------------------------------------------------------------- /src/thirdPart/include/hungarianoper.h: -------------------------------------------------------------------------------- 1 | #ifndef HUNGARIANOPER_H 2 | #define HUNGARIANOPER_H 3 | #include "munkres.h" 4 | #include "boostmatrixadapter.h" 5 | #include "dataType.h" 6 | 7 | class HungarianOper { 8 | public: 9 | static Eigen::Matrix Solve(const DYNAMICM &cost_matrix); 10 | }; 11 | 12 | #endif // HUNGARIANOPER_H 13 | -------------------------------------------------------------------------------- /src/thirdPart/include/matrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 John Weaver 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef _MATRIX_H_ 20 | #define _MATRIX_H_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #define XYZMIN(x, y) (x)<(y)?(x):(y) 30 | #define XYZMAX(x, y) (x)>(y)?(x):(y) 31 | 32 | template 33 | class Matrix { 34 | public: 35 | Matrix(){ 36 | m_rows = 0; 37 | m_columns = 0; 38 | m_matrix = nullptr; 39 | } 40 | Matrix(const size_t rows, const size_t columns) { 41 | m_matrix = nullptr; 42 | resize(rows, columns); 43 | } 44 | Matrix(const std::initializer_list> init) { 45 | m_matrix = nullptr; 46 | m_rows = init.size(); 47 | if ( m_rows == 0 ) { 48 | m_columns = 0; 49 | } else { 50 | m_columns = init.begin()->size(); 51 | if ( m_columns > 0 ) { 52 | resize(m_rows, m_columns); 53 | } 54 | } 55 | 56 | size_t i = 0, j; 57 | for ( auto row = init.begin() ; row != init.end() ; ++row, ++i ) { 58 | assert ( row->size() == m_columns && "All rows must have the same number of columns." ); 59 | j = 0; 60 | for ( auto value = row->begin() ; value != row->end() ; ++value, ++j ) { 61 | m_matrix[i][j] = *value; 62 | } 63 | } 64 | } 65 | Matrix(const Matrix &other) { 66 | if ( other.m_matrix != nullptr ) { 67 | // copy arrays 68 | m_matrix = nullptr; 69 | resize(other.m_rows, other.m_columns); 70 | for ( size_t i = 0 ; i < m_rows ; i++ ) { 71 | for ( size_t j = 0 ; j < m_columns ; j++ ) { 72 | m_matrix[i][j] = other.m_matrix[i][j]; 73 | } 74 | } 75 | } else { 76 | m_matrix = nullptr; 77 | m_rows = 0; 78 | m_columns = 0; 79 | } 80 | } 81 | Matrix & operator= (const Matrix &other){ 82 | if ( other.m_matrix != nullptr ) { 83 | // copy arrays 84 | resize(other.m_rows, other.m_columns); 85 | for ( size_t i = 0 ; i < m_rows ; i++ ) { 86 | for ( size_t j = 0 ; j < m_columns ; j++ ) { 87 | m_matrix[i][j] = other.m_matrix[i][j]; 88 | } 89 | } 90 | } else { 91 | // free arrays 92 | for ( size_t i = 0 ; i < m_columns ; i++ ) { 93 | delete [] m_matrix[i]; 94 | } 95 | 96 | delete [] m_matrix; 97 | 98 | m_matrix = nullptr; 99 | m_rows = 0; 100 | m_columns = 0; 101 | } 102 | 103 | return *this; 104 | } 105 | ~Matrix(){ 106 | if ( m_matrix != nullptr ) { 107 | // free arrays 108 | for ( size_t i = 0 ; i < m_rows ; i++ ) { 109 | delete [] m_matrix[i]; 110 | } 111 | 112 | delete [] m_matrix; 113 | } 114 | m_matrix = nullptr; 115 | } 116 | // all operations modify the matrix in-place. 117 | void resize(const size_t rows, const size_t columns, const T default_value = 0) { 118 | assert ( rows > 0 && columns > 0 && "Columns and rows must exist." ); 119 | 120 | if ( m_matrix == nullptr ) { 121 | // alloc arrays 122 | m_matrix = new T*[rows]; // rows 123 | for ( size_t i = 0 ; i < rows ; i++ ) { 124 | m_matrix[i] = new T[columns]; // columns 125 | } 126 | 127 | m_rows = rows; 128 | m_columns = columns; 129 | clear(); 130 | } else { 131 | // save array pointer 132 | T **new_matrix; 133 | // alloc new arrays 134 | new_matrix = new T*[rows]; // rows 135 | for ( size_t i = 0 ; i < rows ; i++ ) { 136 | new_matrix[i] = new T[columns]; // columns 137 | for ( size_t j = 0 ; j < columns ; j++ ) { 138 | new_matrix[i][j] = default_value; 139 | } 140 | } 141 | 142 | // copy data from saved pointer to new arrays 143 | size_t minrows = XYZMIN(rows, m_rows); 144 | size_t mincols = XYZMIN(columns, m_columns); 145 | for ( size_t x = 0 ; x < minrows ; x++ ) { 146 | for ( size_t y = 0 ; y < mincols ; y++ ) { 147 | new_matrix[x][y] = m_matrix[x][y]; 148 | } 149 | } 150 | 151 | // delete old arrays 152 | if ( m_matrix != nullptr ) { 153 | for ( size_t i = 0 ; i < m_rows ; i++ ) { 154 | delete [] m_matrix[i]; 155 | } 156 | 157 | delete [] m_matrix; 158 | } 159 | 160 | m_matrix = new_matrix; 161 | } 162 | 163 | m_rows = rows; 164 | m_columns = columns; 165 | } 166 | void clear() { 167 | assert( m_matrix != nullptr ); 168 | 169 | for ( size_t i = 0 ; i < m_rows ; i++ ) { 170 | for ( size_t j = 0 ; j < m_columns ; j++ ) { 171 | m_matrix[i][j] = 0; 172 | } 173 | } 174 | } 175 | T& operator () (const size_t x, const size_t y) { 176 | assert ( x < m_rows ); 177 | assert ( y < m_columns ); 178 | assert ( m_matrix != nullptr ); 179 | return m_matrix[x][y]; 180 | } 181 | 182 | const T& operator () (const size_t x, const size_t y) const { 183 | assert ( x < m_rows ); 184 | assert ( y < m_columns ); 185 | assert ( m_matrix != nullptr ); 186 | return m_matrix[x][y]; 187 | } 188 | const T mmin() const { 189 | assert( m_matrix != nullptr ); 190 | assert ( m_rows > 0 ); 191 | assert ( m_columns > 0 ); 192 | T min = m_matrix[0][0]; 193 | 194 | for ( size_t i = 0 ; i < m_rows ; i++ ) { 195 | for ( size_t j = 0 ; j < m_columns ; j++ ) { 196 | min = std::min(min, m_matrix[i][j]); 197 | } 198 | } 199 | 200 | return min; 201 | } 202 | 203 | const T mmax() const { 204 | assert( m_matrix != nullptr ); 205 | assert ( m_rows > 0 ); 206 | assert ( m_columns > 0 ); 207 | T max = m_matrix[0][0]; 208 | 209 | for ( size_t i = 0 ; i < m_rows ; i++ ) { 210 | for ( size_t j = 0 ; j < m_columns ; j++ ) { 211 | max = std::max(max, m_matrix[i][j]); 212 | } 213 | } 214 | 215 | return max; 216 | } 217 | inline size_t minsize() { return ((m_rows < m_columns) ? m_rows : m_columns); } 218 | inline size_t columns() const { return m_columns;} 219 | inline size_t rows() const { return m_rows;} 220 | 221 | friend std::ostream& operator<<(std::ostream& os, const Matrix &matrix) 222 | { 223 | os << "Matrix:" << std::endl; 224 | for (size_t row = 0 ; row < matrix.rows() ; row++ ) 225 | { 226 | for (size_t col = 0 ; col < matrix.columns() ; col++ ) 227 | { 228 | os.width(8); 229 | os << matrix(row, col) << ","; 230 | } 231 | os << std::endl; 232 | } 233 | return os; 234 | } 235 | 236 | private: 237 | T **m_matrix; 238 | size_t m_rows; 239 | size_t m_columns; 240 | }; 241 | 242 | //#ifndef USE_EXPORT_KEYWORD 243 | //#include "matrix.cpp" 244 | ////#define export /*export*/ 245 | //#endif 246 | 247 | #endif /* !defined(_MATRIX_H_) */ 248 | 249 | -------------------------------------------------------------------------------- /src/thirdPart/include/munkres.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 John Weaver 3 | * Copyright (c) 2015 Miroslav Krajicek 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef _MUNKRES_H_ 21 | #define _MUNKRES_H_ 22 | 23 | #include "matrix.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | template class Munkres 34 | { 35 | static constexpr int NORMAL = 0; 36 | static constexpr int STAR = 1; 37 | static constexpr int PRIME = 2; 38 | public: 39 | 40 | /* 41 | * 42 | * Linear assignment problem solution 43 | * [modifies matrix in-place.] 44 | * matrix(row,col): row major format assumed. 45 | * 46 | * Assignments are remaining 0 values 47 | * (extra 0 values are replaced with -1) 48 | * 49 | */ 50 | void solve(Matrix &m) { 51 | const size_t rows = m.rows(), 52 | columns = m.columns(), 53 | size = XYZMAX(rows, columns); 54 | 55 | #ifdef DEBUG 56 | std::cout << "Munkres input: " << m << std::endl; 57 | #endif 58 | 59 | // Copy input matrix 60 | this->matrix = m; 61 | 62 | if ( rows != columns ) { 63 | // If the input matrix isn't square, make it square 64 | // and fill the empty values with the largest value present 65 | // in the matrix. 66 | matrix.resize(size, size, matrix.mmax()); 67 | } 68 | 69 | 70 | // STAR == 1 == starred, PRIME == 2 == primed 71 | mask_matrix.resize(size, size); 72 | row_mask.resize(size, false); 73 | col_mask.resize(size, false); 74 | 75 | // Prepare the matrix values... 76 | 77 | // If there were any infinities, replace them with a value greater 78 | // than the maximum value in the matrix. 79 | replace_infinites(matrix); 80 | 81 | minimize_along_direction(matrix, rows >= columns); 82 | minimize_along_direction(matrix, rows < columns); 83 | 84 | // Follow the steps 85 | int step = 1; 86 | while ( step ) 87 | { 88 | switch ( step ) 89 | { 90 | case 1: 91 | step = step1(); 92 | // step is always 2 93 | break; 94 | case 2: 95 | step = step2(); 96 | // step is always either 0 or 3 97 | break; 98 | case 3: 99 | step = step3(); 100 | // step in [3, 4, 5] 101 | break; 102 | case 4: 103 | step = step4(); 104 | // step is always 2 105 | break; 106 | case 5: 107 | step = step5(); 108 | // step is always 3 109 | break; 110 | } 111 | } 112 | 113 | // Store results 114 | for ( size_t row = 0 ; row < size ; row++ ) 115 | { 116 | for ( size_t col = 0 ; col < size ; col++ ) 117 | { 118 | if ( mask_matrix(row, col) == STAR ) 119 | { 120 | matrix(row, col) = 0; 121 | } 122 | else 123 | { 124 | matrix(row, col) = -1; 125 | } 126 | } 127 | } 128 | 129 | #ifdef DEBUG 130 | std::cout << "Munkres output: " << matrix << std::endl; 131 | #endif 132 | // Remove the excess rows or columns that we added to fit the 133 | // input to a square matrix. 134 | matrix.resize(rows, columns); 135 | 136 | m = matrix; 137 | 138 | row_mask.clear(); 139 | col_mask.clear(); 140 | // delete [] row_mask; 141 | // delete [] col_mask; 142 | } 143 | 144 | static void replace_infinites(Matrix &matrix) 145 | { 146 | const size_t rows = matrix.rows(), 147 | columns = matrix.columns(); 148 | //assert( rows > 0 && columns > 0 ); 149 | double max = matrix(0, 0); 150 | constexpr auto infinity = std::numeric_limits::infinity(); 151 | 152 | // Find the greatest value in the matrix that isn't infinity. 153 | for ( size_t row = 0 ; row < rows ; row++ ) 154 | { 155 | for ( size_t col = 0 ; col < columns ; col++ ) 156 | { 157 | if ( matrix(row, col) != infinity ) 158 | { 159 | if ( max == infinity ) 160 | { 161 | max = matrix(row, col); 162 | } 163 | else 164 | { 165 | max = XYZMAX(max, matrix(row, col)); 166 | } 167 | } 168 | } 169 | } 170 | 171 | // a value higher than the maximum value present in the matrix. 172 | if ( max == infinity ) { 173 | // This case only occurs when all values are infinite. 174 | max = 0; 175 | } else { 176 | max++; 177 | } 178 | 179 | for ( size_t row = 0 ; row < rows ; row++ ) { 180 | for ( size_t col = 0 ; col < columns ; col++ ) { 181 | if ( matrix(row, col) == infinity ) { 182 | matrix(row, col) = max; 183 | } 184 | } 185 | } 186 | 187 | } 188 | static void minimize_along_direction(Matrix &matrix, const bool over_columns) { 189 | const size_t outer_size = over_columns ? matrix.columns() : matrix.rows(), 190 | inner_size = over_columns ? matrix.rows() : matrix.columns(); 191 | 192 | // Look for a minimum value to subtract from all values along 193 | // the "outer" direction. 194 | for ( size_t i = 0 ; i < outer_size ; i++ ) { 195 | double min = over_columns ? matrix(0, i) : matrix(i, 0); 196 | 197 | // As long as the current minimum is greater than zero, 198 | // keep looking for the minimum. 199 | // Start at one because we already have the 0th value in min. 200 | for ( size_t j = 1 ; j < inner_size && min > 0 ; j++ ) { 201 | min = XYZMIN( 202 | min, 203 | over_columns ? matrix(j, i) : matrix(i, j)); 204 | } 205 | 206 | if ( min > 0 ) { 207 | for ( size_t j = 0 ; j < inner_size ; j++ ) { 208 | if ( over_columns ) { 209 | matrix(j, i) -= min; 210 | } else { 211 | matrix(i, j) -= min; 212 | } 213 | } 214 | } 215 | } 216 | } 217 | 218 | private: 219 | 220 | inline bool find_uncovered_in_matrix(const double item, size_t &row, size_t &col) const { 221 | const size_t rows = matrix.rows(), 222 | columns = matrix.columns(); 223 | 224 | for ( row = 0 ; row < rows ; row++ ) { 225 | if ( !row_mask[row] ) { 226 | for ( col = 0 ; col < columns ; col++ ) { 227 | if ( !col_mask[col] ) { 228 | if ( matrix(row,col) == item ) { 229 | return true; 230 | } 231 | } 232 | } 233 | } 234 | } 235 | 236 | return false; 237 | } 238 | 239 | bool pair_in_list(const std::pair &needle, const std::list > &haystack) { 240 | for ( std::list >::const_iterator i = haystack.begin() ; i != haystack.end() ; i++ ) { 241 | if ( needle == *i ) { 242 | return true; 243 | } 244 | } 245 | 246 | return false; 247 | } 248 | 249 | int step1() { 250 | const size_t rows = matrix.rows(), 251 | columns = matrix.columns(); 252 | 253 | for ( size_t row = 0 ; row < rows ; row++ ) { 254 | for ( size_t col = 0 ; col < columns ; col++ ) { 255 | if ( 0 == matrix(row, col) ) { 256 | for ( size_t nrow = 0 ; nrow < row ; nrow++ ) 257 | if ( STAR == mask_matrix(nrow,col) ) 258 | goto next_column; 259 | 260 | mask_matrix(row,col) = STAR; 261 | goto next_row; 262 | } 263 | next_column:; 264 | } 265 | next_row:; 266 | } 267 | 268 | return 2; 269 | } 270 | 271 | int step2() { 272 | const size_t rows = matrix.rows(), 273 | columns = matrix.columns(); 274 | size_t covercount = 0; 275 | 276 | for ( size_t row = 0 ; row < rows ; row++ ) 277 | for ( size_t col = 0 ; col < columns ; col++ ) 278 | if ( STAR == mask_matrix(row, col) ) { 279 | col_mask[col] = true; 280 | covercount++; 281 | } 282 | 283 | if ( covercount >= matrix.minsize() ) 284 | { 285 | return 0; 286 | } 287 | 288 | return 3; 289 | } 290 | 291 | int step3() { 292 | /* 293 | Main Zero Search 294 | 295 | 1. Find an uncovered Z in the distance matrix and prime it. If no such zero exists, go to Step 5 296 | 2. If No Z* exists in the row of the Z', go to Step 4. 297 | 3. If a Z* exists, cover this row and uncover the column of the Z*. Return to Step 3.1 to find a new Z 298 | */ 299 | if ( find_uncovered_in_matrix(0, saverow, savecol) ) { 300 | mask_matrix(saverow,savecol) = PRIME; // prime it. 301 | } else { 302 | return 5; 303 | } 304 | 305 | for ( size_t ncol = 0 ; ncol < matrix.columns() ; ncol++ ) { 306 | if ( mask_matrix(saverow,ncol) == STAR ) { 307 | row_mask[saverow] = true; //cover this row and 308 | col_mask[ncol] = false; // uncover the column containing the starred zero 309 | return 3; // repeat 310 | } 311 | } 312 | 313 | return 4; // no starred zero in the row containing this primed zero 314 | } 315 | 316 | int step4() { 317 | const size_t rows = matrix.rows(), 318 | columns = matrix.columns(); 319 | 320 | // seq contains pairs of row/column values where we have found 321 | // either a star or a prime that is part of the ``alternating sequence``. 322 | std::list > seq; 323 | // use saverow, savecol from step 3. 324 | std::pair z0(saverow, savecol); 325 | seq.insert(seq.end(), z0); 326 | 327 | // We have to find these two pairs: 328 | std::pair z1(-1, -1); 329 | std::pair z2n(-1, -1); 330 | 331 | size_t row, col = savecol; 332 | /* 333 | Increment Set of Starred Zeros 334 | 335 | 1. Construct the ``alternating sequence'' of primed and starred zeros: 336 | 337 | Z0 : Unpaired Z' from Step 4.2 338 | Z1 : The Z* in the column of Z0 339 | Z[2N] : The Z' in the row of Z[2N-1], if such a zero exists 340 | Z[2N+1] : The Z* in the column of Z[2N] 341 | 342 | The sequence eventually terminates with an unpaired Z' = Z[2N] for some N. 343 | */ 344 | bool madepair; 345 | do { 346 | madepair = false; 347 | for ( row = 0 ; row < rows ; row++ ) { 348 | if ( mask_matrix(row,col) == STAR ) { 349 | z1.first = row; 350 | z1.second = col; 351 | if ( pair_in_list(z1, seq) ) { 352 | continue; 353 | } 354 | 355 | madepair = true; 356 | seq.insert(seq.end(), z1); 357 | break; 358 | } 359 | } 360 | 361 | if ( !madepair ) 362 | break; 363 | 364 | madepair = false; 365 | 366 | for ( col = 0 ; col < columns ; col++ ) { 367 | if ( mask_matrix(row, col) == PRIME ) { 368 | z2n.first = row; 369 | z2n.second = col; 370 | if ( pair_in_list(z2n, seq) ) { 371 | continue; 372 | } 373 | madepair = true; 374 | seq.insert(seq.end(), z2n); 375 | break; 376 | } 377 | } 378 | } while ( madepair ); 379 | 380 | for ( std::list >::iterator i = seq.begin() ; 381 | i != seq.end() ; 382 | i++ ) { 383 | // 2. Unstar each starred zero of the sequence. 384 | if ( mask_matrix(i->first,i->second) == STAR ) 385 | mask_matrix(i->first,i->second) = NORMAL; 386 | 387 | // 3. Star each primed zero of the sequence, 388 | // thus increasing the number of starred zeros by one. 389 | if ( mask_matrix(i->first,i->second) == PRIME ) 390 | mask_matrix(i->first,i->second) = STAR; 391 | } 392 | 393 | // 4. Erase all primes, uncover all columns and rows, 394 | for ( size_t row = 0 ; row < mask_matrix.rows() ; row++ ) { 395 | for ( size_t col = 0 ; col < mask_matrix.columns() ; col++ ) { 396 | if ( mask_matrix(row,col) == PRIME ) { 397 | mask_matrix(row,col) = NORMAL; 398 | } 399 | } 400 | } 401 | 402 | for ( size_t i = 0 ; i < rows ; i++ ) { 403 | row_mask[i] = false; 404 | } 405 | 406 | for ( size_t i = 0 ; i < columns ; i++ ) { 407 | col_mask[i] = false; 408 | } 409 | 410 | // and return to Step 2. 411 | return 2; 412 | } 413 | 414 | int step5() { 415 | const size_t rows = matrix.rows(), 416 | columns = matrix.columns(); 417 | /* 418 | New Zero Manufactures 419 | 420 | 1. Let h be the smallest uncovered entry in the (modified) distance matrix. 421 | 2. Add h to all covered rows. 422 | 3. Subtract h from all uncovered columns 423 | 4. Return to Step 3, without altering stars, primes, or covers. 424 | */ 425 | double h = 100000;//xyzoylz std::numeric_limits::max(); 426 | for ( size_t row = 0 ; row < rows ; row++ ) { 427 | if ( !row_mask[row] ) { 428 | for ( size_t col = 0 ; col < columns ; col++ ) { 429 | if ( !col_mask[col] ) { 430 | if ( h > matrix(row, col) && matrix(row, col) != 0 ) { 431 | h = matrix(row, col); 432 | } 433 | } 434 | } 435 | } 436 | } 437 | 438 | for ( size_t row = 0 ; row < rows ; row++ ) { 439 | if ( row_mask[row] ) { 440 | for ( size_t col = 0 ; col < columns ; col++ ) { 441 | matrix(row, col) += h; 442 | } 443 | } 444 | } 445 | 446 | for ( size_t col = 0 ; col < columns ; col++ ) { 447 | if ( !col_mask[col] ) { 448 | for ( size_t row = 0 ; row < rows ; row++ ) { 449 | matrix(row, col) -= h; 450 | } 451 | } 452 | } 453 | 454 | return 3; 455 | } 456 | 457 | Matrix mask_matrix; 458 | Matrix matrix; 459 | std::vector row_mask; 460 | std::vector col_mask; 461 | //bool *row_mask; 462 | //bool *col_mask; 463 | size_t saverow = 0, savecol = 0; 464 | }; 465 | 466 | 467 | #endif /* !defined(_MUNKRES_H_) */ 468 | -------------------------------------------------------------------------------- /src/thirdPart/src/adapter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Miroslav Krajicek 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #include "adapter.h" 20 | -------------------------------------------------------------------------------- /src/thirdPart/src/boostmatrixadapter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Miroslav Krajicek 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #include "boostmatrixadapter.h" 20 | 21 | //template class BoostMatrixAdapter; 22 | //template class BoostMatrixAdapter; 23 | //template class BoostMatrixAdapter; 24 | -------------------------------------------------------------------------------- /src/thirdPart/src/hungarianoper.cpp: -------------------------------------------------------------------------------- 1 | #include "hungarianoper.h" 2 | 3 | Eigen::Matrix HungarianOper::Solve(const DYNAMICM &cost_matrix) 4 | { 5 | int rows = cost_matrix.rows(); 6 | int cols = cost_matrix.cols(); 7 | Matrix matrix(rows, cols); 8 | for (int row = 0; row < rows; row++) { 9 | for (int col = 0; col < cols; col++) { 10 | matrix(row, col) = cost_matrix(row, col); 11 | } 12 | } 13 | //Munkres get matrix; 14 | Munkres m; 15 | m.solve(matrix); 16 | 17 | // 18 | std::vector> pairs; 19 | for (int row = 0; row < rows; row++) { 20 | for (int col = 0; col < cols; col++) { 21 | int tmp = (int)matrix(row, col); 22 | if (tmp == 0) pairs.push_back(std::make_pair(row, col)); 23 | } 24 | } 25 | // 26 | int count = pairs.size(); 27 | Eigen::Matrix re(count, 2); 28 | for (int i = 0; i < count; i++) { 29 | re(i, 0) = pairs[i].first; 30 | re(i, 1) = pairs[i].second; 31 | } 32 | return re; 33 | }//end Solve; 34 | -------------------------------------------------------------------------------- /src/thirdPart/src/munkres.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 John Weaver 3 | * Copyright (c) 2015 Miroslav Krajicek 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "munkres.h" 21 | 22 | template class Munkres; 23 | template class Munkres; 24 | template class Munkres; 25 | 26 | -------------------------------------------------------------------------------- /tensorflow_cc/.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Build folders 35 | example/build 36 | tensorflow_cc/build 37 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/BAZEL_VERSION: -------------------------------------------------------------------------------- 1 | 0.21.0 2 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/archlinux-shared: -------------------------------------------------------------------------------- 1 | FROM archlinux/base 2 | 3 | # copy the contents of this repository to the container 4 | COPY . tensorflow_cc 5 | # alternatively, clone the repository 6 | # RUN git clone https://github.com/FloopCZ/tensorflow_cc.git 7 | 8 | # build and install 9 | RUN ./tensorflow_cc/Dockerfiles/install-archlinux.sh --shared 10 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/archlinux-shared-cuda: -------------------------------------------------------------------------------- 1 | FROM archlinux/base 2 | 3 | # copy the contents of this repository to the container 4 | COPY . tensorflow_cc 5 | # alternatively, clone the repository 6 | # RUN git clone https://github.com/FloopCZ/tensorflow_cc.git 7 | 8 | # build and install 9 | RUN ./tensorflow_cc/Dockerfiles/install-archlinux.sh --cuda --shared 10 | 11 | ENV NVIDIA_VISIBLE_DEVICES all 12 | ENV NVIDIA_DRIVER_CAPABILITIES compute,utility 13 | ENV NVIDIA_REQUIRE_CUDA "cuda>=9.2" 14 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/archlinux-static: -------------------------------------------------------------------------------- 1 | FROM archlinux/base 2 | 3 | # copy the contents of this repository to the container 4 | COPY . tensorflow_cc 5 | # alternatively, clone the repository 6 | # RUN git clone https://github.com/FloopCZ/tensorflow_cc.git 7 | 8 | # build and install 9 | RUN ./tensorflow_cc/Dockerfiles/install-archlinux.sh 10 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/install-archlinux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # parse command line arguments 5 | 6 | shared=false 7 | cuda=false 8 | 9 | for key in "$@"; do 10 | case $key in 11 | --shared) 12 | shared=true 13 | ;; 14 | --cuda) 15 | cuda=true 16 | ;; 17 | esac 18 | done 19 | 20 | # install requirements 21 | pacman -Syu --noconfirm --needed \ 22 | base-devel \ 23 | cmake \ 24 | git \ 25 | unzip \ 26 | mlocate \ 27 | python \ 28 | python-numpy \ 29 | wget 30 | 31 | if $shared; then 32 | pacman -S --noconfirm --needed \ 33 | gcc \ 34 | java-environment=8 \ 35 | libarchive \ 36 | protobuf \ 37 | unzip \ 38 | zip 39 | export BAZEL_VERSION=${BAZEL_VERSION:-`cat ./tensorflow_cc/Dockerfiles/BAZEL_VERSION`} 40 | bazel_installer=bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh 41 | wget -P /tmp https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/${bazel_installer} 42 | chmod +x /tmp/${bazel_installer} 43 | /tmp/${bazel_installer} 44 | rm /tmp/${bazel_installer} 45 | fi 46 | if $cuda; then 47 | pacman -S --noconfirm --needed \ 48 | cuda \ 49 | cudnn \ 50 | nccl 51 | fi 52 | 53 | # when building TF with Intel MKL support, `locate` database needs to exist 54 | updatedb 55 | 56 | # build and install tensorflow_cc 57 | ./tensorflow_cc/Dockerfiles/install-common.sh "$@" 58 | 59 | # cleanup installed cuda libraries (will be provided by nvidia-docker) 60 | if $cuda; then 61 | rm -vf /usr/bin/nvidia* 62 | rm -vf /usr/lib/libnvidia* 63 | rm -vf /usr/lib/libcuda* 64 | fi 65 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/install-common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | cwd="`pwd`" 4 | 5 | ### parse command line arguments ### 6 | 7 | shared=false 8 | 9 | for key in "$@"; do 10 | case $key in 11 | --shared) 12 | shared=true 13 | ;; 14 | esac 15 | done 16 | 17 | ### prepare an unprivileged user 18 | 19 | groupadd -r tensorflow_cc 20 | useradd --no-log-init -r -m -g tensorflow_cc tensorflow_cc 21 | chmod -R go+rX /tensorflow_cc 22 | function unpriv-run() { 23 | sudo --preserve-env=LD_LIBRARY_PATH -H -u tensorflow_cc "$@" 24 | } 25 | 26 | ### build and install tensorflow_cc ### 27 | 28 | mkdir tensorflow_cc/tensorflow_cc/build 29 | chown -R tensorflow_cc:tensorflow_cc tensorflow_cc/tensorflow_cc/build 30 | chmod go+rX tensorflow_cc/tensorflow_cc/build 31 | cd tensorflow_cc/tensorflow_cc/build 32 | 33 | # configure only shared or only static library 34 | if $shared; then 35 | cmake -DTENSORFLOW_STATIC=OFF -DTENSORFLOW_SHARED=ON ..; 36 | else 37 | cmake ..; 38 | fi 39 | 40 | # build and install 41 | make 42 | rm -rf /home/tensorflow_cc/.cache 43 | make install 44 | cd "$cwd" 45 | rm -rf tensorflow_cc/tensorflow_cc/build 46 | 47 | ### build and run example ### 48 | 49 | mkdir tensorflow_cc/example/build 50 | chown -R tensorflow_cc:tensorflow_cc tensorflow_cc/example/build 51 | chmod go+rX tensorflow_cc/example/build 52 | cd tensorflow_cc/example/build 53 | cmake .. 54 | make 55 | ./example 56 | 57 | ### delete the unprivileged user 58 | chown -R root:root /tensorflow_cc 59 | userdel -r tensorflow_cc 60 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/install-ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # parse command line arguments 5 | 6 | shared=false 7 | cuda=false 8 | 9 | for key in "$@"; do 10 | case $key in 11 | --shared) 12 | shared=true 13 | ;; 14 | --cuda) 15 | cuda=true 16 | ;; 17 | esac 18 | done 19 | 20 | # install requirements 21 | apt-get -y update 22 | apt-get -y install \ 23 | build-essential \ 24 | curl \ 25 | git \ 26 | cmake \ 27 | unzip \ 28 | autoconf \ 29 | autogen \ 30 | libtool \ 31 | mlocate \ 32 | zlib1g-dev \ 33 | g++-7 \ 34 | python \ 35 | python3-numpy \ 36 | python3-dev \ 37 | python3-pip \ 38 | python3-wheel \ 39 | sudo \ 40 | wget 41 | 42 | if $shared; then 43 | # install bazel for the shared library version 44 | export BAZEL_VERSION=${BAZEL_VERSION:-`cat ./tensorflow_cc/Dockerfiles/BAZEL_VERSION`} 45 | apt-get -y install pkg-config zip g++ zlib1g-dev unzip python 46 | bazel_installer=bazel-${BAZEL_VERSION}-installer-linux-x86_64.sh 47 | wget -P /tmp https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/${bazel_installer} 48 | chmod +x /tmp/${bazel_installer} 49 | /tmp/${bazel_installer} 50 | rm /tmp/${bazel_installer} 51 | fi 52 | if $cuda; then 53 | # install libcupti 54 | apt-get -y install cuda-command-line-tools-10-0 55 | fi 56 | 57 | apt-get -y clean 58 | 59 | # when building TF with Intel MKL support, `locate` database needs to exist 60 | updatedb 61 | 62 | # build and install tensorflow_cc 63 | ./tensorflow_cc/Dockerfiles/install-common.sh "$@" 64 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/ubuntu-shared: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | # copy the contents of this repository to the container 4 | COPY . tensorflow_cc 5 | # alternatively, clone the repository 6 | # RUN git clone https://github.com/FloopCZ/tensorflow_cc.git 7 | 8 | # build and install 9 | RUN ./tensorflow_cc/Dockerfiles/install-ubuntu.sh --shared 10 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/ubuntu-shared-cuda: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:10.0-cudnn7-devel-ubuntu18.04 2 | 3 | # copy the contents of this repository to the container 4 | COPY . tensorflow_cc 5 | # alternatively, clone the repository 6 | # RUN git clone https://github.com/FloopCZ/tensorflow_cc.git 7 | 8 | # build and install 9 | # temporarily use the CUDA stubs, the real libraries will be provided by nvidia-docker 10 | RUN ln -s /usr/local/cuda/lib64/stubs/libcuda.so /usr/local/cuda/lib64/stubs/libcuda.so.1 \ 11 | && LD_LIBRARY_PATH=/usr/local/cuda/lib64/stubs/:$LD_LIBRARY_PATH \ 12 | ./tensorflow_cc/Dockerfiles/install-ubuntu.sh --shared --cuda \ 13 | && rm /usr/local/cuda/lib64/stubs/libcuda.so.1 14 | -------------------------------------------------------------------------------- /tensorflow_cc/Dockerfiles/ubuntu-static: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | # copy the contents of this repository to the container 4 | COPY . tensorflow_cc 5 | # alternatively, clone the repository 6 | # RUN git clone https://github.com/FloopCZ/tensorflow_cc.git 7 | 8 | # build and install 9 | RUN ./tensorflow_cc/Dockerfiles/install-ubuntu.sh 10 | -------------------------------------------------------------------------------- /tensorflow_cc/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Filip Matzner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tensorflow_cc/README.md: -------------------------------------------------------------------------------- 1 | # tensorflow_cc 2 | [![Build Status](http://ash.floop.cz:8080/buildStatus/icon?job=tensorflow_cc)](http://ash.floop.cz:8080/job/tensorflow_cc/) 3 | [![TF version](https://img.shields.io/badge/TF%20version-1.13.1-brightgreen.svg)]() 4 | 5 | This repository makes possible the usage of the [TensorFlow C++](https://www.tensorflow.org/api_docs/cc/) API from the outside of the TensorFlow source code folders and without the use of the [Bazel](https://bazel.build/) build system. 6 | 7 | This repository contains two CMake projects. The [tensorflow_cc](tensorflow_cc) project downloads, builds and installs the TensorFlow C++ API into the operating system and the [example](example) project demonstrates its simple usage. 8 | 9 | ## Docker 10 | 11 | If you wish to start using this project right away, fetch a prebuilt image on [Docker Hub](https://hub.docker.com/r/floopcz/tensorflow_cc/)! 12 | 13 | Running the image on CPU: 14 | ```bash 15 | docker run -it floopcz/tensorflow_cc:ubuntu-shared /bin/bash 16 | ``` 17 | 18 | If you also want to utilize your NVIDIA GPU, install [NVIDIA Docker](https://github.com/NVIDIA/nvidia-docker) and run: 19 | ```bash 20 | docker run --runtime=nvidia -it floopcz/tensorflow_cc:ubuntu-shared-cuda /bin/bash 21 | ``` 22 | 23 | The list of available images: 24 | 25 | | Image name | Description | 26 | | --- | --- | 27 | | `floopcz/tensorflow_cc:ubuntu-static` | Ubuntu + static build of `tensorflow_cc` | 28 | | `floopcz/tensorflow_cc:ubuntu-shared` | Ubuntu + shared build of `tensorflow_cc` | 29 | | `floopcz/tensorflow_cc:ubuntu-shared-cuda` | Ubuntu + shared build of `tensorflow_cc` + NVIDIA CUDA | 30 | | `floopcz/tensorflow_cc:archlinux-shared` | Arch Linux + shared build of `tensorflow_cc` | 31 | 32 | To build one of the images yourself, e.g. `ubuntu-shared`, run: 33 | ```bash 34 | docker build -t floopcz/tensorflow_cc:ubuntu-shared -f Dockerfiles/ubuntu-shared . 35 | ``` 36 | 37 | ## Installation 38 | 39 | #### 1) Install requirements 40 | 41 | ##### Ubuntu 18.04: 42 | ``` 43 | sudo apt-get install build-essential curl git cmake unzip autoconf autogen automake libtool mlocate \ 44 | zlib1g-dev g++-7 python python3-numpy python3-dev python3-pip python3-wheel wget 45 | sudo updatedb 46 | ``` 47 | 48 | If you require GPU support on Ubuntu, please also install [Bazel](https://bazel.build/), NVIDIA CUDA Toolkit (>=9.2), NVIDIA drivers, cuDNN, and `cuda-command-line-tools` package. The tensorflow build script will automatically detect CUDA if it is installed in `/opt/cuda` or `/usr/local/cuda` directories. 49 | 50 | ##### Arch Linux: 51 | ``` 52 | sudo pacman -S base-devel cmake git unzip mlocate python python-numpy wget 53 | sudo updatedb 54 | ``` 55 | 56 | For GPU support on Arch, also install the following: 57 | 58 | ``` 59 | sudo pacman -S gcc7 bazel cuda cudnn nvidia 60 | ``` 61 | 62 | **Warning:** Newer versions of TensorFlow sometimes fail to build with the latest version of Bazel. You may wish 63 | to install an older version of Bazel (e.g., 0.16.1). 64 | 65 | #### 2) Clone this repository 66 | ``` 67 | git clone https://github.com/FloopCZ/tensorflow_cc.git 68 | cd tensorflow_cc 69 | ``` 70 | 71 | #### 3) Build and install the library 72 | 73 | There are two possible ways to build the TensorFlow C++ library: 74 | 1. As a __static library__ (default): 75 | - Faster to build. 76 | - Provides only basic functionality, just enough for inferring using an existing network 77 | (see [contrib/makefile](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/makefile)). 78 | - No GPU support. 79 | 2. As a __shared library__: 80 | - Requires [Bazel](https://bazel.build/). 81 | - Slower to build. 82 | - Provides the full TensorFlow C++ API. 83 | - GPU support. 84 | 85 | ``` 86 | cd tensorflow_cc 87 | mkdir build && cd build 88 | # for static library only: 89 | cmake .. 90 | # for shared library only (requires Bazel): 91 | # cmake -DTENSORFLOW_STATIC=OFF -DTENSORFLOW_SHARED=ON .. 92 | make && sudo make install 93 | ``` 94 | 95 | **Warning:** Optimizations for Intel CPU generation `>=ivybridge` are enabled by default. If you have a 96 | processor that is older than `ivybridge` generation, you may wish to run `export CC_OPT_FLAGS="-march=native"` 97 | before the build. This command provides the best possible optimizations for your current CPU generation, but 98 | it may cause the built library to be incompatible with older generations. 99 | 100 | #### 4) (Optional) Free disk space 101 | 102 | ``` 103 | # cleanup bazel build directory 104 | rm -rf ~/.cache 105 | # remove the build folder 106 | cd .. && rm -rf build 107 | ``` 108 | 109 | ## Usage 110 | 111 | #### 1) Write your C++ code: 112 | ```C++ 113 | // example.cpp 114 | 115 | #include 116 | #include 117 | #include 118 | using namespace std; 119 | using namespace tensorflow; 120 | 121 | int main() 122 | { 123 | Session* session; 124 | Status status = NewSession(SessionOptions(), &session); 125 | if (!status.ok()) { 126 | cout << status.ToString() << "\n"; 127 | return 1; 128 | } 129 | cout << "Session successfully created.\n"; 130 | } 131 | ``` 132 | 133 | #### 2) Link TensorflowCC to your program using CMake 134 | ```CMake 135 | # CMakeLists.txt 136 | 137 | find_package(TensorflowCC REQUIRED) 138 | add_executable(example example.cpp) 139 | 140 | # Link the static Tensorflow library. 141 | target_link_libraries(example TensorflowCC::Static) 142 | 143 | # Altenatively, link the shared Tensorflow library. 144 | # target_link_libraries(example TensorflowCC::Shared) 145 | 146 | # For shared library setting, you may also link cuda if it is available. 147 | # find_package(CUDA) 148 | # if(CUDA_FOUND) 149 | # target_link_libraries(example ${CUDA_LIBRARIES}) 150 | # endif() 151 | ``` 152 | 153 | #### 3) Build and run your program 154 | ``` 155 | mkdir build && cd build 156 | cmake .. && make 157 | ./example 158 | ``` 159 | 160 | If you are still unsure, consult the Dockerfiles for 161 | [Ubuntu](Dockerfiles/ubuntu-shared) and [Arch Linux](Dockerfiles/archlinux-shared). 162 | -------------------------------------------------------------------------------- /tensorflow_cc/example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3 FATAL_ERROR) 2 | add_executable(example example.cpp) 3 | 4 | # try the shared tensorflow library first 5 | find_package(TensorflowCC COMPONENTS Shared) 6 | if(TensorflowCC_Shared_FOUND) 7 | message("here") 8 | target_link_libraries(example TensorflowCC::Shared tensorflow_framework) 9 | # fallback to the static library 10 | else() 11 | find_package(TensorflowCC REQUIRED COMPONENTS Static) 12 | target_link_libraries(example TensorflowCC::Static) 13 | endif() 14 | 15 | # link cuda if it is available 16 | find_package(CUDA) 17 | if(CUDA_FOUND) 18 | target_link_libraries(example ${CUDA_LIBRARIES}) 19 | endif() 20 | -------------------------------------------------------------------------------- /tensorflow_cc/example/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace std; 7 | using namespace tensorflow; 8 | 9 | int main() 10 | { 11 | Session* session; 12 | Status status = NewSession(SessionOptions(), &session); 13 | if (!status.ok()) { 14 | cout << status.ToString() << "\n"; 15 | return 1; 16 | } 17 | cout << "Session successfully created.\n"; 18 | } 19 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3 FATAL_ERROR) 2 | project( 3 | "tensorflow_cc" 4 | VERSION 1.14.0 5 | ) 6 | 7 | # Static library with no GPU support is built by default. 8 | # Use the following option to build a shared library with GPU support. 9 | # If enabled, bazel has to be installed. 10 | option(TENSORFLOW_SHARED "Build shared library (required for GPU support)." OFF) 11 | option(ALLOW_CUDA "When building the shared library, try to find and use CUDA." ON) 12 | option(TENSORFLOW_STATIC "Build static library." ON) 13 | set(TENSORFLOW_TAG "v1.14.0" CACHE STRING "The tensorflow release tag to be checked out (default v1.14.0).") 14 | option(SYSTEM_PROTOBUF "Use system protobuf instead of static protobuf from contrib/makefile." OFF) 15 | 16 | # ------------- 17 | # CMake Options 18 | # ------------- 19 | 20 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 21 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") 22 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") 23 | include(CMakePackageConfigHelpers) 24 | set(CMAKECFG_INSTALL_DIR lib/cmake/TensorflowCC) 25 | 26 | # Configure the build_tensorflow script. 27 | configure_file("cmake/build_tensorflow.sh.in" "build_tensorflow.sh" @ONLY) 28 | 29 | # -------------------------------------------------------- 30 | # Include External Projects for Shared / Static Tensorflow 31 | # -------------------------------------------------------- 32 | 33 | include(TensorflowBase) 34 | if(TENSORFLOW_SHARED) 35 | include(TensorflowShared) 36 | endif() 37 | if(TENSORFLOW_STATIC) 38 | include(TensorflowStatic) 39 | # Add shared lib as dependency to avoid race 40 | if(TENSORFLOW_SHARED) 41 | add_dependencies( 42 | tensorflow_static 43 | tensorflow_shared 44 | ) 45 | endif() 46 | endif() 47 | 48 | # ---------------------------------- 49 | # Define Shared Tensorflow Interface 50 | # ---------------------------------- 51 | if(SYSTEM_PROTOBUF) 52 | find_package(Protobuf REQUIRED) 53 | endif() 54 | 55 | # ---------------------------------- 56 | # Define Shared Tensorflow Interface 57 | # ---------------------------------- 58 | 59 | if(TENSORFLOW_SHARED) 60 | add_library(tensorflow_cc_shared INTERFACE) 61 | target_compile_options( 62 | tensorflow_cc_shared INTERFACE 63 | "$<$:-std=c++11>" 64 | ) 65 | add_dependencies( 66 | tensorflow_cc_shared 67 | tensorflow_shared 68 | ) 69 | target_include_directories( 70 | tensorflow_cc_shared INTERFACE 71 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow" 72 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/bazel-genfiles" 73 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/bazel-genfiles/genfiles" 74 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads" 75 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads/absl" 76 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads/eigen" 77 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads/gemmlowp" 78 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads/nsync/public" 79 | ) 80 | target_link_libraries( 81 | tensorflow_cc_shared INTERFACE 82 | "${CMAKE_INSTALL_PREFIX}/lib/libtensorflow_cc.so.${PROJECT_VERSION_MAJOR}" 83 | dl pthread 84 | ) 85 | if(SYSTEM_PROTOBUF) 86 | target_include_directories( 87 | tensorflow_cc_shared INTERFACE 88 | "${Protobuf_INCLUDE_DIRS}" 89 | ) 90 | target_link_libraries( 91 | tensorflow_cc_shared INTERFACE 92 | "${Protobuf_LIBRARIES}" 93 | ) 94 | else() 95 | target_include_directories( 96 | tensorflow_cc_shared INTERFACE 97 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/gen/protobuf-host/include" 98 | ) 99 | target_link_libraries( 100 | tensorflow_cc_shared INTERFACE 101 | "${CMAKE_INSTALL_PREFIX}/lib/tensorflow_cc/libprotobuf.a" 102 | ) 103 | endif() 104 | endif() 105 | 106 | # ---------------------------------- 107 | # Define Static Tensorflow Interface 108 | # ---------------------------------- 109 | 110 | if(TENSORFLOW_STATIC) 111 | add_library(tensorflow_cc_static INTERFACE) 112 | target_compile_options( 113 | tensorflow_cc_static INTERFACE 114 | "$<$:-std=c++11>" 115 | ) 116 | add_dependencies( 117 | tensorflow_cc_static 118 | tensorflow_static 119 | ) 120 | target_include_directories( 121 | tensorflow_cc_static INTERFACE 122 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow" 123 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/gen/host_obj" 124 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads" 125 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads/absl" 126 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads/eigen" 127 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads/gemmlowp" 128 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/downloads/nsync/public" 129 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/gen/proto" 130 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/gen/proto_text" 131 | ) 132 | target_link_libraries( 133 | tensorflow_cc_static INTERFACE 134 | "-Wl,--allow-multiple-definition" 135 | "-Wl,--whole-archive ${CMAKE_INSTALL_PREFIX}/lib/tensorflow_cc/libtensorflow-core.a" 136 | "-Wl,--no-whole-archive" 137 | "${CMAKE_INSTALL_PREFIX}/lib/tensorflow_cc/nsync.a" 138 | dl pthread 139 | ) 140 | if(SYSTEM_PROTOBUF) 141 | target_include_directories( 142 | tensorflow_cc_static INTERFACE 143 | "${Protobuf_INCLUDE_DIRS}" 144 | ) 145 | target_link_libraries( 146 | tensorflow_cc_static INTERFACE 147 | "${Protobuf_LIBRARIES}" 148 | ) 149 | else() 150 | target_include_directories( 151 | tensorflow_cc_static INTERFACE 152 | "${CMAKE_INSTALL_PREFIX}/include/tensorflow/tensorflow/contrib/makefile/gen/protobuf-host/include" 153 | ) 154 | target_link_libraries( 155 | tensorflow_cc_static INTERFACE 156 | "${CMAKE_INSTALL_PREFIX}/lib/tensorflow_cc/libprotobuf.a" 157 | ) 158 | endif() 159 | endif() 160 | 161 | # ---------------------------------------- 162 | # Configure CMake Config and Version Files 163 | # ---------------------------------------- 164 | 165 | write_basic_package_version_file( 166 | "${CMAKE_CURRENT_BINARY_DIR}/TensorflowCCConfigVersion.cmake" 167 | VERSION ${PROJECT_VERSION} 168 | COMPATIBILITY SameMajorVersion 169 | ) 170 | configure_package_config_file( 171 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TensorflowCCConfig.cmake.in" 172 | "${CMAKE_CURRENT_BINARY_DIR}/TensorflowCCConfig.cmake" 173 | INSTALL_DESTINATION "${CMAKECFG_INSTALL_DIR}" 174 | NO_SET_AND_CHECK_MACRO # TensorflowCC only uses interface libraries 175 | NO_CHECK_REQUIRED_COMPONENTS_MACRO # TensorflowCC does not have components 176 | ) 177 | 178 | # ------- 179 | # Install 180 | # ------- 181 | 182 | # install all header files 183 | install( 184 | DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/" 185 | DESTINATION include/tensorflow 186 | FILES_MATCHING PATTERN "*.h" 187 | ) 188 | # install all header files downloaded by contrib/makefile 189 | # (Note that we cannot simply include all *.h or *.hpp files, since e.g., eigen 190 | # does not use file extensions for header files.) 191 | install( 192 | DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/tensorflow/contrib/makefile/downloads/" 193 | DESTINATION include/tensorflow/tensorflow/contrib/makefile/downloads 194 | FILES_MATCHING PATTERN "*" 195 | PATTERN "Makefile*" EXCLUDE 196 | PATTERN "*unittest*" EXCLUDE 197 | PATTERN "*.o" EXCLUDE 198 | PATTERN "*.so" EXCLUDE 199 | PATTERN "*.so.*" EXCLUDE 200 | PATTERN "*.a" EXCLUDE 201 | PATTERN "*.tbz" EXCLUDE 202 | PATTERN "*.tgz" EXCLUDE 203 | PATTERN "*.tar" EXCLUDE 204 | PATTERN "*.tar.*" EXCLUDE 205 | PATTERN "*.zip" EXCLUDE 206 | ) 207 | # install all the *.inc files 208 | install( 209 | DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/tensorflow/contrib/makefile/gen/" 210 | DESTINATION include/tensorflow/tensorflow/contrib/makefile/gen 211 | FILES_MATCHING PATTERN "*.inc" 212 | ) 213 | # install all files from third_party folder (e.g., Eigen/Tensor) 214 | install( 215 | DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/third_party/" 216 | DESTINATION include/tensorflow/third_party 217 | ) 218 | # install static libprotobuf from contrib/makefile 219 | if (NOT SYSTEM_PROTOBUF) 220 | install( 221 | FILES "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/tensorflow/contrib/makefile/gen/protobuf-host/lib/libprotobuf.a" 222 | DESTINATION lib/tensorflow_cc 223 | ) 224 | endif() 225 | # shared library specific 226 | if(TENSORFLOW_SHARED) 227 | install( 228 | FILES "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so" 229 | DESTINATION lib 230 | RENAME libtensorflow_cc.so.${PROJECT_VERSION_MAJOR} 231 | OPTIONAL 232 | ) 233 | install( 234 | FILES "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/bazel-bin/bin/tensorflow/libtensorflow_cc.so" 235 | DESTINATION lib 236 | RENAME libtensorflow_cc.so.${PROJECT_VERSION_MAJOR} 237 | OPTIONAL 238 | ) 239 | # Make versioned symlinks to the library 240 | install(CODE "execute_process( \ 241 | COMMAND ${CMAKE_COMMAND} -E create_symlink \ 242 | libtensorflow_cc.so.${PROJECT_VERSION_MAJOR} \ 243 | ${CMAKE_INSTALL_PREFIX}/lib/libtensorflow_cc.so \ 244 | )" 245 | ) 246 | endif() 247 | # static library specific 248 | if(TENSORFLOW_STATIC) 249 | install( 250 | FILES "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/tensorflow/contrib/makefile/gen/lib/libtensorflow-core.a" 251 | "${CMAKE_CURRENT_BINARY_DIR}/tensorflow/tensorflow/contrib/makefile/downloads/nsync/builds/default.linux.c++11/nsync.a" 252 | DESTINATION lib/tensorflow_cc 253 | ) 254 | endif() 255 | 256 | # -------------------------- 257 | # Install CMake targets file 258 | # -------------------------- 259 | 260 | if(TENSORFLOW_SHARED) 261 | set_target_properties( 262 | tensorflow_cc_shared PROPERTIES EXPORT_NAME Shared 263 | ) 264 | install( 265 | TARGETS tensorflow_cc_shared 266 | EXPORT TensorflowCCSharedTargets 267 | ) 268 | install( 269 | EXPORT TensorflowCCSharedTargets 270 | FILE TensorflowCCSharedTargets.cmake 271 | NAMESPACE TensorflowCC:: 272 | DESTINATION "${CMAKECFG_INSTALL_DIR}" 273 | ) 274 | endif() 275 | if(TENSORFLOW_STATIC) 276 | set_target_properties( 277 | tensorflow_cc_static PROPERTIES EXPORT_NAME Static 278 | ) 279 | install( 280 | TARGETS tensorflow_cc_static 281 | EXPORT TensorflowCCStaticTargets 282 | ) 283 | install( 284 | EXPORT TensorflowCCStaticTargets 285 | FILE TensorflowCCStaticTargets.cmake 286 | NAMESPACE TensorflowCC:: 287 | DESTINATION "${CMAKECFG_INSTALL_DIR}" 288 | ) 289 | endif() 290 | 291 | # install config and version files 292 | install( 293 | FILES 294 | "${CMAKE_CURRENT_BINARY_DIR}/TensorflowCCConfig.cmake" 295 | "${CMAKE_CURRENT_BINARY_DIR}/TensorflowCCConfigVersion.cmake" 296 | DESTINATION "${CMAKECFG_INSTALL_DIR}" 297 | ) 298 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/cmake/TensorflowBase.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3 FATAL_ERROR) 2 | include(ExternalProject) 3 | 4 | # TODO This is a patch for 1.12.0. 5 | set(OLD_PROTOBUF "https://mirror.bazel.build/github.com/google/protobuf/archive/396336eb961b75f03b25824fe86cf6490fb75e3a.tar.gz") 6 | set(FIXED_PROTOBUF "https://github.com/protocolbuffers/protobuf/releases/download/v3.6.0/protobuf-all-3.6.0.tar.gz") 7 | 8 | ExternalProject_Add( 9 | tensorflow_base 10 | GIT_REPOSITORY https://github.com/tensorflow/tensorflow.git 11 | GIT_TAG "${TENSORFLOW_TAG}" 12 | TMP_DIR "/tmp" 13 | STAMP_DIR "tensorflow-stamp" 14 | DOWNLOAD_DIR "tensorflow" 15 | SOURCE_DIR "tensorflow" 16 | BUILD_IN_SOURCE 1 17 | UPDATE_COMMAND "" 18 | CONFIGURE_COMMAND make -f tensorflow/contrib/makefile/Makefile clean 19 | 20 | # TODO This is a patch for 1.12.0. 21 | COMMAND git checkout master -- tensorflow/tf_version_script.lds 22 | COMMAND sed -i "s#${OLD_PROTOBUF}#${FIXED_PROTOBUF}#g" tensorflow/contrib/makefile/download_dependencies.sh 23 | 24 | COMMAND tensorflow/contrib/makefile/download_dependencies.sh 25 | BUILD_COMMAND "" 26 | INSTALL_COMMAND "" 27 | ) 28 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/cmake/TensorflowCCConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/TensorflowCCSharedTargets.cmake") 4 | include("${CMAKE_CURRENT_LIST_DIR}/TensorflowCCSharedTargets.cmake") 5 | set(TensorflowCC_Shared_FOUND ON) 6 | endif() 7 | 8 | if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/TensorflowCCStaticTargets.cmake") 9 | include("${CMAKE_CURRENT_LIST_DIR}/TensorflowCCStaticTargets.cmake") 10 | set(TensorflowCC_Static_FOUND ON) 11 | endif() 12 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/cmake/TensorflowShared.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3 FATAL_ERROR) 2 | include(ExternalProject) 3 | 4 | ExternalProject_Add( 5 | tensorflow_shared 6 | DEPENDS tensorflow_base 7 | TMP_DIR "/tmp" 8 | STAMP_DIR "tensorflow-stamp" 9 | SOURCE_DIR "tensorflow" 10 | BUILD_IN_SOURCE 1 11 | DOWNLOAD_COMMAND "" 12 | UPDATE_COMMAND "" 13 | # The grpc integrated in v1.15.0 needs patching, see https://github.com/clearlinux/distribution/issues/1151. 14 | CONFIGURE_COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/patches/v1.15.0-Rename-gettid-functions.patch" . 15 | COMMAND git apply v1.15.0-Rename-gettid-functions.patch 16 | COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/patches/v1.15.0-workspace.bzl.patch" . 17 | COMMAND git apply v1.15.0-workspace.bzl.patch 18 | COMMAND tensorflow/contrib/makefile/compile_linux_protobuf.sh 19 | # Do not fail on warnings when building nsync 20 | COMMAND sed -i "s/ -Werror//g" tensorflow/contrib/makefile/compile_nsync.sh 21 | COMMAND tensorflow/contrib/makefile/compile_nsync.sh 22 | COMMAND "${CMAKE_CURRENT_BINARY_DIR}/build_tensorflow.sh" 23 | COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/cmake/copy_links.sh" . 24 | # For some reason, Bazel sometimes puts the headers into 25 | # `bazel-genfiles/genfiles` and sometimes just to `bazel-genfiles`. 26 | # So we just create and include both the directories. 27 | COMMAND mkdir -p bazel-genfiles/genfiles 28 | COMMAND touch bazel-genfiles/_placeholder.h 29 | COMMAND touch bazel-genfiles/genfiles/_placeholder.h 30 | BUILD_COMMAND "" 31 | INSTALL_COMMAND "" 32 | ) 33 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/cmake/TensorflowStatic.cmake: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3 FATAL_ERROR) 2 | include(ExternalProject) 3 | 4 | ExternalProject_Add( 5 | tensorflow_static 6 | DEPENDS tensorflow_base 7 | TMP_DIR "/tmp" 8 | STAMP_DIR "tensorflow-stamp" 9 | SOURCE_DIR "tensorflow" 10 | BUILD_IN_SOURCE 1 11 | DOWNLOAD_COMMAND "" 12 | UPDATE_COMMAND "" 13 | CONFIGURE_COMMAND tensorflow/contrib/makefile/build_all_linux.sh 14 | COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/cmake/copy_links.sh" . 15 | COMMAND ./copy_links.sh . 16 | BUILD_COMMAND "" 17 | INSTALL_COMMAND "" 18 | ) 19 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/cmake/build_tensorflow.sh.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Test whether one version ($1) is less than or equal to other ($2). 5 | function version_gt { 6 | test "`printf '%s\n' "$@" | sort -V | head -n 1`" != "$1" 7 | } 8 | 9 | # configure environmental variables 10 | export CC_OPT_FLAGS=${CC_OPT_FLAGS:-"-march=ivybridge"} 11 | export TF_NEED_GCP=${TF_NEED_GCP:-0} 12 | export TF_NEED_HDFS=${TF_NEED_HDFS:-0} 13 | export TF_NEED_OPENCL=${TF_NEED_OPENCL:-0} 14 | export TF_NEED_OPENCL_SYCL=${TF_NEED_OPENCL_SYCL:-0} 15 | export TF_NEED_TENSORRT=${TF_NEED_TENSORRT:-0} 16 | export TF_NEED_NGRAPH=${TF_NEED_NGRAPH:-0} 17 | export TF_NEED_JEMALLOC=${TF_NEED_JEMALLOC:-1} 18 | export TF_NEED_VERBS=${TF_NEED_VERBS:-0} 19 | export TF_NEED_MKL=${TF_NEED_MKL:-1} 20 | export TF_DOWNLOAD_MKL=${TF_DOWNLOAD_MKL:-1} 21 | export TF_NEED_MPI=${TF_NEED_MPI:-0} 22 | export TF_ENABLE_XLA=${TF_ENABLE_XLA:-1} 23 | export TF_NEED_AWS=${TF_NEED_AWS:-0} 24 | export TF_NEED_GDR=${TF_NEED_GDR:-0} 25 | export TF_CUDA_CLANG=${TF_CUDA_CLANG:-0} 26 | export TF_SET_ANDROID_WORKSPACE=${TF_SET_ANDROID_WORKSPACE:-0} 27 | export TF_NEED_KAFKA=${TF_NEED_KAFKA:-0} 28 | export TF_DOWNLOAD_CLANG=${TF_DOWNLOAD_CLANG:-0} 29 | export TF_NEED_IGNITE=${TF_NEED_IGNITE:-0} 30 | export TF_NEED_ROCM=${TF_NEED_ROCM:-0} 31 | export NCCL_INSTALL_PATH=${NCCL_INSTALL_PATH:-/usr} 32 | export PYTHON_BIN_PATH=${PYTHON_BIN_PATH:-"$(which python3)"} 33 | export PYTHON_LIB_PATH="$($PYTHON_BIN_PATH -c 'import site; print(site.getsitepackages()[0])')" 34 | 35 | # check if cuda support requested and supported 36 | if [ "@ALLOW_CUDA@" = "ON" ] && hash nvcc 2>/dev/null; then 37 | echo "CUDA support enabled" 38 | cuda_config_opts="--config=cuda" 39 | export TF_NEED_CUDA=1 40 | export TF_CUDA_COMPUTE_CAPABILITIES=${TF_CUDA_COMPUTE_CAPABILITIES:-"3.5,7.0"} # default from configure.py 41 | export TF_CUDA_PATHS=${TF_CUDA_PATHS:-"/opt/cuda,/usr/local/cuda,/usr/local,/usr/cuda,/usr"} 42 | export TF_CUDA_VERSION="$(nvcc --version | sed -n 's/^.*release \(.*\),.*/\1/p')" 43 | export TF_NCCL_VERSION="$(find / -name 'libnccl.so.*' | tail -n1 | sed -r 's/^.*\.so\.//')" 44 | export TF_CUDNN_VERSION="$(find / -name 'libcudnn.so.*' | tail -n1 | sed -r 's/^.*\.so\.//')" 45 | 46 | # choose the right version of CUDA compiler 47 | if [ -z "$GCC_HOST_COMPILER_PATH" ]; then 48 | if hash gcc-8 2>/dev/null && version_gt 8.5 `gcc-8 -dumpversion`; then 49 | export GCC_HOST_COMPILER_PATH=${GCC_HOST_COMPILER_PATH:-"/usr/bin/gcc-8"} 50 | elif hash gcc-8 2>/dev/null && version_gt 10.1 `gcc-8 -dumpversion`; then 51 | export GCC_HOST_COMPILER_PATH=${GCC_HOST_COMPILER_PATH:-"/usr/bin/gcc-8"} 52 | elif hash gcc-7 2>/dev/null && version_gt 7.5 `gcc-7 -dumpversion`; then 53 | export GCC_HOST_COMPILER_PATH=${GCC_HOST_COMPILER_PATH:-"/usr/bin/gcc-7"} 54 | elif hash gcc-6 2>/dev/null && version_gt 6.4 `gcc-6 -dumpversion`; then 55 | export GCC_HOST_COMPILER_PATH=${GCC_HOST_COMPILER_PATH:-"/usr/bin/gcc-6"} 56 | elif hash gcc-5 2>/dev/null && version_gt 5.5 `gcc-5 -dumpversion`; then 57 | export GCC_HOST_COMPILER_PATH=${GCC_HOST_COMPILER_PATH:-"/usr/bin/gcc-5"} 58 | elif hash gcc-4 2>/dev/null && version_gt 4.9 `gcc-4 -dumpversion`; then 59 | export GCC_HOST_COMPILER_PATH=${GCC_HOST_COMPILER_PATH:-"/usr/bin/gcc-4"} 60 | else 61 | echo "No supported CUDA compiler available. If you are sure your compiler" 62 | echo "version is supported by your CUDA version, please run e.g.:" 63 | echo "export GCC_HOST_COMPILER_PATH=/usr/bin/gcc" 64 | echo "before the build. For the list of supported compilers refer to:" 65 | echo "https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html" 66 | exit 1 67 | fi 68 | fi 69 | 70 | export CLANG_CUDA_COMPILER_PATH=${CLANG_CUDA_COMPILER_PATH:-"/usr/bin/clang"} 71 | export TF_CUDA_CLANG=${TF_CUDA_CLANG:-0} 72 | else 73 | echo "CUDA support disabled" 74 | cuda_config_opts="" 75 | export TF_NEED_CUDA=0 76 | fi 77 | 78 | # configure and build 79 | ./configure 80 | bazel --host_jvm_args=-Xmx4g build --jobs=2 --config=opt \ 81 | --config=monolithic \ 82 | $cuda_config_opts \ 83 | tensorflow:libtensorflow_cc.so 84 | bazel shutdown 85 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/cmake/copy_links.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | # This file recursively traverses a directory and replaces each 4 | # link by a copy of its target. 5 | 6 | echo "Replacing links with the copies of their targets." 7 | echo "This may take a while..." 8 | # To properly handle whitespace characters in filenames, we need to use 9 | # an ugly `find` and `read` trick. 10 | find -L "$1" -depth -print0 | 11 | while IFS= read -r -d $'\0' f; do 12 | # We need to check whether the file is still a link. 13 | # It may have happened that we have already replaced it by 14 | # the original when some of its parent directories were copied. 15 | # Also the first check is to detect whether the file (after 16 | # symlink dereference) exists so that `realpath` does not fail. 17 | if [[ -w "$f" ]] && [[ -L "$f" ]]; then 18 | realf="$(realpath "$f")" 19 | rm "$f" 20 | cp -r --link "$realf" "$f" 2>/dev/null || cp -r "$realf" "$f" 21 | fi 22 | done 23 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/patches/v1.15.0-Rename-gettid-functions.patch: -------------------------------------------------------------------------------- 1 | new file mode 100644 2 | index 00000000..90bd9115 3 | --- /dev/null 4 | +++ b/third_party/Rename-gettid-functions.patch 5 | @@ -0,0 +1,78 @@ 6 | +From d1d017390b799c59d6fdf7b8afa6136d218bdd61 Mon Sep 17 00:00:00 2001 7 | +From: Benjamin Peterson 8 | +Date: Fri, 3 May 2019 08:11:00 -0700 9 | +Subject: [PATCH] Rename gettid() functions. 10 | + 11 | +glibc 2.30 will declare its own gettid; see https://sourceware.org/git/?p=glibc.git;a=commit;h=1d0fc213824eaa2a8f8c4385daaa698ee8fb7c92. Rename the grpc versions to avoid naming conflicts. 12 | +--- 13 | + src/core/lib/gpr/log_linux.cc | 4 ++-- 14 | + src/core/lib/gpr/log_posix.cc | 4 ++-- 15 | + src/core/lib/iomgr/ev_epollex_linux.cc | 4 ++-- 16 | + 3 files changed, 6 insertions(+), 6 deletions(-) 17 | + 18 | +diff --git a/src/core/lib/gpr/log_linux.cc b/src/core/lib/gpr/log_linux.cc 19 | +index 561276f0c20..8b597b4cf2f 100644 20 | +--- a/src/core/lib/gpr/log_linux.cc 21 | ++++ b/src/core/lib/gpr/log_linux.cc 22 | +@@ -40,7 +40,7 @@ 23 | + #include 24 | + #include 25 | + 26 | +-static long gettid(void) { return syscall(__NR_gettid); } 27 | ++static long sys_gettid(void) { return syscall(__NR_gettid); } 28 | + 29 | + void gpr_log(const char* file, int line, gpr_log_severity severity, 30 | + const char* format, ...) { 31 | +@@ -70,7 +70,7 @@ void gpr_default_log(gpr_log_func_args* args) { 32 | + gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); 33 | + struct tm tm; 34 | + static __thread long tid = 0; 35 | +- if (tid == 0) tid = gettid(); 36 | ++ if (tid == 0) tid = sys_gettid(); 37 | + 38 | + timer = static_cast(now.tv_sec); 39 | + final_slash = strrchr(args->file, '/'); 40 | +diff --git a/src/core/lib/gpr/log_posix.cc b/src/core/lib/gpr/log_posix.cc 41 | +index b6edc14ab6b..2f7c6ce3760 100644 42 | +--- a/src/core/lib/gpr/log_posix.cc 43 | ++++ b/src/core/lib/gpr/log_posix.cc 44 | +@@ -31,7 +31,7 @@ 45 | + #include 46 | + #include 47 | + 48 | +-static intptr_t gettid(void) { return (intptr_t)pthread_self(); } 49 | ++static intptr_t sys_gettid(void) { return (intptr_t)pthread_self(); } 50 | + 51 | + void gpr_log(const char* file, int line, gpr_log_severity severity, 52 | + const char* format, ...) { 53 | +@@ -86,7 +86,7 @@ void gpr_default_log(gpr_log_func_args* args) { 54 | + char* prefix; 55 | + gpr_asprintf(&prefix, "%s%s.%09d %7" PRIdPTR " %s:%d]", 56 | + gpr_log_severity_string(args->severity), time_buffer, 57 | +- (int)(now.tv_nsec), gettid(), display_file, args->line); 58 | ++ (int)(now.tv_nsec), sys_gettid(), display_file, args->line); 59 | + 60 | + fprintf(stderr, "%-70s %s\n", prefix, args->message); 61 | + gpr_free(prefix); 62 | +diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc 63 | +index 08116b3ab53..76f59844312 100644 64 | +--- a/src/core/lib/iomgr/ev_epollex_linux.cc 65 | ++++ b/src/core/lib/iomgr/ev_epollex_linux.cc 66 | +@@ -1102,7 +1102,7 @@ static void end_worker(grpc_pollset* pollset, grpc_pollset_worker* worker, 67 | + } 68 | + 69 | + #ifndef NDEBUG 70 | +-static long gettid(void) { return syscall(__NR_gettid); } 71 | ++static long sys_gettid(void) { return syscall(__NR_gettid); } 72 | + #endif 73 | + 74 | + /* pollset->mu lock must be held by the caller before calling this. 75 | +@@ -1122,7 +1122,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset, 76 | + #define WORKER_PTR (&worker) 77 | + #endif 78 | + #ifndef NDEBUG 79 | +- WORKER_PTR->originator = gettid(); 80 | ++ WORKER_PTR->originator = sys_gettid(); 81 | + #endif 82 | + if (grpc_polling_trace.enabled()) { 83 | + gpr_log(GPR_INFO, 84 | -------------------------------------------------------------------------------- /tensorflow_cc/tensorflow_cc/patches/v1.15.0-workspace.bzl.patch: -------------------------------------------------------------------------------- 1 | index 55d7eb93..33e86087 100755 2 | --- a/tensorflow/workspace.bzl 3 | +++ b/tensorflow/workspace.bzl 4 | @@ -486,6 +486,7 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): 5 | # WARNING: make sure ncteisen@ and vpai@ are cc-ed on any CL to change the below rule 6 | tf_http_archive( 7 | name = "grpc", 8 | + patch_file = clean_dep("//third_party:Rename-gettid-functions.patch"), 9 | sha256 = "67a6c26db56f345f7cee846e681db2c23f919eba46dd639b09462d1b6203d28c", 10 | strip_prefix = "grpc-4566c2a29ebec0835643b972eb99f4306c4234a3", 11 | system_build_file = clean_dep("//third_party/systemlibs:grpc.BUILD"), 12 | --------------------------------------------------------------------------------