├── data ├── grace_hopper.jpg └── imagenet_slim_labels.txt ├── cmake └── Modules │ ├── Eigen_VERSION.cmake │ ├── FindEigen.cmake │ └── FindTensorFlow.cmake ├── .gitignore ├── CMakeLists.txt ├── Dockerfile ├── README.md ├── eigen.sh ├── LICENSE └── main.cc /data/grace_hopper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhzrz/tensorflow-cpp/HEAD/data/grace_hopper.jpg -------------------------------------------------------------------------------- /cmake/Modules/Eigen_VERSION.cmake: -------------------------------------------------------------------------------- 1 | set(Eigen_URL https://bitbucket.org/eigen/eigen/get/429aa5254200.tar.gz,http://mirror.bazel.build/bitbucket.org/eigen/eigen/get/429aa5254200.tar.gz,) 2 | set(Eigen_ARCHIVE_HASH 429aa5254200) 3 | set(Eigen_HASH SHA256=61d8b6fc4279dd1dda986fb1677d15e3d641c07a3ea5abe255790b1f0c0c14e9) 4 | set(Eigen_DIR eigen3) 5 | set(Eigen_INSTALL_DIR /usr/local) 6 | -------------------------------------------------------------------------------- /.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 | *.xml 35 | cmake-build-debug/ 36 | .idea/ -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6) 2 | project(hello_tensorflow) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | 6 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") 7 | 8 | link_directories(/usr/lib /usr/local/lib) 9 | # Eigen 10 | find_package(Eigen REQUIRED) 11 | include_directories(${Eigen_INCLUDE_DIRS}) 12 | 13 | # Protobuf 14 | FIND_PACKAGE(Protobuf 3.4.0 REQUIRED) 15 | MESSAGE(STATUS "Using protobuf ${Protobuf_VERSION}") 16 | 17 | # tensorflow 18 | find_package(TensorFlow REQUIRED) 19 | include_directories(${TensorFlow_INCLUDE_DIRS}) 20 | 21 | add_executable(hello_tensorflow main.cc) 22 | target_link_libraries(hello_tensorflow tensorflow_cc tensorflow_framework ${Protobuf_LIBRARIES}) 23 | -------------------------------------------------------------------------------- /cmake/Modules/FindEigen.cmake: -------------------------------------------------------------------------------- 1 | # Finds the required directories to include Eigen. Since Eigen is 2 | # only header files, there is no library to locate, and therefore 3 | # no *_LIBRARIES variable is set. 4 | 5 | include(FindPackageHandleStandardArgs) 6 | include(Eigen_VERSION) 7 | unset(EIGEN_FOUND) 8 | 9 | find_path(Eigen_INCLUDE_DIR 10 | NAMES 11 | ${Eigen_DIR} 12 | ${Eigen_DIR}/unsupported 13 | ${Eigen_DIR}/Eigen 14 | HINTS 15 | ${Eigen_INSTALL_DIR}/include/eigen) 16 | 17 | # set Eigen_FOUND 18 | find_package_handle_standard_args(Eigen DEFAULT_MSG Eigen_INCLUDE_DIR) 19 | 20 | # set external variables for usage in CMakeLists.txt 21 | if(EIGEN_FOUND) 22 | set(Eigen_INCLUDE_DIRS ${Eigen_INCLUDE_DIR} ${Eigen_INCLUDE_DIR}/${Eigen_DIR}) 23 | endif() 24 | 25 | 26 | 27 | # hide locals from GUI 28 | mark_as_advanced(Eigen_INCLUDE_DIR) 29 | -------------------------------------------------------------------------------- /cmake/Modules/FindTensorFlow.cmake: -------------------------------------------------------------------------------- 1 | # Locates the tensorFlow library and include directories. 2 | 3 | include(FindPackageHandleStandardArgs) 4 | unset(TENSORFLOW_FOUND) 5 | 6 | find_path(TensorFlow_INCLUDE_DIR 7 | NAMES 8 | tensorflow/core 9 | tensorflow/cc 10 | third_party 11 | HINTS 12 | /usr/local/include/google/tensorflow 13 | /usr/include/google/tensorflow) 14 | 15 | find_library(TensorFlow_LIBRARY NAMES tensorflow_cc 16 | HINTS 17 | /usr/lib 18 | /usr/local/lib) 19 | 20 | # set TensorFlow_FOUND 21 | find_package_handle_standard_args(TensorFlow DEFAULT_MSG TensorFlow_INCLUDE_DIR TensorFlow_LIBRARY) 22 | 23 | # set external variables for usage in CMakeLists.txt 24 | if(TENSORFLOW_FOUND) 25 | set(TensorFlow_LIBRARIES ${TensorFlow_LIBRARY}) 26 | set(TensorFlow_INCLUDE_DIRS ${TensorFlow_INCLUDE_DIR}) 27 | endif() 28 | 29 | # hide locals from GUI 30 | mark_as_advanced(TensorFlow_INCLUDE_DIR TensorFlow_LIBRARY) 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | autoconf \ 5 | automake \ 6 | ccache \ 7 | curl \ 8 | g++ \ 9 | libtool \ 10 | make \ 11 | unzip \ 12 | wget \ 13 | git \ 14 | && apt-get clean && rm -rf /var/lib/apt/lists/* 15 | 16 | RUN wget https://cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.sh \ 17 | && sed -i 's/interactive=TRUE/interactive=FALSE/g' cmake-3.7.2-Linux-x86_64.sh \ 18 | && sed -i 's/cpack_skip_license=FALSE/cpack_skip_license=TRUE/g' cmake-3.7.2-Linux-x86_64.sh \ 19 | && sh cmake-3.7.2-Linux-x86_64.sh --prefix=/usr \ 20 | && rm -Rf cmake-3.7.2-Linux-x86_64.sh 21 | 22 | RUN git clone https://github.com/google/protobuf \ 23 | && cd protobuf \ 24 | && git checkout v3.4.0 \ 25 | && ./autogen.sh \ 26 | && ./configure --prefix=/usr \ 27 | && make install \ 28 | && cd .. \ 29 | && rm -Rf protobuf 30 | 31 | # Install Bazel 32 | # 1.Install JDK 8 33 | RUN sudo apt-get update \ 34 | && sudo apt-get install -y software-properties-common \ 35 | && sudo add-apt-repository -y ppa:webupd8team/java \ 36 | && sudo apt-get update \ 37 | && echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections \ 38 | && echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections \ 39 | && sudo apt-get install -y oracle-java8-installer \ 40 | # 2. Add Bazel distribution URI as a package source 41 | && echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list \ 42 | && curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - \ 43 | # 3. Install and update Bazel 44 | && sudo apt-get update && sudo apt-get install -y bazel && sudo apt-get upgrade -y bazel \ 45 | && sudo apt-get clean && rm -rf /var/lib/apt/lists/* 46 | 47 | # Install TensorFlow Python dependencies 48 | RUN sudo apt-get update && sudo apt-get install -y \ 49 | python-numpy \ 50 | python-dev \ 51 | python-pip \ 52 | python-wheel \ 53 | swig \ 54 | && sudo apt-get clean && rm -rf /var/lib/apt/lists/* 55 | 56 | RUN mkdir -p /hello_tensorflow 57 | COPY eigen.sh /hello_tensorflow/ 58 | WORKDIR /hello_tensorflow 59 | 60 | # Install TensorFlow 61 | RUN git clone --recurse-submodules -b v1.4.0-rc1 https://github.com/tensorflow/tensorflow.git \ 62 | && cd tensorflow \ 63 | && printf '\n\n\n\n\n\n\n\n\n\n\n\n' | ./configure \ 64 | && bazel build //tensorflow:libtensorflow_cc.so \ 65 | && sudo mkdir -p /usr/local/include/google/tensorflow \ 66 | && sudo cp -r bazel-genfiles/* /usr/local/include/google/tensorflow/ \ 67 | && sudo cp -r tensorflow /usr/local/include/google/tensorflow/ \ 68 | && sudo find /usr/local/include/google/tensorflow -type f ! -name "*.h" -delete \ 69 | && sudo cp -r third_party /usr/local/include/google/tensorflow/ \ 70 | && sudo cp bazel-bin/tensorflow/libtensorflow_cc.so /usr/local/lib \ 71 | && sudo cp bazel-bin/tensorflow/libtensorflow_framework.so /usr/local/lib \ 72 | && cd .. \ 73 | && sudo ./eigen.sh install ./tensorflow /usr/local \ 74 | && rm -Rf tensorflow && rm -Rf ~/.cache 75 | 76 | RUN git clone https://github.com/google/nsync.git \ 77 | && cd nsync \ 78 | && git checkout 839fcc53ff9be58218ed55397deb3f8376a1444e \ 79 | && cmake -DCMAKE_INSTALL_PREFIX=/usr \ 80 | && make -j4 install \ 81 | && cd .. \ 82 | && rm -Rf nsync 83 | 84 | COPY CMakeLists.txt /hello_tensorflow/ 85 | COPY cmake /hello_tensorflow/cmake/ 86 | COPY data /hello_tensorflow/data/ 87 | RUN curl -L "https://storage.googleapis.com/download.tensorflow.org/models/inception_v3_2016_08_28_frozen.pb.tar.gz" | \ 88 | tar -C ./data -xz 89 | COPY main.cc /hello_tensorflow/ 90 | RUN cmake . && make -j4 \ 91 | && ./hello_tensorflow 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tensorflow-cpp 2 | Compile TensorFlow to C++ library for CMake project. 3 | 4 | **NOTE** :This mannual only test under ubuntu 14.04, so other platforms are not guaranteed. 5 | 6 | In general, for compiling tensorflow library as a c++ shared library, we need two other libraries: `protobuf` and `eigen`, and a compiling tool `bazel`. 7 | 8 | If you are quite familiar with `docker`, you can go ahead to look into the `Dockerfile` in this repository and just ignore all the following explanation. 9 | ## Prerequisites 10 | platform: ubuntu 14.04 11 | 12 | ## Step1: Install protobuf (version 3.4.0) 13 | 1. Install protobuf dependencies 14 | ```bash 15 | sudo apt-get update && sudo apt-get install -y \ 16 | autoconf \ 17 | automake \ 18 | ccache \ 19 | curl \ 20 | g++ \ 21 | libtool \ 22 | make \ 23 | unzip \ 24 | wget 25 | ``` 26 | 2: Install protobuf 27 | Be careful, we must install version 3.4.0 as current tensorflow(v1.4.0-rc1) need this version's protobuf. 28 | ```bash 29 | git clone https://github.com/google/protobuf \ 30 | && cd protobuf \ 31 | && git checkout v3.4.0 \ 32 | && ./autogen.sh \ 33 | && ./configure --prefix=/usr \ 34 | && sudo make install \ 35 | && cd .. 36 | ``` 37 | 38 | ## Step2: Install Bazel 39 | 1. Install JDK 8 40 | ```bash 41 | sudo apt-get update \ 42 | && sudo apt-get install -y software-properties-common \ 43 | && sudo add-apt-repository -y ppa:webupd8team/java \ 44 | && sudo apt-get update \ 45 | && echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections \ 46 | && echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections \ 47 | && sudo apt-get install -y oracle-java8-installer 48 | ``` 49 | 2. Add Bazel distribution URI as a package source 50 | ```bash 51 | echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list \ 52 | && curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - 53 | ``` 54 | 3. Install and update Bazel 55 | ```bash 56 | sudo apt-get update && sudo apt-get install -y bazel && sudo apt-get upgrade -y bazel 57 | ``` 58 | 59 | ## Step3: Install TensorFlow Python dependencies 60 | ```bash 61 | sudo apt-get update && sudo apt-get install -y \ 62 | python-numpy \ 63 | python-dev \ 64 | python-pip \ 65 | python-wheel \ 66 | swig 67 | ``` 68 | 69 | ## Step4: Install TensorFlow 70 | ```bash 71 | git clone --recurse-submodules -b v1.4.0-rc1 https://github.com/tensorflow/tensorflow.git \ 72 | && cd tensorflow \ 73 | && printf '\n\n\n\n\n\n\n\n\n\n\n\n' | ./configure \ 74 | && bazel build //tensorflow:libtensorflow_cc.so \ 75 | && sudo mkdir -p /usr/local/include/google/tensorflow \ 76 | && sudo cp -r bazel-genfiles/* /usr/local/include/google/tensorflow/ \ 77 | && sudo cp -r tensorflow /usr/local/include/google/tensorflow/ \ 78 | && sudo find /usr/local/include/google/tensorflow -type f ! -name "*.h" -delete \ 79 | && sudo cp -r third_party /usr/local/include/google/tensorflow/ \ 80 | && sudo cp bazel-bin/tensorflow/libtensorflow_cc.so /usr/local/lib \ 81 | && sudo cp bazel-bin/tensorflow/libtensorflow_framework.so /usr/local/lib \ 82 | && cd .. 83 | ``` 84 | 85 | ## Step5: Install eigen header files 86 | Execute the file `eigen.sh` in this repository as follow, 87 | Please specify `` as the root directory of the TensorFlow repository which cloned in step4, 88 | and `/usr/local` is the directory to where you wish to install eigen. 89 | ```bash 90 | cd tensorflow-cpp 91 | sudo ./eigen.sh install /usr/local 92 | ``` 93 | 94 | ## Step6: Install nsync 95 | For my case(under ubuntu 14.04), i found that i also need another library `nsync` after preparing everything. 96 | If you came across some errors similar to the following, it aproves you also need this: 97 | ```c++ 98 | /usr/local/include/google/tensorflow/tensorflow/core/platform/default/mutex.h:25:22: fatal error: nsync_cv.h: No such file or directory 99 | #include "nsync_cv.h" 100 | ``` 101 | So, just install it as following: 102 | ```bash 103 | git clone https://github.com/google/nsync.git \ 104 | && cd nsync \ 105 | && git checkout 839fcc53ff9be58218ed55397deb3f8376a1444e \ 106 | && cmake -DCMAKE_INSTALL_PREFIX=/usr \ 107 | && sudo make -j4 install 108 | ``` 109 | 110 | ## Testing 111 | After finishing above steps, everything should be ok. 112 | Now let's build a small CMake project which run the official [tensorflow image recognition demo](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/label_image) to validate our work. 113 | 114 | 1. After clone this repository. 115 | 2. Go inside: `cd tensorflow-cpp`, and Download the model data to the `data` directory: 116 | ``` 117 | curl -L "https://storage.googleapis.com/download.tensorflow.org/models/inception_v3_2016_08_28_frozen.pb.tar.gz" | tar -C ./data -xz 118 | ``` 119 | 2. Build this project: `cmake . && make -j4` 120 | 3. Run the binary: `./hello_tensorflow` 121 | 4. If everything is ok, the result should be similar to the following: 122 | ```c++ 123 | 2017-10-27 08:53:28.165985: I tensorflow/core/platform/cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX AVX2 FMA 124 | 2017-10-27 08:53:28.779356: I /tensorflow-cpp/main.cc:250] military uniform (653): 0.834306 125 | 2017-10-27 08:53:28.779484: I /tensorflow-cpp/main.cc:250] mortarboard (668): 0.0218692 126 | 2017-10-27 08:53:28.779523: I /tensorflow-cpp/main.cc:250] academic gown (401): 0.0103579 127 | 2017-10-27 08:53:28.779551: I /tensorflow-cpp/main.cc:250] pickelhaube (716): 0.00800814 128 | 2017-10-27 08:53:28.779732: I /tensorflow-cpp/main.cc:250] bulletproof vest (466): 0.00535088 129 | ``` 130 | 131 | ## Conclusion 132 | If you want to integrate tensorflow c++ library to your c++ project, after building tensorflow c++ library successfully according to the above instructions: 133 | 1. Copy all cmake mond `tensorflow_framework`.dules(Eigen_VERSION.cmake, FindEigen.cmake, FindTensorFlow.cmake) in this repository to your own project's `cmake/Modules` directory. 134 | 2. Add your project's `cmake/Modules` directory to `CMAKE_MODULE_PATH` variable. 135 | 3. Link your executable with two more libraries: `tensorflow_cc` and `tensorflow_framework` -------------------------------------------------------------------------------- /eigen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Author: Connor Weeks 3 | 4 | SCRIPT_DIR="$(cd "$(dirname "${0}")"; pwd)" 5 | NUMJOBS=${NUMJOBS:-1} 6 | RED="\033[1;31m" 7 | YELLOW="\033[1;33m" 8 | GREEN="\033[0;32m" 9 | NO_COLOR="\033[0m" 10 | 11 | ################################### Functions ################################### 12 | 13 | # Prints an error message and exits with an error code of 1 14 | fail () { 15 | echo -e "${RED}Command failed - script terminated${NO_COLOR}" 16 | exit 1 17 | } 18 | 19 | # Prints usage information concerning this script 20 | print_usage () { 21 | echo "| 22 | | Usage: ${0} generate|install [args] 23 | | 24 | | --> ${0} generate installed|external [ ]: 25 | | 26 | | Generates the cmake files for the given installation of tensorflow 27 | | and writes them to . If 'generate installed' is executed, 28 | | corresponds to the directory Eigen was installed to; 29 | | defaults to /usr/local. 30 | | 31 | | --> ${0} install [ ] 32 | | 33 | | Downloads Eigen to (defaults to the current directory), 34 | | and installs it to (defaults to /usr/local). 35 | |" 36 | } 37 | 38 | # Tries to find eigen using the given method 39 | # Methods begin at 0 and increase as integers. 40 | # If this function is called with a method that 41 | # does not exist, it will print an error message 42 | # and exit the program. 43 | find_eigen () { 44 | # Check for argument 45 | if [ -z "${1}" ]; then 46 | fail 47 | fi 48 | # locate eigen archive in tensorflow directory 49 | ANY="[^\)]*" 50 | ANY_NO_QUOTES="[^\)\\\"]*" 51 | ANY_HEX="[a-fA-F0-9]*" 52 | ARCHIVE_HEADER="native.new_http_archive\(\s*" 53 | NAME_START="name\s*=\s*\\\"" 54 | QUOTE_START="\s*=\s*\\\"" 55 | QUOTE_END="\\\"\s*,\s*" 56 | FOOTER="\)" 57 | EIGEN_NAME="${NAME_START}eigen_archive${QUOTE_END}" 58 | EIGEN_REGEX="${ARCHIVE_HEADER}${ANY}${EIGEN_NAME}${ANY}${FOOTER}" 59 | 60 | echo "Finding Eigen version in ${TF_DIR} using method ${1}..." 61 | # check specified format 62 | if [ ${1} -eq 0 ]; then 63 | EIGEN_VERSION_LABEL="eigen_version" 64 | EIGEN_ARCHIVE_HASH_REGEX="${EIGEN_VERSION_LABEL}\s*=\s*\\\"${ANY_HEX}\\\"\s*" 65 | EIGEN_HASH_REGEX="eigen_sha256\s*=\s*\\\"${ANY_HEX}\\\"\s*" 66 | HASH_SED="s/\s*eigen_sha256${QUOTE_START}\(${ANY_HEX}\)\\\"\s*/\1/p" 67 | ARCHIVE_HASH_SED="s/\s*${EIGEN_VERSION_LABEL}${QUOTE_START}\(${ANY_HEX}\)\\\"\s*/\1/p" 68 | 69 | 70 | EIGEN_TEXT=$(grep -Pzo ${EIGEN_REGEX} ${TF_DIR}/tensorflow/workspace.bzl) || fail 71 | EIGEN_ARCHIVE_TEXT=$(grep -Pzo ${EIGEN_ARCHIVE_HASH_REGEX} ${TF_DIR}/tensorflow/workspace.bzl) 72 | EIGEN_HASH_TEXT=$(grep -Pzo ${EIGEN_HASH_REGEX} ${TF_DIR}/tensorflow/workspace.bzl) 73 | 74 | # note that we must determine the eigen archive hash before we determine the URL 75 | EIGEN_HASH=$(echo "${EIGEN_HASH_TEXT}" | sed -n ${HASH_SED}) 76 | EIGEN_ARCHIVE_HASH=$(echo "${EIGEN_ARCHIVE_TEXT}" | sed -n ${ARCHIVE_HASH_SED}) 77 | # the following varibale is split into two parts for readability 78 | URL_SED_1="s/\s*url${QUOTE_START}\(${ANY_NO_QUOTES}\)\\\"\s*+\s*${EIGEN_VERSION_LABEL}\s*+\s*\\\"" 79 | URL_SED_2="\(${ANY_NO_QUOTES}\)${QUOTE_END}/\1${EIGEN_ARCHIVE_HASH}\2/p" 80 | URL_SED=${URL_SED_1}${URL_SED_2} 81 | EIGEN_URL=$(echo "${EIGEN_TEXT}" | sed -n ${URL_SED}) 82 | EIGEN_URLS[0]=${EIGEN_URL} 83 | elif [ ${1} -eq 1 ]; then 84 | # find eigen without 'eigen_version' or 'eigen_sha256' 85 | URL_SED="s/\s*url${QUOTE_START}\(${ANY_NO_QUOTES}\)${QUOTE_END}/\1/p" 86 | HASH_SED="s/\s*sha256${QUOTE_START}\(${ANY_HEX}\)${QUOTE_END}/\1/p" 87 | ARCHIVE_HASH_SED="s=.*/\(${ANY_HEX}\)\\.tar\\.gz=\1=p" 88 | 89 | EIGEN_TEXT=$(grep -Pzo ${EIGEN_REGEX} ${TF_DIR}/tensorflow/workspace.bzl) 90 | EIGEN_URL=$(echo "${EIGEN_TEXT}" | sed -n ${URL_SED}) 91 | EIGEN_URLS[0]=${EIGEN_URL} 92 | EIGEN_HASH=$(echo "${EIGEN_TEXT}" | sed -n ${HASH_SED}) 93 | EIGEN_ARCHIVE_HASH=$(echo "${EIGEN_URL}" | sed -n ${ARCHIVE_HASH_SED}) 94 | elif [ ${1} -eq 2 ]; then 95 | # find eigen using arrays 96 | URL_SED="s/.*urls=\[\([^]]*\)\].*/\1/p" 97 | HASH_SED="s/.*sha256${QUOTE_START}\(${ANY_HEX}\)${QUOTE_END}.*/\1/p" 98 | ARCHIVE_HASH_SED="s=.*/\(${ANY_HEX}\)\\.tar\\.gz.*=\1=p" 99 | 100 | EIGEN_TEXT=$(grep -Pzo ${EIGEN_REGEX} ${TF_DIR}/tensorflow/workspace.bzl) 101 | EIGEN_TEXT=${EIGEN_TEXT//[[:space:]]/} 102 | EIGEN_URL=$(echo "${EIGEN_TEXT}" | sed -n ${URL_SED}) 103 | EIGEN_URL=$(echo "${EIGEN_URL}" | sed 's/\"//g') 104 | IFS=',' read -r -a EIGEN_URLS <<< "${EIGEN_URL}" 105 | EIGEN_HASH=$(echo "${EIGEN_TEXT}" | sed -n ${HASH_SED}) 106 | EIGEN_ARCHIVE_HASH=$(echo "${EIGEN_URL}" | sed -n ${ARCHIVE_HASH_SED}) 107 | else 108 | # no methods left to try 109 | echo -e "${RED}Failure: could not find Eigen version in ${TF_DIR}${NO_COLOR}" 110 | exit 1 111 | fi 112 | # check if all variables were defined and are unempty 113 | if [ -z "${EIGEN_URL}" ] || 114 | [ -z "${EIGEN_URLS}" ] || 115 | [ -z "${EIGEN_HASH}" ] || 116 | [ -z "${EIGEN_ARCHIVE_HASH}" ]; then 117 | # unset varibales and return 1 (not found) 118 | unset EIGEN_URL 119 | unset EIGEN_URLS 120 | unset EIGEN_HASH 121 | unset EIGEN_ARCHIVE_HASH 122 | return 1 123 | fi 124 | # return found 125 | return 0 126 | } 127 | 128 | ################################### Script ################################### 129 | 130 | # validate and assign input 131 | if [ ${#} -lt 2 ]; then 132 | print_usage 133 | exit 1 134 | fi 135 | # Determine mode 136 | if [ "${1}" == "install" ] || [ "${1}" == "generate" ]; then 137 | MODE="${1}" 138 | else 139 | print_usage 140 | exit 1 141 | fi 142 | 143 | # get arguments 144 | if [ "${MODE}" == "install" ]; then 145 | TF_DIR="${2}" 146 | INSTALL_DIR="/usr/local" 147 | DOWNLOAD_DIR="." 148 | if [ ${#} -gt 2 ]; then 149 | INSTALL_DIR="${3}" 150 | fi 151 | if [ ${#} -gt 3 ]; then 152 | DOWNLOAD_DIR="${4}" 153 | fi 154 | elif [ "${MODE}" == "generate" ]; then 155 | GENERATE_MODE="${2}" 156 | if [ "${GENERATE_MODE}" != "installed" ] && [ "${GENERATE_MODE}" != "external" ]; then 157 | print_usage 158 | exit 1 159 | fi 160 | TF_DIR="${3}" 161 | CMAKE_DIR="." 162 | if [ ${#} -gt 3 ]; then 163 | CMAKE_DIR="${4}" 164 | fi 165 | INSTALL_DIR="/usr/local" 166 | if [ "${GENERATE_MODE}" == "installed" ] && [ ${#} -gt 4 ]; then 167 | INSTALL_DIR="${5}" 168 | fi 169 | fi 170 | 171 | # try to find eigen information 172 | N=0 173 | find_eigen ${N} 174 | while [ ${?} -eq 1 ]; do 175 | N=$((N+1)) 176 | find_eigen ${N} 177 | done 178 | 179 | # print information 180 | echo 181 | echo -e "${GREEN}Found Eigen information in ${TF_DIR}:${NO_COLOR}" 182 | echo "Eigen URL(s): ${EIGEN_URLS[*]}" 183 | echo "Eigen URL Hash: ${EIGEN_HASH}" 184 | echo "Eigen Archive Hash: ${EIGEN_ARCHIVE_HASH}" 185 | echo 186 | 187 | # perform requested action 188 | if [ "${MODE}" == "install" ]; then 189 | # donwload eigen and extract to download directory 190 | echo "Downlaoding Eigen to ${DOWNLOAD_DIR}" 191 | cd ${DOWNLOAD_DIR} || fail 192 | rm -rf eigen-eigen-${EIGEN_ARCHIVE_HASH} || fail 193 | rm -f ${EIGEN_ARCHIVE_HASH}.tar.gz* || fail 194 | 195 | # download and check for success 196 | FOUND_URL=0 197 | for URL in "${EIGEN_URLS[@]}"; do 198 | echo "Trying URL: ${URL}" 199 | wget ${URL} && FOUND_URL=1 && break 200 | done 201 | if [ ${FOUND_URL} -eq 0 ]; then 202 | echo "${RED}Could not download eigen${NO_COLOR}" 203 | exit 1 204 | fi 205 | 206 | tar -zxvf ${EIGEN_ARCHIVE_HASH}.tar.gz || fail 207 | cd eigen-eigen-${EIGEN_ARCHIVE_HASH} || fail 208 | # create build directory and build 209 | mkdir build || fail 210 | cd build 211 | cmake -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} .. || fail 212 | make -j$NUMJOBS || fail 213 | make install || fail 214 | echo "Installation complete" 215 | echo "Cleaning up..." 216 | # clean up 217 | cd ../.. 218 | rm -rf eigen-eigen-${EIGEN_ARCHIVE_HASH} || fail 219 | rm -f ${EIGEN_ARCHIVE_HASH}.tar.gz* || fail 220 | elif [ "${MODE}" == "generate" ]; then 221 | OLD_EIGEN=0 222 | if [ "${GENERATE_MODE}" == "installed" ]; then 223 | # try to locate eigen in INSTALL_DIR 224 | if [ -d "${INSTALL_DIR}/include/eigen/eigen-eigen-${EIGEN_ARCHIVE_HASH}" ]; then 225 | # this is how eiegn was stored in older version of TensorFlow 226 | echo -e "${GREEN}Found Eigen in ${INSTALL_DIR}${NO_COLOR}" 227 | elif [ -d "${INSTALL_DIR}/include/eigen3" ]; then 228 | # this is the new way 229 | echo -e "${GREEN}Found Eigen in ${INSTALL_DIR}${NO_COLOR}" 230 | OLD_EIGEN=0 231 | else 232 | echo -e "${YELLOW}Warning: Could not find Eigen in ${INSTALL_DIR}${NO_COLOR}" 233 | fi 234 | fi 235 | 236 | # output Eigen information to file 237 | EIGEN_OUT="${CMAKE_DIR}/Eigen_VERSION.cmake" 238 | echo "set(Eigen_URL ${EIGEN_URL})" > ${EIGEN_OUT} || fail 239 | echo "set(Eigen_ARCHIVE_HASH ${EIGEN_ARCHIVE_HASH})" >> ${EIGEN_OUT} || fail 240 | echo "set(Eigen_HASH SHA256=${EIGEN_HASH})" >> ${EIGEN_OUT} || fail 241 | if [ ${OLD_EIGEN} -eq 1 ]; then 242 | echo "set(Eigen_DIR eigen-eigen-${EIGEN_ARCHIVE_HASH})" >> ${EIGEN_OUT} || fail 243 | else 244 | echo "set(Eigen_DIR eigen3)" >> ${EIGEN_OUT} || fail 245 | fi 246 | 247 | echo "set(Eigen_INSTALL_DIR ${INSTALL_DIR})" >> ${EIGEN_OUT} || fail 248 | echo "Eigen_VERSION.cmake written to ${CMAKE_DIR}" 249 | # perform specific operations regarding installation 250 | if [ "${GENERATE_MODE}" == "external" ]; then 251 | cp ${SCRIPT_DIR}/Eigen.cmake ${CMAKE_DIR} || fail 252 | echo "Wrote Eigen_VERSION.cmake and Eigen.cmake to ${CMAKE_DIR}" 253 | elif [ "${GENERATE_MODE}" == "installed" ]; then 254 | cp ${SCRIPT_DIR}/FindEigen.cmake ${CMAKE_DIR} || fail 255 | echo "FindEigen.cmake copied to ${CMAKE_DIR}" 256 | fi 257 | fi 258 | 259 | echo -e "${GREEN}Done${NO_COLOR}" 260 | exit 0 261 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /data/imagenet_slim_labels.txt: -------------------------------------------------------------------------------- 1 | dummy 2 | tench 3 | goldfish 4 | great white shark 5 | tiger shark 6 | hammerhead 7 | electric ray 8 | stingray 9 | cock 10 | hen 11 | ostrich 12 | brambling 13 | goldfinch 14 | house finch 15 | junco 16 | indigo bunting 17 | robin 18 | bulbul 19 | jay 20 | magpie 21 | chickadee 22 | water ouzel 23 | kite 24 | bald eagle 25 | vulture 26 | great grey owl 27 | European fire salamander 28 | common newt 29 | eft 30 | spotted salamander 31 | axolotl 32 | bullfrog 33 | tree frog 34 | tailed frog 35 | loggerhead 36 | leatherback turtle 37 | mud turtle 38 | terrapin 39 | box turtle 40 | banded gecko 41 | common iguana 42 | American chameleon 43 | whiptail 44 | agama 45 | frilled lizard 46 | alligator lizard 47 | Gila monster 48 | green lizard 49 | African chameleon 50 | Komodo dragon 51 | African crocodile 52 | American alligator 53 | triceratops 54 | thunder snake 55 | ringneck snake 56 | hognose snake 57 | green snake 58 | king snake 59 | garter snake 60 | water snake 61 | vine snake 62 | night snake 63 | boa constrictor 64 | rock python 65 | Indian cobra 66 | green mamba 67 | sea snake 68 | horned viper 69 | diamondback 70 | sidewinder 71 | trilobite 72 | harvestman 73 | scorpion 74 | black and gold garden spider 75 | barn spider 76 | garden spider 77 | black widow 78 | tarantula 79 | wolf spider 80 | tick 81 | centipede 82 | black grouse 83 | ptarmigan 84 | ruffed grouse 85 | prairie chicken 86 | peacock 87 | quail 88 | partridge 89 | African grey 90 | macaw 91 | sulphur-crested cockatoo 92 | lorikeet 93 | coucal 94 | bee eater 95 | hornbill 96 | hummingbird 97 | jacamar 98 | toucan 99 | drake 100 | red-breasted merganser 101 | goose 102 | black swan 103 | tusker 104 | echidna 105 | platypus 106 | wallaby 107 | koala 108 | wombat 109 | jellyfish 110 | sea anemone 111 | brain coral 112 | flatworm 113 | nematode 114 | conch 115 | snail 116 | slug 117 | sea slug 118 | chiton 119 | chambered nautilus 120 | Dungeness crab 121 | rock crab 122 | fiddler crab 123 | king crab 124 | American lobster 125 | spiny lobster 126 | crayfish 127 | hermit crab 128 | isopod 129 | white stork 130 | black stork 131 | spoonbill 132 | flamingo 133 | little blue heron 134 | American egret 135 | bittern 136 | crane 137 | limpkin 138 | European gallinule 139 | American coot 140 | bustard 141 | ruddy turnstone 142 | red-backed sandpiper 143 | redshank 144 | dowitcher 145 | oystercatcher 146 | pelican 147 | king penguin 148 | albatross 149 | grey whale 150 | killer whale 151 | dugong 152 | sea lion 153 | Chihuahua 154 | Japanese spaniel 155 | Maltese dog 156 | Pekinese 157 | Shih-Tzu 158 | Blenheim spaniel 159 | papillon 160 | toy terrier 161 | Rhodesian ridgeback 162 | Afghan hound 163 | basset 164 | beagle 165 | bloodhound 166 | bluetick 167 | black-and-tan coonhound 168 | Walker hound 169 | English foxhound 170 | redbone 171 | borzoi 172 | Irish wolfhound 173 | Italian greyhound 174 | whippet 175 | Ibizan hound 176 | Norwegian elkhound 177 | otterhound 178 | Saluki 179 | Scottish deerhound 180 | Weimaraner 181 | Staffordshire bullterrier 182 | American Staffordshire terrier 183 | Bedlington terrier 184 | Border terrier 185 | Kerry blue terrier 186 | Irish terrier 187 | Norfolk terrier 188 | Norwich terrier 189 | Yorkshire terrier 190 | wire-haired fox terrier 191 | Lakeland terrier 192 | Sealyham terrier 193 | Airedale 194 | cairn 195 | Australian terrier 196 | Dandie Dinmont 197 | Boston bull 198 | miniature schnauzer 199 | giant schnauzer 200 | standard schnauzer 201 | Scotch terrier 202 | Tibetan terrier 203 | silky terrier 204 | soft-coated wheaten terrier 205 | West Highland white terrier 206 | Lhasa 207 | flat-coated retriever 208 | curly-coated retriever 209 | golden retriever 210 | Labrador retriever 211 | Chesapeake Bay retriever 212 | German short-haired pointer 213 | vizsla 214 | English setter 215 | Irish setter 216 | Gordon setter 217 | Brittany spaniel 218 | clumber 219 | English springer 220 | Welsh springer spaniel 221 | cocker spaniel 222 | Sussex spaniel 223 | Irish water spaniel 224 | kuvasz 225 | schipperke 226 | groenendael 227 | malinois 228 | briard 229 | kelpie 230 | komondor 231 | Old English sheepdog 232 | Shetland sheepdog 233 | collie 234 | Border collie 235 | Bouvier des Flandres 236 | Rottweiler 237 | German shepherd 238 | Doberman 239 | miniature pinscher 240 | Greater Swiss Mountain dog 241 | Bernese mountain dog 242 | Appenzeller 243 | EntleBucher 244 | boxer 245 | bull mastiff 246 | Tibetan mastiff 247 | French bulldog 248 | Great Dane 249 | Saint Bernard 250 | Eskimo dog 251 | malamute 252 | Siberian husky 253 | dalmatian 254 | affenpinscher 255 | basenji 256 | pug 257 | Leonberg 258 | Newfoundland 259 | Great Pyrenees 260 | Samoyed 261 | Pomeranian 262 | chow 263 | keeshond 264 | Brabancon griffon 265 | Pembroke 266 | Cardigan 267 | toy poodle 268 | miniature poodle 269 | standard poodle 270 | Mexican hairless 271 | timber wolf 272 | white wolf 273 | red wolf 274 | coyote 275 | dingo 276 | dhole 277 | African hunting dog 278 | hyena 279 | red fox 280 | kit fox 281 | Arctic fox 282 | grey fox 283 | tabby 284 | tiger cat 285 | Persian cat 286 | Siamese cat 287 | Egyptian cat 288 | cougar 289 | lynx 290 | leopard 291 | snow leopard 292 | jaguar 293 | lion 294 | tiger 295 | cheetah 296 | brown bear 297 | American black bear 298 | ice bear 299 | sloth bear 300 | mongoose 301 | meerkat 302 | tiger beetle 303 | ladybug 304 | ground beetle 305 | long-horned beetle 306 | leaf beetle 307 | dung beetle 308 | rhinoceros beetle 309 | weevil 310 | fly 311 | bee 312 | ant 313 | grasshopper 314 | cricket 315 | walking stick 316 | cockroach 317 | mantis 318 | cicada 319 | leafhopper 320 | lacewing 321 | dragonfly 322 | damselfly 323 | admiral 324 | ringlet 325 | monarch 326 | cabbage butterfly 327 | sulphur butterfly 328 | lycaenid 329 | starfish 330 | sea urchin 331 | sea cucumber 332 | wood rabbit 333 | hare 334 | Angora 335 | hamster 336 | porcupine 337 | fox squirrel 338 | marmot 339 | beaver 340 | guinea pig 341 | sorrel 342 | zebra 343 | hog 344 | wild boar 345 | warthog 346 | hippopotamus 347 | ox 348 | water buffalo 349 | bison 350 | ram 351 | bighorn 352 | ibex 353 | hartebeest 354 | impala 355 | gazelle 356 | Arabian camel 357 | llama 358 | weasel 359 | mink 360 | polecat 361 | black-footed ferret 362 | otter 363 | skunk 364 | badger 365 | armadillo 366 | three-toed sloth 367 | orangutan 368 | gorilla 369 | chimpanzee 370 | gibbon 371 | siamang 372 | guenon 373 | patas 374 | baboon 375 | macaque 376 | langur 377 | colobus 378 | proboscis monkey 379 | marmoset 380 | capuchin 381 | howler monkey 382 | titi 383 | spider monkey 384 | squirrel monkey 385 | Madagascar cat 386 | indri 387 | Indian elephant 388 | African elephant 389 | lesser panda 390 | giant panda 391 | barracouta 392 | eel 393 | coho 394 | rock beauty 395 | anemone fish 396 | sturgeon 397 | gar 398 | lionfish 399 | puffer 400 | abacus 401 | abaya 402 | academic gown 403 | accordion 404 | acoustic guitar 405 | aircraft carrier 406 | airliner 407 | airship 408 | altar 409 | ambulance 410 | amphibian 411 | analog clock 412 | apiary 413 | apron 414 | ashcan 415 | assault rifle 416 | backpack 417 | bakery 418 | balance beam 419 | balloon 420 | ballpoint 421 | Band Aid 422 | banjo 423 | bannister 424 | barbell 425 | barber chair 426 | barbershop 427 | barn 428 | barometer 429 | barrel 430 | barrow 431 | baseball 432 | basketball 433 | bassinet 434 | bassoon 435 | bathing cap 436 | bath towel 437 | bathtub 438 | beach wagon 439 | beacon 440 | beaker 441 | bearskin 442 | beer bottle 443 | beer glass 444 | bell cote 445 | bib 446 | bicycle-built-for-two 447 | bikini 448 | binder 449 | binoculars 450 | birdhouse 451 | boathouse 452 | bobsled 453 | bolo tie 454 | bonnet 455 | bookcase 456 | bookshop 457 | bottlecap 458 | bow 459 | bow tie 460 | brass 461 | brassiere 462 | breakwater 463 | breastplate 464 | broom 465 | bucket 466 | buckle 467 | bulletproof vest 468 | bullet train 469 | butcher shop 470 | cab 471 | caldron 472 | candle 473 | cannon 474 | canoe 475 | can opener 476 | cardigan 477 | car mirror 478 | carousel 479 | carpenter's kit 480 | carton 481 | car wheel 482 | cash machine 483 | cassette 484 | cassette player 485 | castle 486 | catamaran 487 | CD player 488 | cello 489 | cellular telephone 490 | chain 491 | chainlink fence 492 | chain mail 493 | chain saw 494 | chest 495 | chiffonier 496 | chime 497 | china cabinet 498 | Christmas stocking 499 | church 500 | cinema 501 | cleaver 502 | cliff dwelling 503 | cloak 504 | clog 505 | cocktail shaker 506 | coffee mug 507 | coffeepot 508 | coil 509 | combination lock 510 | computer keyboard 511 | confectionery 512 | container ship 513 | convertible 514 | corkscrew 515 | cornet 516 | cowboy boot 517 | cowboy hat 518 | cradle 519 | crane 520 | crash helmet 521 | crate 522 | crib 523 | Crock Pot 524 | croquet ball 525 | crutch 526 | cuirass 527 | dam 528 | desk 529 | desktop computer 530 | dial telephone 531 | diaper 532 | digital clock 533 | digital watch 534 | dining table 535 | dishrag 536 | dishwasher 537 | disk brake 538 | dock 539 | dogsled 540 | dome 541 | doormat 542 | drilling platform 543 | drum 544 | drumstick 545 | dumbbell 546 | Dutch oven 547 | electric fan 548 | electric guitar 549 | electric locomotive 550 | entertainment center 551 | envelope 552 | espresso maker 553 | face powder 554 | feather boa 555 | file 556 | fireboat 557 | fire engine 558 | fire screen 559 | flagpole 560 | flute 561 | folding chair 562 | football helmet 563 | forklift 564 | fountain 565 | fountain pen 566 | four-poster 567 | freight car 568 | French horn 569 | frying pan 570 | fur coat 571 | garbage truck 572 | gasmask 573 | gas pump 574 | goblet 575 | go-kart 576 | golf ball 577 | golfcart 578 | gondola 579 | gong 580 | gown 581 | grand piano 582 | greenhouse 583 | grille 584 | grocery store 585 | guillotine 586 | hair slide 587 | hair spray 588 | half track 589 | hammer 590 | hamper 591 | hand blower 592 | hand-held computer 593 | handkerchief 594 | hard disc 595 | harmonica 596 | harp 597 | harvester 598 | hatchet 599 | holster 600 | home theater 601 | honeycomb 602 | hook 603 | hoopskirt 604 | horizontal bar 605 | horse cart 606 | hourglass 607 | iPod 608 | iron 609 | jack-o'-lantern 610 | jean 611 | jeep 612 | jersey 613 | jigsaw puzzle 614 | jinrikisha 615 | joystick 616 | kimono 617 | knee pad 618 | knot 619 | lab coat 620 | ladle 621 | lampshade 622 | laptop 623 | lawn mower 624 | lens cap 625 | letter opener 626 | library 627 | lifeboat 628 | lighter 629 | limousine 630 | liner 631 | lipstick 632 | Loafer 633 | lotion 634 | loudspeaker 635 | loupe 636 | lumbermill 637 | magnetic compass 638 | mailbag 639 | mailbox 640 | maillot 641 | maillot 642 | manhole cover 643 | maraca 644 | marimba 645 | mask 646 | matchstick 647 | maypole 648 | maze 649 | measuring cup 650 | medicine chest 651 | megalith 652 | microphone 653 | microwave 654 | military uniform 655 | milk can 656 | minibus 657 | miniskirt 658 | minivan 659 | missile 660 | mitten 661 | mixing bowl 662 | mobile home 663 | Model T 664 | modem 665 | monastery 666 | monitor 667 | moped 668 | mortar 669 | mortarboard 670 | mosque 671 | mosquito net 672 | motor scooter 673 | mountain bike 674 | mountain tent 675 | mouse 676 | mousetrap 677 | moving van 678 | muzzle 679 | nail 680 | neck brace 681 | necklace 682 | nipple 683 | notebook 684 | obelisk 685 | oboe 686 | ocarina 687 | odometer 688 | oil filter 689 | organ 690 | oscilloscope 691 | overskirt 692 | oxcart 693 | oxygen mask 694 | packet 695 | paddle 696 | paddlewheel 697 | padlock 698 | paintbrush 699 | pajama 700 | palace 701 | panpipe 702 | paper towel 703 | parachute 704 | parallel bars 705 | park bench 706 | parking meter 707 | passenger car 708 | patio 709 | pay-phone 710 | pedestal 711 | pencil box 712 | pencil sharpener 713 | perfume 714 | Petri dish 715 | photocopier 716 | pick 717 | pickelhaube 718 | picket fence 719 | pickup 720 | pier 721 | piggy bank 722 | pill bottle 723 | pillow 724 | ping-pong ball 725 | pinwheel 726 | pirate 727 | pitcher 728 | plane 729 | planetarium 730 | plastic bag 731 | plate rack 732 | plow 733 | plunger 734 | Polaroid camera 735 | pole 736 | police van 737 | poncho 738 | pool table 739 | pop bottle 740 | pot 741 | potter's wheel 742 | power drill 743 | prayer rug 744 | printer 745 | prison 746 | projectile 747 | projector 748 | puck 749 | punching bag 750 | purse 751 | quill 752 | quilt 753 | racer 754 | racket 755 | radiator 756 | radio 757 | radio telescope 758 | rain barrel 759 | recreational vehicle 760 | reel 761 | reflex camera 762 | refrigerator 763 | remote control 764 | restaurant 765 | revolver 766 | rifle 767 | rocking chair 768 | rotisserie 769 | rubber eraser 770 | rugby ball 771 | rule 772 | running shoe 773 | safe 774 | safety pin 775 | saltshaker 776 | sandal 777 | sarong 778 | sax 779 | scabbard 780 | scale 781 | school bus 782 | schooner 783 | scoreboard 784 | screen 785 | screw 786 | screwdriver 787 | seat belt 788 | sewing machine 789 | shield 790 | shoe shop 791 | shoji 792 | shopping basket 793 | shopping cart 794 | shovel 795 | shower cap 796 | shower curtain 797 | ski 798 | ski mask 799 | sleeping bag 800 | slide rule 801 | sliding door 802 | slot 803 | snorkel 804 | snowmobile 805 | snowplow 806 | soap dispenser 807 | soccer ball 808 | sock 809 | solar dish 810 | sombrero 811 | soup bowl 812 | space bar 813 | space heater 814 | space shuttle 815 | spatula 816 | speedboat 817 | spider web 818 | spindle 819 | sports car 820 | spotlight 821 | stage 822 | steam locomotive 823 | steel arch bridge 824 | steel drum 825 | stethoscope 826 | stole 827 | stone wall 828 | stopwatch 829 | stove 830 | strainer 831 | streetcar 832 | stretcher 833 | studio couch 834 | stupa 835 | submarine 836 | suit 837 | sundial 838 | sunglass 839 | sunglasses 840 | sunscreen 841 | suspension bridge 842 | swab 843 | sweatshirt 844 | swimming trunks 845 | swing 846 | switch 847 | syringe 848 | table lamp 849 | tank 850 | tape player 851 | teapot 852 | teddy 853 | television 854 | tennis ball 855 | thatch 856 | theater curtain 857 | thimble 858 | thresher 859 | throne 860 | tile roof 861 | toaster 862 | tobacco shop 863 | toilet seat 864 | torch 865 | totem pole 866 | tow truck 867 | toyshop 868 | tractor 869 | trailer truck 870 | tray 871 | trench coat 872 | tricycle 873 | trimaran 874 | tripod 875 | triumphal arch 876 | trolleybus 877 | trombone 878 | tub 879 | turnstile 880 | typewriter keyboard 881 | umbrella 882 | unicycle 883 | upright 884 | vacuum 885 | vase 886 | vault 887 | velvet 888 | vending machine 889 | vestment 890 | viaduct 891 | violin 892 | volleyball 893 | waffle iron 894 | wall clock 895 | wallet 896 | wardrobe 897 | warplane 898 | washbasin 899 | washer 900 | water bottle 901 | water jug 902 | water tower 903 | whiskey jug 904 | whistle 905 | wig 906 | window screen 907 | window shade 908 | Windsor tie 909 | wine bottle 910 | wing 911 | wok 912 | wooden spoon 913 | wool 914 | worm fence 915 | wreck 916 | yawl 917 | yurt 918 | web site 919 | comic book 920 | crossword puzzle 921 | street sign 922 | traffic light 923 | book jacket 924 | menu 925 | plate 926 | guacamole 927 | consomme 928 | hot pot 929 | trifle 930 | ice cream 931 | ice lolly 932 | French loaf 933 | bagel 934 | pretzel 935 | cheeseburger 936 | hotdog 937 | mashed potato 938 | head cabbage 939 | broccoli 940 | cauliflower 941 | zucchini 942 | spaghetti squash 943 | acorn squash 944 | butternut squash 945 | cucumber 946 | artichoke 947 | bell pepper 948 | cardoon 949 | mushroom 950 | Granny Smith 951 | strawberry 952 | orange 953 | lemon 954 | fig 955 | pineapple 956 | banana 957 | jackfruit 958 | custard apple 959 | pomegranate 960 | hay 961 | carbonara 962 | chocolate sauce 963 | dough 964 | meat loaf 965 | pizza 966 | potpie 967 | burrito 968 | red wine 969 | espresso 970 | cup 971 | eggnog 972 | alp 973 | bubble 974 | cliff 975 | coral reef 976 | geyser 977 | lakeside 978 | promontory 979 | sandbar 980 | seashore 981 | valley 982 | volcano 983 | ballplayer 984 | groom 985 | scuba diver 986 | rapeseed 987 | daisy 988 | yellow lady's slipper 989 | corn 990 | acorn 991 | hip 992 | buckeye 993 | coral fungus 994 | agaric 995 | gyromitra 996 | stinkhorn 997 | earthstar 998 | hen-of-the-woods 999 | bolete 1000 | ear 1001 | toilet tissue 1002 | -------------------------------------------------------------------------------- /main.cc: -------------------------------------------------------------------------------- 1 | /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | ==============================================================================*/ 15 | 16 | // A minimal but useful C++ example showing how to load an Imagenet-style object 17 | // recognition TensorFlow model, prepare input images for it, run them through 18 | // the graph, and interpret the results. 19 | // 20 | // It's designed to have as few dependencies and be as clear as possible, so 21 | // it's more verbose than it could be in production code. In particular, using 22 | // auto for the types of a lot of the returned values from TensorFlow calls can 23 | // remove a lot of boilerplate, but I find the explicit types useful in sample 24 | // code to make it simple to look up the classes involved. 25 | // 26 | // To use it, compile and then run in a working directory with the 27 | // learning/brain/tutorials/label_image/data/ folder below it, and you should 28 | // see the top five labels for the example Lena image output. You can then 29 | // customize it to use your own models or images by changing the file names at 30 | // the top of the main() function. 31 | // 32 | // The googlenet_graph.pb file included by default is created from Inception. 33 | // 34 | // Note that, for GIF inputs, to reuse existing code, only single-frame ones 35 | // are supported. 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include "tensorflow/cc/ops/const_op.h" 42 | #include "tensorflow/cc/ops/image_ops.h" 43 | #include "tensorflow/cc/ops/standard_ops.h" 44 | #include "tensorflow/core/framework/graph.pb.h" 45 | #include "tensorflow/core/framework/tensor.h" 46 | #include "tensorflow/core/graph/default_device.h" 47 | #include "tensorflow/core/graph/graph_def_builder.h" 48 | #include "tensorflow/core/lib/core/errors.h" 49 | #include "tensorflow/core/lib/core/stringpiece.h" 50 | #include "tensorflow/core/lib/core/threadpool.h" 51 | #include "tensorflow/core/lib/io/path.h" 52 | #include "tensorflow/core/lib/strings/stringprintf.h" 53 | #include "tensorflow/core/platform/env.h" 54 | #include "tensorflow/core/platform/init_main.h" 55 | #include "tensorflow/core/platform/logging.h" 56 | #include "tensorflow/core/platform/types.h" 57 | #include "tensorflow/core/public/session.h" 58 | #include "tensorflow/core/util/command_line_flags.h" 59 | 60 | // These are all common classes it's handy to reference with no namespace. 61 | using tensorflow::Flag; 62 | using tensorflow::Tensor; 63 | using tensorflow::Status; 64 | using tensorflow::string; 65 | using tensorflow::int32; 66 | 67 | // Takes a file name, and loads a list of labels from it, one per line, and 68 | // returns a vector of the strings. It pads with empty strings so the length 69 | // of the result is a multiple of 16, because our model expects that. 70 | Status ReadLabelsFile(const string& file_name, std::vector* result, 71 | size_t* found_label_count) { 72 | std::ifstream file(file_name); 73 | if (!file) { 74 | return tensorflow::errors::NotFound("Labels file ", file_name, 75 | " not found."); 76 | } 77 | result->clear(); 78 | string line; 79 | while (std::getline(file, line)) { 80 | result->push_back(line); 81 | } 82 | *found_label_count = result->size(); 83 | const int padding = 16; 84 | while (result->size() % padding) { 85 | result->emplace_back(); 86 | } 87 | return Status::OK(); 88 | } 89 | 90 | static Status ReadEntireFile(tensorflow::Env* env, const string& filename, 91 | Tensor* output) { 92 | tensorflow::uint64 file_size = 0; 93 | TF_RETURN_IF_ERROR(env->GetFileSize(filename, &file_size)); 94 | 95 | string contents; 96 | contents.resize(file_size); 97 | 98 | std::unique_ptr file; 99 | TF_RETURN_IF_ERROR(env->NewRandomAccessFile(filename, &file)); 100 | 101 | tensorflow::StringPiece data; 102 | TF_RETURN_IF_ERROR(file->Read(0, file_size, &data, &(contents)[0])); 103 | if (data.size() != file_size) { 104 | return tensorflow::errors::DataLoss("Truncated read of '", filename, 105 | "' expected ", file_size, " got ", 106 | data.size()); 107 | } 108 | output->scalar()() = data.ToString(); 109 | return Status::OK(); 110 | } 111 | 112 | // Given an image file name, read in the data, try to decode it as an image, 113 | // resize it to the requested size, and then scale the values as desired. 114 | Status ReadTensorFromImageFile(const string& file_name, const int input_height, 115 | const int input_width, const float input_mean, 116 | const float input_std, 117 | std::vector* out_tensors) { 118 | auto root = tensorflow::Scope::NewRootScope(); 119 | using namespace ::tensorflow::ops; // NOLINT(build/namespaces) 120 | 121 | string input_name = "file_reader"; 122 | string output_name = "normalized"; 123 | 124 | // read file_name into a tensor named input 125 | Tensor input(tensorflow::DT_STRING, tensorflow::TensorShape()); 126 | TF_RETURN_IF_ERROR( 127 | ReadEntireFile(tensorflow::Env::Default(), file_name, &input)); 128 | 129 | // use a placeholder to read input data 130 | auto file_reader = 131 | Placeholder(root.WithOpName("input"), tensorflow::DataType::DT_STRING); 132 | 133 | std::vector> inputs = { 134 | {"input", input}, 135 | }; 136 | 137 | // Now try to figure out what kind of file it is and decode it. 138 | const int wanted_channels = 3; 139 | tensorflow::Output image_reader; 140 | if (tensorflow::StringPiece(file_name).ends_with(".png")) { 141 | image_reader = DecodePng(root.WithOpName("png_reader"), file_reader, 142 | DecodePng::Channels(wanted_channels)); 143 | } else if (tensorflow::StringPiece(file_name).ends_with(".gif")) { 144 | // gif decoder returns 4-D tensor, remove the first dim 145 | image_reader = 146 | Squeeze(root.WithOpName("squeeze_first_dim"), 147 | DecodeGif(root.WithOpName("gif_reader"), file_reader)); 148 | } else if (tensorflow::StringPiece(file_name).ends_with(".bmp")) { 149 | image_reader = DecodeBmp(root.WithOpName("bmp_reader"), file_reader); 150 | } else { 151 | // Assume if it's neither a PNG nor a GIF then it must be a JPEG. 152 | image_reader = DecodeJpeg(root.WithOpName("jpeg_reader"), file_reader, 153 | DecodeJpeg::Channels(wanted_channels)); 154 | } 155 | // Now cast the image data to float so we can do normal math on it. 156 | auto float_caster = 157 | Cast(root.WithOpName("float_caster"), image_reader, tensorflow::DT_FLOAT); 158 | // The convention for image ops in TensorFlow is that all images are expected 159 | // to be in batches, so that they're four-dimensional arrays with indices of 160 | // [batch, height, width, channel]. Because we only have a single image, we 161 | // have to add a batch dimension of 1 to the start with ExpandDims(). 162 | auto dims_expander = ExpandDims(root, float_caster, 0); 163 | // Bilinearly resize the image to fit the required dimensions. 164 | auto resized = ResizeBilinear( 165 | root, dims_expander, 166 | Const(root.WithOpName("size"), {input_height, input_width})); 167 | // Subtract the mean and divide by the scale. 168 | Div(root.WithOpName(output_name), Sub(root, resized, {input_mean}), 169 | {input_std}); 170 | 171 | // This runs the GraphDef network definition that we've just constructed, and 172 | // returns the results in the output tensor. 173 | tensorflow::GraphDef graph; 174 | TF_RETURN_IF_ERROR(root.ToGraphDef(&graph)); 175 | 176 | std::unique_ptr session( 177 | tensorflow::NewSession(tensorflow::SessionOptions())); 178 | TF_RETURN_IF_ERROR(session->Create(graph)); 179 | TF_RETURN_IF_ERROR(session->Run({inputs}, {output_name}, {}, out_tensors)); 180 | return Status::OK(); 181 | } 182 | 183 | // Reads a model graph definition from disk, and creates a session object you 184 | // can use to run it. 185 | Status LoadGraph(const string& graph_file_name, 186 | std::unique_ptr* session) { 187 | tensorflow::GraphDef graph_def; 188 | Status load_graph_status = 189 | ReadBinaryProto(tensorflow::Env::Default(), graph_file_name, &graph_def); 190 | if (!load_graph_status.ok()) { 191 | return tensorflow::errors::NotFound("Failed to load compute graph at '", 192 | graph_file_name, "'"); 193 | } 194 | session->reset(tensorflow::NewSession(tensorflow::SessionOptions())); 195 | Status session_create_status = (*session)->Create(graph_def); 196 | if (!session_create_status.ok()) { 197 | return session_create_status; 198 | } 199 | return Status::OK(); 200 | } 201 | 202 | // Analyzes the output of the Inception graph to retrieve the highest scores and 203 | // their positions in the tensor, which correspond to categories. 204 | Status GetTopLabels(const std::vector& outputs, int how_many_labels, 205 | Tensor* indices, Tensor* scores) { 206 | auto root = tensorflow::Scope::NewRootScope(); 207 | using namespace ::tensorflow::ops; // NOLINT(build/namespaces) 208 | 209 | string output_name = "top_k"; 210 | TopK(root.WithOpName(output_name), outputs[0], how_many_labels); 211 | // This runs the GraphDef network definition that we've just constructed, and 212 | // returns the results in the output tensors. 213 | tensorflow::GraphDef graph; 214 | TF_RETURN_IF_ERROR(root.ToGraphDef(&graph)); 215 | 216 | std::unique_ptr session( 217 | tensorflow::NewSession(tensorflow::SessionOptions())); 218 | TF_RETURN_IF_ERROR(session->Create(graph)); 219 | // The TopK node returns two outputs, the scores and their original indices, 220 | // so we have to append :0 and :1 to specify them both. 221 | std::vector out_tensors; 222 | TF_RETURN_IF_ERROR(session->Run({}, {output_name + ":0", output_name + ":1"}, 223 | {}, &out_tensors)); 224 | *scores = out_tensors[0]; 225 | *indices = out_tensors[1]; 226 | return Status::OK(); 227 | } 228 | 229 | // Given the output of a model run, and the name of a file containing the labels 230 | // this prints out the top five highest-scoring values. 231 | Status PrintTopLabels(const std::vector& outputs, 232 | const string& labels_file_name) { 233 | std::vector labels; 234 | size_t label_count; 235 | Status read_labels_status = 236 | ReadLabelsFile(labels_file_name, &labels, &label_count); 237 | if (!read_labels_status.ok()) { 238 | LOG(ERROR) << read_labels_status; 239 | return read_labels_status; 240 | } 241 | const int how_many_labels = std::min(5, static_cast(label_count)); 242 | Tensor indices; 243 | Tensor scores; 244 | TF_RETURN_IF_ERROR(GetTopLabels(outputs, how_many_labels, &indices, &scores)); 245 | tensorflow::TTypes::Flat scores_flat = scores.flat(); 246 | tensorflow::TTypes::Flat indices_flat = indices.flat(); 247 | for (int pos = 0; pos < how_many_labels; ++pos) { 248 | const int label_index = indices_flat(pos); 249 | const float score = scores_flat(pos); 250 | LOG(INFO) << labels[label_index] << " (" << label_index << "): " << score; 251 | } 252 | return Status::OK(); 253 | } 254 | 255 | // This is a testing function that returns whether the top label index is the 256 | // one that's expected. 257 | Status CheckTopLabel(const std::vector& outputs, int expected, 258 | bool* is_expected) { 259 | *is_expected = false; 260 | Tensor indices; 261 | Tensor scores; 262 | const int how_many_labels = 1; 263 | TF_RETURN_IF_ERROR(GetTopLabels(outputs, how_many_labels, &indices, &scores)); 264 | tensorflow::TTypes::Flat indices_flat = indices.flat(); 265 | if (indices_flat(0) != expected) { 266 | LOG(ERROR) << "Expected label #" << expected << " but got #" 267 | << indices_flat(0); 268 | *is_expected = false; 269 | } else { 270 | *is_expected = true; 271 | } 272 | return Status::OK(); 273 | } 274 | 275 | int main(int argc, char* argv[]) { 276 | // These are the command-line flags the program can understand. 277 | // They define where the graph and input data is located, and what kind of 278 | // input the model expects. If you train your own model, or use something 279 | // other than inception_v3, then you'll need to update these. 280 | string image = "./data/grace_hopper.jpg"; 281 | string graph = 282 | "./data/inception_v3_2016_08_28_frozen.pb"; 283 | string labels = 284 | "./data/imagenet_slim_labels.txt"; 285 | int32 input_width = 299; 286 | int32 input_height = 299; 287 | float input_mean = 0; 288 | float input_std = 255; 289 | string input_layer = "input"; 290 | string output_layer = "InceptionV3/Predictions/Reshape_1"; 291 | bool self_test = false; 292 | string root_dir = ""; 293 | std::vector flag_list = { 294 | Flag("image", &image, "image to be processed"), 295 | Flag("graph", &graph, "graph to be executed"), 296 | Flag("labels", &labels, "name of file containing labels"), 297 | Flag("input_width", &input_width, "resize image to this width in pixels"), 298 | Flag("input_height", &input_height, 299 | "resize image to this height in pixels"), 300 | Flag("input_mean", &input_mean, "scale pixel values to this mean"), 301 | Flag("input_std", &input_std, "scale pixel values to this std deviation"), 302 | Flag("input_layer", &input_layer, "name of input layer"), 303 | Flag("output_layer", &output_layer, "name of output layer"), 304 | Flag("self_test", &self_test, "run a self test"), 305 | Flag("root_dir", &root_dir, 306 | "interpret image and graph file names relative to this directory"), 307 | }; 308 | string usage = tensorflow::Flags::Usage(argv[0], flag_list); 309 | const bool parse_result = tensorflow::Flags::Parse(&argc, argv, flag_list); 310 | if (!parse_result) { 311 | LOG(ERROR) << usage; 312 | return -1; 313 | } 314 | 315 | // We need to call this to set up global state for TensorFlow. 316 | tensorflow::port::InitMain(argv[0], &argc, &argv); 317 | if (argc > 1) { 318 | LOG(ERROR) << "Unknown argument " << argv[1] << "\n" << usage; 319 | return -1; 320 | } 321 | 322 | // First we load and initialize the model. 323 | std::unique_ptr session; 324 | string graph_path = tensorflow::io::JoinPath(root_dir, graph); 325 | Status load_graph_status = LoadGraph(graph_path, &session); 326 | if (!load_graph_status.ok()) { 327 | LOG(ERROR) << load_graph_status; 328 | return -1; 329 | } 330 | 331 | // Get the image from disk as a float array of numbers, resized and normalized 332 | // to the specifications the main graph expects. 333 | std::vector resized_tensors; 334 | string image_path = tensorflow::io::JoinPath(root_dir, image); 335 | Status read_tensor_status = 336 | ReadTensorFromImageFile(image_path, input_height, input_width, input_mean, 337 | input_std, &resized_tensors); 338 | if (!read_tensor_status.ok()) { 339 | LOG(ERROR) << read_tensor_status; 340 | return -1; 341 | } 342 | const Tensor& resized_tensor = resized_tensors[0]; 343 | 344 | // Actually run the image through the model. 345 | std::vector outputs; 346 | Status run_status = session->Run({{input_layer, resized_tensor}}, 347 | {output_layer}, {}, &outputs); 348 | if (!run_status.ok()) { 349 | LOG(ERROR) << "Running model failed: " << run_status; 350 | return -1; 351 | } 352 | 353 | // This is for automated testing to make sure we get the expected result with 354 | // the default settings. We know that label 653 (military uniform) should be 355 | // the top label for the Admiral Hopper image. 356 | if (self_test) { 357 | bool expected_matches; 358 | Status check_status = CheckTopLabel(outputs, 653, &expected_matches); 359 | if (!check_status.ok()) { 360 | LOG(ERROR) << "Running check failed: " << check_status; 361 | return -1; 362 | } 363 | if (!expected_matches) { 364 | LOG(ERROR) << "Self-test failed!"; 365 | return -1; 366 | } 367 | } 368 | 369 | // Do something interesting with the results we've generated. 370 | Status print_status = PrintTopLabels(outputs, labels); 371 | if (!print_status.ok()) { 372 | LOG(ERROR) << "Running print failed: " << print_status; 373 | return -1; 374 | } 375 | 376 | return 0; 377 | } 378 | --------------------------------------------------------------------------------