Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
bctcvai committed Jan 31, 2019
2 parents 35b041d + 9f5c8be commit ddf6f7e
Show file tree
Hide file tree
Showing 54 changed files with 3,914 additions and 358 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ option(BUILD_EXAMPLES "Whether to build example executables." ON)

if(MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT /MP")
else()
set(BUILD_CSHARP OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()

set(CXX_STANDARD 11)

# Not Ideal, but let's do this for now -- screwed up Eigen didn't go in
# include.
include_directories(BEFORE /opt/include /opt)
link_directories(/opt/lib)

if(BUILD_DOCS)
add_subdirectory(doc)
endif()
Expand Down
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,24 @@ pretrained models available in our example data (see tutorial). The base
library is written in C++, with bindings available for both Python and C#.
Examples are included for all three languages.

The current release includes a training library for the detection
model. There are immediate plans to expand this library to include
all OpenEM functionality. Currently builds have only been tested on
Windows. We plan to support both Ubuntu and macOS in the future.
The current release also includes a training library for the all OpenEM
functionality. The library is distributed as a native Windows library and
as a Docker image.

Click the image below to see a video of OpenEM in action:

[![OpenEM detection example](https://img.youtube.com/vi/EZ1Xyg_mnhM/0.jpg)](https://youtu.be/EZ1Xyg_mnhM)

### Distributions

Get the latest Windows library from our [GitHub releases page][Releases].

The docker image can be obtained with:

```shell
docker pull cvisionai/openem
```

### Contents

* [Building](doc/build.md)
Expand All @@ -27,3 +36,5 @@ Click the image below to see a video of OpenEM in action:
* [Annotation Guidelines](doc/annotation.md)
* [Library reference](https://jrtcppv.bitbucket.io)

[Releases]: https://github.com/openem-team/openem/releases

175 changes: 175 additions & 0 deletions config/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Top Layer just gets an updated cuda image
FROM nvidia/cuda AS cvbase0
MAINTAINER CVision AI <[email protected]>

# Configure cuDNN
ENV CUDNN_VERSION 7.4.1.5
LABEL com.nvidia.cudnn.version="${CUDNN_VERSION}"

# System packages
# Clean this out first to ensure apt-get update always runs!
RUN rm -fr /var/lib/apt/lists/*
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
libcudnn7=$CUDNN_VERSION-1+cuda10.0 \
libcudnn7-dev=$CUDNN_VERSION-1+cuda10.0 && \
apt-mark hold libcudnn7 && apt-get install -y --no-install-recommends curl git swig pkg-config zip g++ zlib1g-dev unzip \
cmake autoconf automake libtool make mercurial ffmpeg libavcodec-dev \
libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev \
libv4l-dev
RUN apt-get clean
RUN rm -fr /var/lib/apt/lists/*

# Temporary layer to do utility wrangling
# miniconda, eigen, protobuf

FROM cvbase0 AS cvwrangler
# Build and install protobuf
WORKDIR /
RUN git clone -b v3.6.0 https://github.com/protocolbuffers/protobuf.git
WORKDIR protobuf
RUN git submodule update --init --recursive
RUN ./autogen.sh
RUN ./configure --prefix=/opt
RUN make -j8
RUN make -j8 check
RUN make -j8 install
RUN ldconfig
WORKDIR /
RUN rm -rf protobuf

# Build and install eigen
WORKDIR /
RUN hg clone -r ea85a5993547 http://bitbucket.org/eigen/eigen
WORKDIR eigen
RUN mkdir build
WORKDIR build
RUN cmake -DINCLUDE_INSTALL_DIR=/opt ..
RUN make -j8 install
WORKDIR /
RUN rm -rf eigen

# Install miniconda
RUN curl -LO http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
RUN bash Miniconda3-latest-Linux-x86_64.sh -p /miniconda -b
RUN rm Miniconda3-latest-Linux-x86_64.sh
ENV PATH=/miniconda/bin:${PATH}
RUN conda update -y conda

# Install conda packages
RUN conda install -y scikit-image=0.14.0 scikit-learn==0.20.1 opencv==3.4.2 pandas==0.23.4 keras-gpu==2.2.4
RUN conda clean -y -a

# cvbase is now clean of temporary layers used in construction.
FROM cvbase0 AS cvbase
copy --from=cvwrangler /opt /opt
copy --from=cvwrangler /miniconda /miniconda

FROM cvbase AS cvtensorflow
# Install bazel
RUN curl -LO https://github.com/bazelbuild/bazel/releases/download/0.18.0/bazel-0.18.0-installer-linux-x86_64.sh
RUN bash bazel-0.18.0-installer-linux-x86_64.sh --prefix=/bazel
RUN rm bazel-0.18.0-installer-linux-x86_64.sh #
ENV PATH=/bazel/bin:${PATH}

# Build TensorFlow C++ API
RUN mkdir config
RUN git clone -b v1.12.0 https://github.com/tensorflow/tensorflow.git
WORKDIR tensorflow
RUN ln -s /usr/local/cuda/lib64/stubs/libcuda.so /usr/local/cuda/lib64/stubs/libcuda.so.1
ENV LD_LIBRARY_PATH=/usr/local/cuda/lib64/stubs/:$LD_LIBRARY_PATH
COPY config/tf_config.txt /config/tf_config.txt
RUN ./configure < /config/tf_config.txt
RUN bazel build --config=opt --verbose_failures //tensorflow:libtensorflow_cc.so
RUN rm /usr/local/cuda/lib64/stubs/libcuda.so.1

FROM cvbase AS cvopencv
# Build OpenCV with contrib modules
WORKDIR /
RUN git clone -b 3.4.1 https://github.com/opencv/opencv.git opencv_src
RUN git clone -b 3.4.1 https://github.com/opencv/opencv_contrib.git
WORKDIR opencv_src
RUN mkdir build
WORKDIR build
RUN cmake \
-DWITH_FFMPEG=ON \
-DWITH_LIBV4L=ON \
-DBUILD_SHARED_LIBS=OFF \
-DOPENCV_EXTRA_MODULES_PATH=/opencv_contrib/modules \
-DCMAKE_INSTALL_PREFIX=/opencv \
..
RUN make -j8 install
WORKDIR /
RUN rm -rf opencv_src
RUN rm -rf opencv_contrib



FROM cvbase as cvopenem

# Naive Implementation copies everything:
# COPY --from=cvtensorflow /tensorflow /tensorflow
# Bazel hides things in /root which isn't very pleasant.
# Only copy in what we need to build
RUN mkdir -p /tensorflow/lib
RUN mkdir -p /tensorflow/include
RUN mkdir -p /tensorflow/include/bazel-genfiles

COPY --from=cvtensorflow /tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so /tensorflow/lib
COPY --from=cvtensorflow /tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so /tensorflow/lib
COPY --from=cvtensorflow /tensorflow/tensorflow /tensorflow/include/tensorflow
COPY --from=cvtensorflow /tensorflow/third_party /tensorflow/include/third_party
COPY --from=cvtensorflow /tensorflow/bazel-genfiles/tensorflow /tensorflow/include/bazel-genfiles/tensorflow
# Copy abseil to include dir
COPY --from=cvtensorflow /tensorflow/bazel-tensorflow/external/com_google_absl/absl /usr/include/absl

COPY --from=cvopencv /opencv /opencv

# Build and install openem
WORKDIR /
RUN mkdir /openem_src
WORKDIR /openem_src
COPY deploy deploy
COPY train train
COPY doc doc
COPY examples examples
COPY CMakeLists.txt CMakeLists.txt
COPY LICENSE.md LICENSE.md
RUN mkdir build
WORKDIR build
COPY config/tensorflow-config.cmake /config/tensorflow-config.cmake
RUN ln -s /usr/local/cuda/lib64/stubs/libcuda.so /usr/local/cuda/lib64/stubs/libcuda.so.1
ENV LD_LIBRARY_PATH=/usr/local/cuda/lib64/stubs/:${LD_LIBRARY_PATH}
RUN cmake \
-DTensorflow_DIR=/config \
-DOpenCV_DIR=/opencv/share/OpenCV \
-DPYTHON_LIBRARY=/miniconda/lib/libpython3.6m.so \
-DPYTHON_INCLUDE_DIR=/miniconda/include/python3.6m \
-DCMAKE_INSTALL_PREFIX=/openem \
..
RUN make -j8 install
WORKDIR /
RUN rm -rf openem_src
RUN rm -rf opencv

FROM cvbase as cvopenem_deploy
COPY --from=cvopenem /tensorflow /tensorflow
COPY --from=cvopenem /openem /openem

# Add libraries to path
ENV LD_LIBRARY_PATH=/tensorflow/lib:$LD_LIBRARY_PATH
ENV LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH
ENV LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
ENV PATH=/miniconda/bin:$PATH

# Set up environment variables for command line invokation
ENV find_ruler_model /openem_example_data/deploy/find_ruler/find_ruler.pb
ENV detect_model /openem_example_data/deploy/detect/detect.pb
ENV classify_model /openem_example_data/deploy/classify/classify.pb
ENV count_model /openem_example_data/deploy/count/count.pb
ENV video_paths "/openem_example_data/deploy/video/test_video_000.mp4 /openem_example_data/deploy/video/test_video_001.mp4 /openem_example_data/deploy/video/test_video_002.mp4"
ENV video_out "--no_video"

# Define run command
WORKDIR /openem/examples/deploy/python
CMD ["sh", "-c", "python video.py ${find_ruler_model} ${detect_model} ${classify_model} ${count_model} ${video_paths} ${video_out}"]
10 changes: 10 additions & 0 deletions config/tensorflow-config.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
find_package(Threads REQUIRED)
add_library(tensorflow SHARED IMPORTED)
set_target_properties(tensorflow PROPERTIES
IMPORTED_LOCATION
/tensorflow/lib/libtensorflow_cc.so
INTERFACE_INCLUDE_DIRECTORIES
"/tensorflow/include/bazel-genfiles;/tensorflow/include"
INTERFACE_LINK_LIBRARIES
"/tensorflow/lib/libtensorflow_framework.so;${CMAKE_THREAD_LIBS_INIT}"
)
12 changes: 12 additions & 0 deletions config/tf_config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@






Y
10.0




2 changes: 1 addition & 1 deletion deploy/bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ include_directories(../include)
set_source_files_properties(openem.i PROPERTIES CPLUSPLUS ON)

if(BUILD_PYTHON)
find_package(PythonLibs REQUIRED)
find_package(PythonLibs 3 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
swig_add_library(openem TYPE MODULE LANGUAGE python SOURCES openem.i)
swig_link_libraries(openem ${PYTHON_LIBRARIES} openem)
Expand Down
2 changes: 2 additions & 0 deletions deploy/bindings/openem.i
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ namespace std {
%template(VectorVectorVectorFloat) vector<vector<vector<float>>>;
%template(VectorUint8) vector<uint8_t>;
%template(PairIntInt) pair<int, int>;
%template(PairDoubleDouble) pair<double, double>;
%template(PointPair) pair<pair<double, double>, pair<double, double>>;
%template(Rect) array<int, 4>;
%template(Color) array<uint8_t, 3>;
%template(VectorRect) vector<array<int, 4>>;
Expand Down
16 changes: 16 additions & 0 deletions deploy/include/detail/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <future>

#include <opencv2/core.hpp>
#include <opencv2/video.hpp>
#include <tensorflow/core/public/session.h>
#include "image.h"
#include "error_codes.h"
Expand Down Expand Up @@ -125,6 +126,21 @@ tensorflow::Tensor Preprocess(
const cv::Scalar& bias,
bool rgb);

/// Converts ruler endpoints to a transform.
/// @param x0 X-coord of first endpoint.
/// @param y0 Y-coord of first endpoint.
/// @param x1 X-coord of second endpoint.
/// @param y1 Y-coord of second endpoint.
/// @param rows Number of rows in image.
/// @param cols Number of columns in image.
cv::Mat EndpointsToTransform(
double x0,
double y0,
double x1,
double y1,
int rows,
int cols);

} // namespace detail
} // namespace openem

Expand Down
1 change: 1 addition & 0 deletions deploy/include/error_codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum ErrorCode {
kErrorNotContinuous, ///< cv::Mat expected to be continuous.
kErrorRunSession, ///< Failed to run session.
kErrorReadingImage, ///< Failed to read image.
kErrorSavingImage, ///< Failed to save image.
kErrorImageSize, ///< Invalid image data size for given dimensions.
kErrorNumChann, ///< Invalid number of image channels.
kErrorVidFileOpen, ///< Failed to open video file.
Expand Down
8 changes: 4 additions & 4 deletions deploy/include/find_ruler.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,17 @@ class RulerMaskFinder {
/// @return True if ruler is present, false otherwise.
bool RulerPresent(const Image& mask);

/// Finds ruler orientation in a mask.
/// Finds ruler endpoints from a mask.
/// @param mask Mask image.
/// @return Affine transformation matrix.
std::vector<double> RulerOrientation(const Image& mask);
PointPair RulerEndpoints(const Image& mask);

/// Rectifies an image by applying specified rotation. This is
/// meant to make the ruler horizontal in the image.
/// @param image Image to be rectified. May be a mask image.
/// @param transform Transform found with RulerOrientation.
/// @param endpoints Endpoints found with RulerEndpoints.
/// @return Rectified image.
Image Rectify(const Image& image, const std::vector<double>& transform);
Image Rectify(const Image& image, const PointPair& endpoints);

/// Finds region of interest (ROI) on a rectified mask image. The ROI
/// will retain the same aspect ratio as the original image. Size of
Expand Down
23 changes: 12 additions & 11 deletions deploy/include/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define OPENEM_DEPLOY_IMAGE_H_

#include <string>
#include <utility>
#include <vector>
#include <array>
#include <memory>
Expand All @@ -33,6 +34,12 @@ using Rect = std::array<int, 4>;
/// Type for storing RGB color.
using Color = std::array<uint8_t, 3>;

/// Type for storing a pair of points.
using PointPair = std::pair<
std::pair<double, double>,
std::pair<double, double>
>;

/// Class for holding image data.
///
/// This class is a thin wrapper around a cv::Mat. We avoid using
Expand Down Expand Up @@ -66,6 +73,10 @@ class Image {
/// @param color If true, load a color image.
ErrorCode FromFile(const std::string& image_path, bool color=true);

/// Saves to image file.
/// @param image_path Path to image file.
ErrorCode ToFile(const std::string& image_path);

/// Creates an image from existing data. Data is copied.
///
/// This function will check to make sure the size of data
Expand Down Expand Up @@ -123,19 +134,9 @@ class Image {
const Rect& rect,
const Color& color={0, 0, 255},
int linewidth=2,
const std::vector<double>& transform={1.0, 0.0, 0.0, 0.0, 1.0, 0.0},
const PointPair& endpoints={{0.0, 0.0}, {0.0, 0.0}},
const Rect& roi={0, 0, 0, 0});

/// Draws text in the image.
/// @param text Text to write.
/// @param loc Bottom left text corner location on the image.
/// @param color Color of the text.
void DrawText(
const std::string& text,
const std::pair<int, int>& loc={0, 0},
const Color& color={0, 0, 255},
double scale=10.0);

/// Displays the image in a named window.
///
/// Window will be displayed until user closes it.
Expand Down
Loading

0 comments on commit ddf6f7e

Please sign in to comment.