Skip to content
Commits on Source (2)
......@@ -234,7 +234,7 @@ configure_file(
# Setup inference engines
foreach(ENGINE ${FAST_INFERENCE_ENGINES})
message("---- Adding inference engnine ${ENGINE}")
add_dependencies(testFAST ${ENGINE})
#add_dependencies(testFAST ${ENGINE})
endforeach()
if(NOT FAST_BUILD_QT5 AND WIN32)
......
......@@ -23,7 +23,7 @@ If you use FAST for research, please cite this article.
### Download
If you are only interested in using/testing FAST, and not developing FAST, please download a [stable binary release](https://github.com/smistad/FAST/releases).
If you are only interested in using/testing FAST, and not developing FAST, please download a [stable binary release](https://github.com/smistad/FAST/releases). Make sure you have the [requirements](https://github.com/smistad/FAST/wiki/Requirements) installed before using the releases.
### Build
......@@ -36,4 +36,6 @@ To setup and build the framework, see the instructions for your operating system
To start using the framework, see the [Getting started with FAST](https://github.com/smistad/FAST/wiki/Getting-started-with-FAST) guide or the [examples page](https://github.com/smistad/FAST/wiki/Examples).
![Surface mesh extracted from a large abdominal CT scan in about 100 ms using FAST and a modern GPU.](https://github.com/smistad/FAST/wiki/images/surface_extraction.png) ![Ultrasound image segmented using binary thresholding.](https://github.com/smistad/FAST/wiki/images/binary_thresholding.png)
![Surface mesh extracted from a large abdominal CT scan.](https://github.com/smistad/FAST/wiki/images/surface_extraction.png) ![Alpha blending ray casting rendering of a thorax CT image.](https://github.com/smistad/FAST/wiki/images/volume_renderer.jpg)
![Ultrasound image segmentation using neural netwoks.](https://github.com/smistad/FAST/wiki/images/ultrasound_segmentation.jpg) ![Whole slide microscopy image.](https://github.com/smistad/FAST/wiki/images/wsi.jpg)
......@@ -7,7 +7,7 @@ ExternalProject_Add(eigen
BINARY_DIR ${FAST_EXTERNAL_BUILD_DIR}/eigen
#GIT_REPOSITORY "https://github.com/RLovelett/eigen.git"
#GIT_TAG "a46d2e7337c4656f00abe54a8115f6d76153a048"
URL "https://bitbucket.org/eigen/eigen/get/f3a22f35b044.tar.gz"
URL "https://bitbucket.org/eigen/eigen/get/b4890dc.tar.gz"
INSTALL_DIR ${FAST_EXTERNAL_INSTALL_DIR}
CMAKE_CACHE_ARGS
-DCMAKE_BUILD_TYPE:STRING=Release
......
......@@ -5,34 +5,54 @@ include(${PROJECT_SOURCE_DIR}/cmake/Externals.cmake)
if(WIN32)
set(GIT_EXECUTABLE "git.exe")
# Use CMake to build tensorflow on windows
ExternalProject_Add(tensorflow
if(FAST_BUILD_TensorFlow_CPU OR FAST_BUILD_TensorFlow_CUDA)
ExternalProject_Add(tensorflow_download
PREFIX ${FAST_EXTERNAL_BUILD_DIR}/tensorflow
BINARY_DIR ${FAST_EXTERNAL_BUILD_DIR}/tensorflow
GIT_REPOSITORY "https://github.com/smistad/tensorflow.git"
GIT_TAG "fast"
# Need to override this because tensorflow creates a file in the source dir
# and cmake files to stash these files
UPDATE_COMMAND
${GIT_EXECUTABLE} pull origin fast
# Must use CONFIGURE_COMMAND because CMakeLists.txt is not in the src root of tensorflow
GIT_TAG "fast-updated"
UPDATE_COMMAND ""
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
endif()
if(FAST_BUILD_TensorFlow_CPU)
ExternalProject_Add(tensorflow_CPU
DEPENDS tensorflow_download
PREFIX ${FAST_EXTERNAL_BUILD_DIR}/tensorflow
BINARY_DIR ${FAST_EXTERNAL_BUILD_DIR}/tensorflow
DOWNLOAD_COMMAND ""
UPDATE_COMMAND ""
CONFIGURE_COMMAND
${CMAKE_COMMAND}
${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/tensorflow/contrib/cmake/
-G${CMAKE_GENERATOR}
-Thost=x64
-DCMAKE_BUILD_TYPE:STRING=Release
-Dtensorflow_BUILD_PYTHON_BINDINGS=OFF
-Dtensorflow_ENABLE_SNAPPY_SUPPORT=ON
-Dtensorflow_BUILD_CC_EXAMPLE=OFF
-Dtensorflow_BUILD_SHARED_LIB=ON
-Dtensorflow_BUILD_CONTRIB_KERNELS=OFF
-Dtensorflow_ENABLE_GRPC_SUPPORT=OFF
-Dtensorflow_WIN_CPU_SIMD_OPTIONS=/arch:AVX
#-Dtensorflow_ENABLE_GPU=ON
-DCMAKE_VERBOSE_MAKEFILE:BOOL=OFF
-DCMAKE_INSTALL_MESSAGE:BOOL=LAZY
-DCMAKE_INSTALL_PREFIX:STRING=${FAST_EXTERNAL_INSTALL_DIR}
echo "Configuring TensorFlow..." COMMAND
cd ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/ COMMAND
${PROJECT_SOURCE_DIR}/cmake/TensorflowConfigureCPU.bat COMMAND
echo "Done TF configure"
BUILD_COMMAND
echo "Building tensorflow with bazel for CPU.." COMMAND
cd ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/ COMMAND
bazel build --config=opt //tensorflow:tensorflow.dll
INSTALL_COMMAND
echo "Installing tensorflow binary" COMMAND
${CMAKE_COMMAND} -E copy ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/tensorflow.dll.if.lib ${FAST_EXTERNAL_INSTALL_DIR}/lib/tensorflow_CPU.lib COMMAND
${CMAKE_COMMAND} -E copy ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/external/protobuf_archive/protobuf.lib ${FAST_EXTERNAL_INSTALL_DIR}/lib/protobuf.lib COMMAND
${CMAKE_COMMAND} -E copy ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/tensorflow.dll ${FAST_EXTERNAL_INSTALL_DIR}/bin/tensorflow_CPU.dll COMMAND
echo "Installing tensorflow headers" COMMAND
${CMAKE_COMMAND} -E copy_directory ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/tensorflow ${FAST_EXTERNAL_INSTALL_DIR}/include/tensorflow/ COMMAND
echo "Installing tensorflow generated headers" COMMAND
${CMAKE_COMMAND} -E copy_directory ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-genfiles/tensorflow ${FAST_EXTERNAL_INSTALL_DIR}/include/tensorflow/ COMMAND
echo "Installing tensorflow third party headers" COMMAND
${CMAKE_COMMAND} -E copy_directory ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/third_party/ ${FAST_EXTERNAL_INSTALL_DIR}/include/third_party/ COMMAND
#echo "Installing protobuf headers" COMMAND
#${CMAKE_COMMAND} -E copy_directory ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-tensorflow_download/external/protobuf_archive/src/google/ ${FAST_EXTERNAL_INSTALL_DIR}/include/google/ COMMAND
#echo "Installing nsync headers" COMMAND
#xcopy ${src} ${dest} /y COMMAND
echo "Installing absl headers" COMMAND
${CMAKE_COMMAND} -E copy_directory ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-tensorflow_download/external/com_google_absl/absl/ ${FAST_EXTERNAL_INSTALL_DIR}/include/absl/
)
endif()
else(WIN32)
# Use bazel to build tensorflow on linux
set(GIT_EXECUTABLE "git")
......@@ -90,8 +110,8 @@ else(WIN32)
cp -rf ${FAST_EXTERNAL_BUILD_DIR}/tensorflow_rocm/src/tensorflow_download_rocm/third_party/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ &&
echo "Installing protobuf headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow_rocm/src/tensorflow_download_rocm/bazel-out/)/../../../external/protobuf_archive/src/google/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
echo "Installing nsync headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow_rocm/src/tensorflow_download_rocm/bazel-out/)/../../../external/nsync/public/*.h ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
#echo "Installing nsync headers" &&
#bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow_rocm/src/tensorflow_download_rocm/bazel-out/)/../../../external/nsync/public/*.h ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
echo "Installing absl headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow_rocm/src/tensorflow_download_rocm/bazel-out/)/../../../external/com_google_absl/absl/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf"
)
......@@ -112,13 +132,13 @@ else(WIN32)
cd ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/ && bazel build -c opt --config=cuda --copt=-mfpmath=both --copt=-march=core-avx2 //tensorflow:libtensorflow_cc.so
INSTALL_COMMAND
echo "Installing tensorflow binary" &&
cp -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/libtensorflow_cc.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CUDA.so &&
cp -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/libtensorflow_framework.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_framework_CUDA.so &&
cp -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/libtensorflow_cc.so.1.14.0 ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CUDA.so &&
cp -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/libtensorflow_framework.so.1.14.0 ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_framework_CUDA.so &&
chmod a+w ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CUDA.so &&
chmod a+w ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_framework_CUDA.so &&
patchelf --set-soname libtensorflow_cc_CUDA.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CUDA.so &&
patchelf --set-soname libtensorflow_framework_CUDA.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_framework_CUDA.so &&
patchelf --replace-needed libtensorflow_framework.so libtensorflow_framework_CUDA.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CUDA.so &&
patchelf --replace-needed libtensorflow_framework.so.1 libtensorflow_framework_CUDA.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CUDA.so &&
#echo "Installing mkl binaries" &&
#bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/mkl/lib/libmklml_intel.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/ -Rf" &&
#bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/mkl/lib/libiomp5.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/ -Rf" &&
......@@ -130,8 +150,8 @@ else(WIN32)
cp -rf ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/third_party/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ &&
echo "Installing protobuf headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/protobuf_archive/src/google/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
echo "Installing nsync headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/nsync/public/*.h ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
#echo "Installing nsync headers" &&
#bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/nsync/public/*.h ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
echo "Installing absl headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/com_google_absl/absl/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf"
)
......@@ -152,13 +172,13 @@ else(WIN32)
cd ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/ && bazel build --config=opt --copt=-mfpmath=both --copt=-march=core-avx2 //tensorflow:libtensorflow_cc.so
INSTALL_COMMAND
echo "Installing tensorflow binary" &&
cp -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/libtensorflow_cc.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CPU.so &&
cp -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/libtensorflow_framework.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_framework_CPU.so &&
cp -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/libtensorflow_cc.so.1.14.0 ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CPU.so &&
cp -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-bin/tensorflow/libtensorflow_framework.so.1.14.0 ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_framework_CPU.so &&
chmod a+w ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CPU.so &&
chmod a+w ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_framework_CPU.so &&
patchelf --set-soname libtensorflow_cc_CPU.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CPU.so &&
patchelf --set-soname libtensorflow_framework_CPU.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_framework_CPU.so &&
patchelf --replace-needed libtensorflow_framework.so libtensorflow_framework_CPU.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CPU.so &&
patchelf --replace-needed libtensorflow_framework.so.1 libtensorflow_framework_CPU.so ${FAST_EXTERNAL_INSTALL_DIR}/lib/libtensorflow_cc_CPU.so &&
echo "Installing tensorflow headers" &&
cp -rf ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/tensorflow/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ &&
echo "Installing tensorflow generated headers" &&
......@@ -167,11 +187,10 @@ else(WIN32)
cp -rf ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/third_party/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ &&
echo "Installing protobuf headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/protobuf_archive/src/google/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
echo "Installing nsync headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/nsync/public/*.h ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
#echo "Installing nsync headers" &&
#bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/nsync/public/*.h ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf" &&
echo "Installing absl headers" &&
bash -c "cp $(readlink -f ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/bazel-out/)/../../../external/com_google_absl/absl/ ${FAST_EXTERNAL_INSTALL_DIR}/include/ -Rf"
)
endif()
endif(WIN32)
......@@ -41,6 +41,9 @@ elseif(APPLE)
)
else()
file(GLOB SOs ${PROJECT_BINARY_DIR}/lib/*.so*)
foreach(SO ${SOs})
execute_process(COMMAND echo "Setting runtime path of ${SO}" COMMAND patchelf --set-rpath "$ORIGIN/../lib" ${SO})
endforeach()
install(FILES ${SOs}
DESTINATION fast/lib
)
......@@ -212,7 +215,7 @@ install(FILES ${PROJECT_SOURCE_DIR}/cmake/InstallFiles/Semaphore_LICENSE.txt
if(FAST_MODULE_TensorFlow)
# Tensorflow license
install(FILES ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow/LICENSE
install(FILES ${FAST_EXTERNAL_BUILD_DIR}/tensorflow/src/tensorflow_download/LICENSE
DESTINATION fast/licenses/tensorflow/
)
endif()
......
## TensorFlow module
if(FAST_MODULE_TensorFlow)
message("-- Tensorflow module enabled.")
message("-- TensorFlow module enabled. Select which TensorFlow versions to build (CPU/CUDA/ROCM).")
option(FAST_BUILD_TensorFlow_CUDA "Build TensorFlow CUDA/cuDNN version" OFF)
option(FAST_BUILD_TensorFlow_ROCm "Build TensorFlow ROCm version" OFF)
option(FAST_BUILD_TensorFlow_CPU "Build TensorFlow CPU version" ON)
if(NOT WIN32)
option(FAST_BUILD_TensorFlow_ROCm "Build TensorFlow ROCm version" OFF)
endif()
include(${PROJECT_SOURCE_DIR}/cmake/ExternalTensorflow.cmake)
## Tensorflow
......@@ -12,21 +14,14 @@ if(FAST_MODULE_TensorFlow)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_definitions(-DEIGEN_AVOID_STL_ARRAY)
if(WIN32)
# Some definitions needed to compile with tensorflow on windows
# These are taken from tensorflow/contrib/cmake/CMakeLists.txt
add_definitions(-DNOMINMAX -D_WIN32_WINNT=0x0A00 -DLANG_CXX11 -DCOMPILER_MSVC -D__VERSION__=\"MSVC\")
add_definitions(-DWIN32 -DOS_WIN -D_MBCS -DWIN64 -DPLATFORM_WINDOWS)
add_definitions(-DTENSORFLOW_USE_EIGEN_THREADPOOL -DEIGEN_HAS_C99_MATH -D_ITERATOR_DEBUG_LEVEL=0)
# Suppress warnings to reduce build log size.
add_definitions(/wd4267 /wd4244 /wd4800 /wd4503 /wd4554 /wd4996 /wd4348 /wd4018)
add_definitions(/wd4099 /wd4146 /wd4267 /wd4305 /wd4307)
add_definitions(/wd4715 /wd4722 /wd4723 /wd4838 /wd4309 /wd4334)
# To get rid of this error: Not found: No session factory registered for the given session options: {target: "" config: } Registered factories are {}.
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /WHOLEARCHIVE:\"${Tensorflow_LIBRARY}\"")
set(TensorFlow_LIBRARIES
tensorflow.lib
#libprotobuf.lib # For windows we need this protobuf static lib for some reason..
set(TensorFlow_CUDA_LIBRARIES
${FAST_EXTERNAL_INSTALL_DIR}/lib/tensorflow_CUDA.lib
)
set(TensorFlow_ROCm_LIBRARIES
${FAST_EXTERNAL_INSTALL_DIR}/lib/tensorflow_ROCm.lib
)
set(TensorFlow_CPU_LIBRARIES
${FAST_EXTERNAL_INSTALL_DIR}/lib/tensorflow_CPU.lib
)
else()
set(TensorFlow_CUDA_LIBRARIES
......
rem Setup environment variables so that configure command will not ask user for input by keyboard
setx CC_OPT_FLAGS "/arch:AVX2"
setx TF_NEED_GCP 0
setx TF_NEED_HDFS 0
setx TF_NEED_OPENCL 0
setx TF_NEED_OPENCL_SYCL 0
setx TF_NEED_COMPUTECPP 0
setx TF_NEED_TENSORRT 0
setx TF_NEED_KAFKA 0
setx TF_NEED_JEMALLOC 1
setx TF_NEED_VERBS 0
setx TF_NEED_MKL 0
setx TF_NEED_ROCM 0
setx TF_SET_ANDROID_WORKSPACE 0
setx TF_DOWNLOAD_MKL 0
setx TF_DOWNLOAD_CLANG 0
setx TF_NEED_MPI 0
setx TF_NEED_S3 0
setx TF_NEED_GDR 0
setx TF_ENABLE_XLA 0
setx TF_CUDA_CLANG 0
setx TF_NEED_CUDA 0
setx TF_NCCL_VERSION " "
setx PYTHON_BIN_PATH "$(which python3)"
setx PYTHON_LIB_PATH "$($PYTHON_BIN_PATH -c 'import site; print(site.getsitepackages()[0])')"
python configure.py
......@@ -21,7 +21,7 @@ export TF_NEED_S3=0
export TF_NEED_GDR=0
export TF_ENABLE_XLA=0
export TF_CUDA_CLANG=0
export TF_NCCL_VERSION=" "
#export TF_NCCL_VERSION=" "
export PYTHON_BIN_PATH="$(which python3)"
export PYTHON_LIB_PATH="$($PYTHON_BIN_PATH -c 'import site; print(site.getsitepackages()[0])')"
......@@ -32,7 +32,7 @@ if [ -e /usr/local/cuda ]; then
export TF_NEED_CUDA=1
export TF_CUDA_COMPUTE_CAPABILITIES="3.5,5.2,6.1"
export CUDA_TOOLKIT_PATH=/usr/local/cuda
export CUDNN_INSTALL_PATH=/usr/local/cuda
export CUDNN_INSTALL_PATH=/usr/
export TF_CUDA_VERSION="$($CUDA_TOOLKIT_PATH/bin/nvcc --version | sed -n 's/^.*release \(.*\),.*/\1/p')"
export TF_CUDNN_VERSION="$(sed -n 's/^#define CUDNN_MAJOR\s*\(.*\).*/\1/p' $CUDNN_INSTALL_PATH/include/cudnn.h)"
export GCC_HOST_COMPILER_PATH=/usr/bin/gcc
......
......@@ -9,7 +9,8 @@ PatchStitcher::PatchStitcher() {
createInputPort<DataObject>(0); // Can be Image, Batch or Tensor
createOutputPort<DataObject>(0); // Can be Image or Tensor
createOpenCLProgram(Config::getKernelSourcePath() + "/Algorithms/ImagePatch/PatchStitcher.cl");
createOpenCLProgram(Config::getKernelSourcePath() + "/Algorithms/ImagePatch/PatchStitcher2D.cl", "2D");
createOpenCLProgram(Config::getKernelSourcePath() + "/Algorithms/ImagePatch/PatchStitcher3D.cl", "3D");
}
void PatchStitcher::execute() {
......@@ -97,17 +98,23 @@ void PatchStitcher::processImage(SharedPointer<Image> patch) {
int fullDepth = 1;
float patchSpacingZ = 1.0f;
bool is3D = true;
try {
fullDepth = std::stoi(patch->getFrameData("original-depth"));
patchSpacingZ = std::stof(patch->getFrameData("patch-spacing-z"));
} catch(Exception &e) {
// If exception: is a 2D image
is3D = false;
}
if(!m_outputImage) {
// Create output image
m_outputImage = Image::New();
if(is3D) {
m_outputImage->create(fullWidth, fullHeight, fullDepth, patch->getDataType(), patch->getNrOfChannels());
} else {
m_outputImage->create(fullWidth, fullHeight, patch->getDataType(), patch->getNrOfChannels());
}
m_outputImage->fill(0);
m_outputImage->setSpacing(Vector3f(patchSpacingX, patchSpacingY, patchSpacingZ));
try {
......@@ -127,7 +134,7 @@ void PatchStitcher::processImage(SharedPointer<Image> patch) {
auto patchAccess = patch->getOpenCLImageAccess(ACCESS_READ, device);
if(fullDepth == 1) {
cl::Program program = getOpenCLProgram(device);
cl::Program program = getOpenCLProgram(device, "2D");
const int startX = std::stoi(patch->getFrameData("patchid-x")) * std::stoi(patch->getFrameData("patch-width"));
const int startY = std::stoi(patch->getFrameData("patchid-y")) * std::stoi(patch->getFrameData("patch-height"));
const int endX = startX + patch->getWidth();
......@@ -159,7 +166,7 @@ void PatchStitcher::processImage(SharedPointer<Image> patch) {
if(device->isWritingTo3DTexturesSupported()) {
auto outputAccess = m_outputImage->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
cl::Program program = getOpenCLProgram(device);
cl::Program program = getOpenCLProgram(device, "3D");
cl::Kernel kernel(program, "applyPatch3D");
kernel.setArg(0, *patchAccess->get3DImage());
kernel.setArg(2, startX);
......@@ -175,7 +182,7 @@ void PatchStitcher::processImage(SharedPointer<Image> patch) {
);
} else {
auto outputAccess = m_outputImage->getOpenCLBufferAccess(ACCESS_READ_WRITE, device);
cl::Program program = getOpenCLProgram(device, "", "-DTYPE=" + getCTypeAsString(m_outputImage->getDataType()));
cl::Program program = getOpenCLProgram(device, "3D", "-DTYPE=" + getCTypeAsString(m_outputImage->getDataType()));
cl::Kernel kernel(program, "applyPatch3D");
kernel.setArg(0, *patchAccess->get3DImage());
kernel.setArg(1, *outputAccess->get());
......
__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;
__kernel void applyPatch2D(
__read_only image2d_t patch,
__write_only image2d_t image,
__private int startX,
__private int startY
) {
const int2 pos = {get_global_id(0) + startX, get_global_id(1) + startY};
int dataType = get_image_channel_data_type(image);
if(dataType == CLK_FLOAT) {
write_imagef(image, pos, read_imagef(patch, sampler, pos - (int2)(startX, startY)));
} else if(dataType == CLK_UNSIGNED_INT8 || dataType == CLK_UNSIGNED_INT16) {
write_imageui(image, pos, read_imageui(patch, sampler, pos - (int2)(startX, startY)));
} else {
write_imagei(image, pos, read_imagei(patch, sampler, pos - (int2)(startX, startY)));
}
}
__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;
__kernel void applyPatch2D(
__read_only image2d_t patch,
__write_only image2d_t image,
__private int startX,
__private int startY
) {
const int2 pos = {get_global_id(0) + startX, get_global_id(1) + startY};
int dataType = get_image_channel_data_type(image);
if(dataType == CLK_FLOAT) {
write_imagef(image, pos, read_imagef(patch, sampler, pos - (int2)(startX, startY)));
} else if(dataType == CLK_UNSIGNED_INT8 || dataType == CLK_UNSIGNED_INT16) {
write_imageui(image, pos, read_imageui(patch, sampler, pos - (int2)(startX, startY)));
} else {
write_imagei(image, pos, read_imagei(patch, sampler, pos - (int2)(startX, startY)));
}
}
#ifdef fast_3d_image_writes
__kernel void applyPatch3D(
__read_only image3d_t patch,
......
......@@ -54,6 +54,7 @@ void InferenceEngineManager::loadAll() {
std::string name = item.substr(prefix.size(), item.rfind('.') - prefix.size());
Reporter::info() << "Loading inference engine " << name << " from shared library " << item << Reporter::end();
#ifdef WIN32
SetErrorMode(SEM_FAILCRITICALERRORS); // TODO To avoid diaglog box, when not able to load a DLL
auto handle = LoadLibrary(item.c_str());
if(!handle) {
Reporter::warning() << "Failed to load plugin because " << GetLastErrorAsString() << Reporter::end();
......
#include "TensorFlowEngine.hpp"
//#define TF_CPP_MIN_LOG_LEVEL 5
//#define TF_CPP_MIN_VLOG_LEVEL 5
// Windows hack for removing need for protobuf
#ifdef WIN32
#include <google/protobuf/stubs/logging.h>
......@@ -8,20 +10,22 @@
!(CONDITION) ? std::clog : std::cerr
// end hack
#endif
#include <tensorflow/core/framework/step_stats.pb.h>
#include <tensorflow/core/framework/tensor.h>
#include <tensorflow/core/framework/types.pb.h>
#include <tensorflow/core/lib/strings/stringprintf.h>
#include <tensorflow/core/platform/env.h>
#include <tensorflow/core/platform/mutex.h>
#include <tensorflow/core/platform/types.h>
//#include <tensorflow/core/framework/step_stats.pb.h>
//#include <tensorflow/core/framework/tensor.h>
//#include <tensorflow/core/framework/types.pb.h>
//#include <tensorflow/core/lib/strings/stringprintf.h>
//#include <tensorflow/core/platform/env.h>
//#include <tensorflow/core/platform/mutex.h>
//#include <tensorflow/core/platform/types.h>
#include <tensorflow/core/public/session.h>
#include <tensorflow/core/graph/default_device.h>
#include <tensorflow/core/platform/init_main.h>
#include <tensorflow/cc/framework/ops.h>
#include <tensorflow/core/platform/logging.h>
//#include <tensorflow/core/graph/default_device.h>
//#include <tensorflow/core/platform/init_main.h>
//#include <tensorflow/cc/framework/ops.h>
//#include <tensorflow/core/platform/logging.h>
#include <FAST/Utility.hpp>
namespace fast {
......@@ -173,15 +177,23 @@ void TensorFlowEngine::load() {
const auto networkFilename = getFilename();
tensorflow::SessionOptions options;
tensorflow::ConfigProto &config = options.config;
tensorflow::GPUOptions* gpuOptions = config.mutable_gpu_options();
#ifndef WIN32
// These lines cause linking issues on windows
config.mutable_gpu_options()->set_allow_growth(true); // Set this so that tensorflow will not use up all GPU memory
if(m_deviceIndex >= 0)
gpuOptions->set_visible_device_list(std::to_string(m_deviceIndex));
gpuOptions->set_allow_growth(true); // Set this so that tensorflow will not use up all GPU memory
config.mutable_gpu_options()->set_visible_device_list(std::to_string(m_deviceIndex));
#endif
/*
tensorflow::GPUOptions* gpuOptions = config.mutable_gpu_options();
gpuOptions->set_allow_growth(true);
//gpuOptions->set_per_process_gpu_memory_fraction(0.5);
*/
mSession.reset(tensorflow::NewSession(options));
tensorflow::GraphDef tensorflow_graph;
{
if(!fileExists(networkFilename))
throw Exception(networkFilename + " does not exist");
reportInfo() << "Loading network file: " << networkFilename << reportEnd();
tensorflow::Status s = ReadBinaryProto(tensorflow::Env::Default(), networkFilename, &tensorflow_graph);
if (!s.ok()) {
......@@ -194,6 +206,7 @@ void TensorFlowEngine::load() {
if(mInputNodes.size() == 0) {
nodesSpecified = false;
}
for(int i = 0; i < tensorflow_graph.node_size(); ++i) {
tensorflow::NodeDef node = tensorflow_graph.node(i);
if(mInputNodes.count(node.name()) > 0) {
......
......@@ -76,7 +76,7 @@ TEST_CASE("Execute NN on single 2D image", "[fast][neuralnetwork][visual][ultras
window->addRenderer(imageRenderer);
window->addRenderer(segmentationRenderer);
window->set2DMode();
window->setTimeout(10000);
window->setTimeout(5000);
window->start();
segmentation->getAllRuntimes()->printAll();
}
......@@ -145,7 +145,7 @@ TEST_CASE("Multi input single output network", "[fast][neuralnetwork]") {
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape({-1, 1, 64, 64}));
network->setInputNode(1, "input_2", NodeType::IMAGE, TensorShape({-1, 1, 64, 64}));
network->setOutputNode(0, "dense/BiasAdd", NodeType::TENSOR);
network->setOutputNode(0, "dense/BiasAdd", NodeType::TENSOR, TensorShape({-1,6}));
network->load(Config::getTestDataPath() + "NeuralNetworkModels/multi_input_single_output_channels_first.uff");
} else {
network->load(Config::getTestDataPath() + "NeuralNetworkModels/multi_input_single_output.xml");
......@@ -174,8 +174,8 @@ TEST_CASE("Single input multi output network", "[fast][neuralnetwork]") {
network->load(Config::getTestDataPath() + "NeuralNetworkModels/single_input_multi_output.pb");
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape({-1, 1, 64, 64}));
network->setOutputNode(0, "dense_1/BiasAdd", NodeType::TENSOR);
network->setOutputNode(1, "dense_2/BiasAdd", NodeType::TENSOR);
network->setOutputNode(0, "dense_1/BiasAdd", NodeType::TENSOR, TensorShape({-1, 6}));
network->setOutputNode(1, "dense_2/BiasAdd", NodeType::TENSOR, TensorShape({-1, 6}));
network->load(
Config::getTestDataPath() + "NeuralNetworkModels/single_input_multi_output_channels_first.uff");
} else {
......@@ -255,8 +255,8 @@ TEST_CASE("Execute NN on batch of 2D images", "[fast][neuralnetwork][batch]") {
network->load(Config::getTestDataPath() + "NeuralNetworkModels/single_input_multi_output.pb");
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape({-1, 1, 64, 64}));
network->setOutputNode(0, "dense_1/BiasAdd", NodeType::TENSOR);
network->setOutputNode(1, "dense_2/BiasAdd", NodeType::TENSOR);
network->setOutputNode(0, "dense_1/BiasAdd", NodeType::TENSOR, TensorShape({-1, 6}));
network->setOutputNode(1, "dense_2/BiasAdd", NodeType::TENSOR, TensorShape({-1, 6}));
network->load(Config::getTestDataPath() + "NeuralNetworkModels/single_input_multi_output_channels_first.uff");
} else {
network->load(Config::getTestDataPath() + "NeuralNetworkModels/single_input_multi_output.xml");
......
......@@ -30,9 +30,12 @@
using namespace fast;
TEST_CASE("Volume -> Patch generator -> Neural network -> Patch stitcher -> visualize", "[fast][neuralnetwork][volume][visual]") {
for(auto& engine : InferenceEngineManager::getEngineList()) {
if(engine.substr(0, 10) != "TensorFlow") // Only TensorFlow can run this example atm
continue;
auto importer = ImageFileImporter::New();
//importer->setFilename(Config::getTestDataPath() + "/CT/CT-Thorax.mhd");
importer->setFilename(Config::getTestDataPath() + "/CT/LIDC-IDRI-0072/01-01-2000-CT CHEST W CONT-45499/4-Recon 3-88650/000001.dcm");
importer->setFilename(Config::getTestDataPath() + "/CT/LIDC-IDRI-0072/000001.dcm");
/*
auto hounsefieldConverter = HounsefieldConverter::New();
......@@ -46,17 +49,17 @@ TEST_CASE("Volume -> Patch generator -> Neural network -> Patch stitcher -> visu
*/
auto generator = PatchGenerator::New();
generator->setPatchSize(512, 512, 64);
generator->setPatchSize(512, 512, 32);
generator->setInputConnection(importer->getOutputPort());
generator->enableRuntimeMeasurements();
auto network = SegmentationNetwork::New();
network->setInferenceEngine("TensorFlowCUDA");
network->load(Config::getTestDataPath() + "/NeuralNetworkModels/lung_nodule_model.pb");
network->setInferenceEngine("engine");
network->load(Config::getTestDataPath() + "/NeuralNetworkModels/lung_nodule_segmentation.pb");
network->setMinAndMaxIntensity(-1200.0f, 400.0f);
network->setScaleFactor(1.0f / (400 + 1200));
network->setMeanAndStandardDeviation(-1200.0f, 1.0f);
network->setOutputNode(0, "conv3d_18/truediv");
network->setOutputNode(0, "conv3d_14/truediv");
network->setInputConnection(generator->getOutputPort());
network->setResizeBackToOriginalSize(true);
network->setThreshold(0.3);
......@@ -76,7 +79,8 @@ TEST_CASE("Volume -> Patch generator -> Neural network -> Patch stitcher -> visu
auto window = SimpleWindow::New();
window->addRenderer(renderer);
window->addRenderer(renderer2);
//window->setTimeout(1000);
window->setTimeout(5000);
window->start();
}
}
......@@ -25,8 +25,9 @@
using namespace fast;
TEST_CASE("WSI -> Patch generator -> Neural network -> Patch stitcher -> visualize", "[fast][neuralnetwork][wsi][visual]") {
for(auto& engine : InferenceEngineManager::getEngineList()) {
auto importer = WholeSlideImageImporter::New();
importer->setFilename(Config::getTestDataPath() + "/CMU-1.tiff");
importer->setFilename(Config::getTestDataPath() + "/WSI/A05.svs");
auto tissueSegmentation = TissueSegmentation::New();
tissueSegmentation->setInputConnection(importer->getOutputPort());
......@@ -38,17 +39,15 @@ TEST_CASE("WSI -> Patch generator -> Neural network -> Patch stitcher -> visuali
generator->setInputConnection(1, tissueSegmentation->getOutputPort());
auto network = NeuralNetwork::New();
//network->setInferenceEngine("TensorFlowCUDA");
//network->setInferenceEngine("OpenVINO");
network->setInferenceEngine("TensorRT");
auto engine = network->getInferenceEngine()->getName();
network->setInferenceEngine(engine);
if(engine.substr(0, 10) == "TensorFlow") {
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR);
network->setOutputNode(0, "sequential/dense_1/Softmax", NodeType::TENSOR);
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape{-1, 3, 512, 512});
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
network->setOutputNode(0, "sequential/dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
}
network->load(Config::getTestDataPath() + "NeuralNetworkModels/bc_grade_model_3_grades_10x_512_heavy_HSV." + network->getInferenceEngine()->getDefaultFileExtension());
network->load(Config::getTestDataPath() + "NeuralNetworkModels/wsi_classification." +
network->getInferenceEngine()->getDefaultFileExtension());
network->setInputConnection(generator->getOutputPort());
network->setScaleFactor(1.0f / 255.0f);
......@@ -61,19 +60,22 @@ TEST_CASE("WSI -> Patch generator -> Neural network -> Patch stitcher -> visuali
auto heatmapRenderer = HeatmapRenderer::New();
heatmapRenderer->addInputConnection(stitcher->getOutputPort());
//heatmapRenderer->setMinConfidence(0.5);
heatmapRenderer->setMaxOpacity(0.4);
heatmapRenderer->setMaxOpacity(0.3);
auto window = SimpleWindow::New();
window->addRenderer(renderer);
window->addRenderer(heatmapRenderer);
//window->setTimeout(1000);
window->setTimeout(4000);
window->enableMaximized();
window->set2DMode();
window->start();
}
}
TEST_CASE("WSI -> Patch generator -> Image to batch generator -> Neural network -> Patch stitcher -> visualize", "[fast][neuralnetwork][wsi][visual][batch]") {
for(auto& engine : InferenceEngineManager::getEngineList()) {
auto importer = WholeSlideImageImporter::New();
importer->setFilename(Config::getTestDataPath() + "/CMU-1.tiff");
importer->setFilename(Config::getTestDataPath() + "/WSI/A05.svs");
auto tissueSegmentation = TissueSegmentation::New();
tissueSegmentation->setInputConnection(importer->getOutputPort());
......@@ -89,15 +91,15 @@ TEST_CASE("WSI -> Patch generator -> Image to batch generator -> Neural network
batchGenerator->setInputConnection(generator->getOutputPort());
auto network = NeuralNetwork::New();
network->setInferenceEngine("TensorFlowCUDA");
auto engine = network->getInferenceEngine()->getName();
network->setInferenceEngine(engine);
if(engine.substr(0, 10) == "TensorFlow") {
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR);
network->setOutputNode(0, "sequential/dense_1/Softmax", NodeType::TENSOR);
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape{-1, 3, 512, 512});
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
network->setOutputNode(0, "sequential/dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
}
network->load(Config::getTestDataPath() + "NeuralNetworkModels/bc_grade_model_3_grades_10x_512_heavy_HSV." + network->getInferenceEngine()->getDefaultFileExtension());
network->load(Config::getTestDataPath() + "NeuralNetworkModels/wsi_classification." +
network->getInferenceEngine()->getDefaultFileExtension());
network->setInputConnection(batchGenerator->getOutputPort());
network->setScaleFactor(1.0f / 255.0f);
......@@ -110,20 +112,23 @@ TEST_CASE("WSI -> Patch generator -> Image to batch generator -> Neural network
auto heatmapRenderer = HeatmapRenderer::New();
heatmapRenderer->addInputConnection(stitcher->getOutputPort());
//heatmapRenderer->setMinConfidence(0.5);
heatmapRenderer->setChannelHidden(0, true);
heatmapRenderer->setMaxOpacity(0.4);
auto window = SimpleWindow::New();
window->addRenderer(renderer);
window->addRenderer(heatmapRenderer);
//window->setTimeout(1000);
//window->setTimeout(4000);
window->set2DMode();
window->start();
}
}
/*
TEST_CASE("WSI -> Patch generator -> Pixel classifier -> visualize", "[fast][neuralnetwork][wsi][visual]") {
Config::setStreamingMode(STREAMING_MODE_PROCESS_ALL_FRAMES);
auto importer = WholeSlideImageImporter::New();
importer->setFilename(Config::getTestDataPath() + "/CMU-1.tiff");
importer->setFilename(Config::getTestDataPath() + "/WSI/A05.svs");
auto tissueSegmentation = TissueSegmentation::New();
tissueSegmentation->setInputConnection(importer->getOutputPort());
......@@ -158,210 +163,8 @@ TEST_CASE("WSI -> Patch generator -> Pixel classifier -> visualize", "[fast][neu
window->addRenderer(renderer);
//window->addRenderer(heatmapRenderer);
window->addRenderer(segRenderer);
//window->setTimeout(1000);
window->setTimeout(3000);
window->set2DMode();
window->start();
}
// TIMING
/*
TEST_CASE("Timing WSI -> Patch generator -> Neural network -> Patch stitcher -> visualize", "[fast][neuralnetwork][wsi][timing]") {
Reporter::setGlobalReportMethod(Reporter::NONE);
auto importer = WholeSlideImageImporter::New();
importer->setFilename(Config::getTestDataPath() + "/CMU-1.tiff");
auto generator = PatchGenerator::New();
generator->setPatchSize(512, 512);
generator->setPatchLevel(0);
generator->setInputConnection(importer->getOutputPort());
generator->enableRuntimeMeasurements();
auto network = NeuralNetwork::New();
network->setInferenceEngine("TensorFlowCUDA");
auto engine = network->getInferenceEngine()->getName();
if(engine.substr(0, 10) == "TensorFlow") {
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR);
}
network->load(Config::getTestDataPath() + "NeuralNetworkModels/bc_grade_model_3_grades_10x_512_heavy_HSV." + network->getInferenceEngine()->getDefaultFileExtension());
network->setInputConnection(generator->getOutputPort());
network->setScaleFactor(1.0f/255.0f);
network->enableRuntimeMeasurements();
auto stitcher = PatchStitcher::New();
stitcher->setInputConnection(network->getOutputPort());
stitcher->enableRuntimeMeasurements();
auto start = std::chrono::high_resolution_clock::now();
DataObject::pointer data;
do {
data = stitcher->updateAndGetOutputData<DataObject>();
} while(!data->isLastFrame());
std::chrono::duration<float, std::milli> timeUsed = std::chrono::high_resolution_clock::now() - start;
std::cout << "RUNTIME WSI " << engine << std::endl;
std::cout << "=========================================" << std::endl;
std::cout << "Total runtime: " << timeUsed.count() << std::endl;
std::cout << "Patch generator runtime: " << std::endl;
generator->getRuntime("create patch")->print();
std::cout << "NN runtime: " << std::endl;
network->getRuntime("input_processing")->print();
network->getRuntime("inference")->print();
network->getRuntime("output_processing")->print();
std::cout << "Patch stitcher runtime: " << std::endl;
stitcher->getRuntime()->print();
}*/
TEST_CASE("Timing WSI -> TS -> Patch generator -> Neural network -> Patch stitcher -> visualize", "[fast][neuralnetwork][wsi][timing][nobatch]") {
Reporter::setGlobalReportMethod(Reporter::INFO, Reporter::NONE);
for(auto& engine : InferenceEngineManager::getEngineList()) {
std::map<std::string, InferenceDeviceType> deviceTypes = {{"ANY", InferenceDeviceType::ANY}};
if(engine == "OpenVINO") {
// On OpenVINO, try all device types
deviceTypes = std::map<std::string, InferenceDeviceType>{
{"CPU", InferenceDeviceType::CPU},
{"GPU", InferenceDeviceType::GPU},
{"VPU", InferenceDeviceType::VPU},
};
}
for(auto &&deviceType : deviceTypes) {
std::cout << engine << " for device type " << deviceType.first << std::endl;
std::cout << "====================================" << std::endl;
auto importer = WholeSlideImageImporter::New();
importer->setFilename(Config::getTestDataPath() + "/CMU-1.tiff");
auto tissueSegmentation = TissueSegmentation::New();
tissueSegmentation->setInputConnection(importer->getOutputPort());
auto generator = PatchGenerator::New();
generator->setPatchSize(512, 512);
generator->setPatchLevel(0);
generator->setInputConnection(importer->getOutputPort());
generator->setInputConnection(1, tissueSegmentation->getOutputPort());
generator->enableRuntimeMeasurements();
auto network = NeuralNetwork::New();
network->setInferenceEngine(engine);
std::string postfix;
if(engine.substr(0, 10) == "TensorFlow") {
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR);
continue;// TODO Skip for now
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape{-1, 3, 512, 512});
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
} else if(engine == "OpenVINO") {
network->getInferenceEngine()->setDeviceType(deviceType.second);
if(deviceType.first == "VPU") {
postfix = "_fp16";
}
}
network->load(Config::getTestDataPath() + "NeuralNetworkModels/bc_grade_model_3_grades_10x_512_heavy_HSV" + postfix + "." +
network->getInferenceEngine()->getDefaultFileExtension());
network->setInputConnection(generator->getOutputPort());
network->setScaleFactor(1.0f / 255.0f);
network->enableRuntimeMeasurements();
auto stitcher = PatchStitcher::New();
stitcher->setInputConnection(network->getOutputPort());
stitcher->enableRuntimeMeasurements();
auto start = std::chrono::high_resolution_clock::now();
DataObject::pointer data;
do {
data = stitcher->updateAndGetOutputData<DataObject>();
} while(!data->isLastFrame());
std::chrono::duration<float, std::milli> timeUsed = std::chrono::high_resolution_clock::now() - start;
std::cout << "RUNTIME WSI " << engine << std::endl;
std::cout << "=========================================" << std::endl;
std::cout << "Total runtime: " << timeUsed.count() << std::endl;
std::cout << "Patch generator runtime: " << std::endl;
generator->getRuntime("create patch")->print();
std::cout << "NN runtime: " << std::endl;
network->getRuntime("input_processing")->print();
network->getRuntime("inference")->print();
network->getRuntime("output_processing")->print();
std::cout << "Patch stitcher runtime: " << std::endl;
stitcher->getRuntime()->print();
}
}
}
TEST_CASE("Timing of WSI -> TS -> Patch generator -> Image to batch generator -> Neural network -> Patch stitcher -> visualize", "[fast][neuralnetwork][wsi][timing][batch]") {
int batchSize = 16;
Reporter::setGlobalReportMethod(Reporter::INFO, Reporter::NONE);
for(auto& engine : InferenceEngineManager::getEngineList()) {
std::map<std::string, InferenceDeviceType> deviceTypes = {{"ANY", InferenceDeviceType::ANY}};
if(engine == "OpenVINO") {
// On OpenVINO, try all device types
deviceTypes = std::map<std::string, InferenceDeviceType>{
{"CPU", InferenceDeviceType::CPU},
{"GPU", InferenceDeviceType::GPU},
{"VPU", InferenceDeviceType::VPU},
};
}
for(auto &&deviceType : deviceTypes) {
std::cout << engine << " for device type " << deviceType.first << std::endl;
std::cout << "====================================" << std::endl;
auto importer = WholeSlideImageImporter::New();
importer->setFilename(Config::getTestDataPath() + "/CMU-1.tiff");
auto tissueSegmentation = TissueSegmentation::New();
tissueSegmentation->setInputConnection(importer->getOutputPort());
auto generator = PatchGenerator::New();
generator->setPatchSize(512, 512);
generator->setPatchLevel(0);
generator->setInputConnection(importer->getOutputPort());
generator->setInputConnection(1, tissueSegmentation->getOutputPort());
generator->enableRuntimeMeasurements();
auto batchGenerator = ImageToBatchGenerator::New();
batchGenerator->setMaxBatchSize(batchSize);
batchGenerator->setInputConnection(generator->getOutputPort());
auto network = NeuralNetwork::New();
network->setInferenceEngine(engine);
network->getInferenceEngine()->setMaxBatchSize(batchSize);
std::string postfix;
if(engine.substr(0, 10) == "TensorFlow") {
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR);
continue;// TODO Skip for now
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape{-1, 3, 512, 512});
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
} else if(engine == "OpenVINO") {
network->getInferenceEngine()->setDeviceType(deviceType.second);
postfix = "_batch_" + std::to_string(batchSize);
if(deviceType.first == "VPU") {
postfix = "_fp16";
}
}
network->load(Config::getTestDataPath() + "NeuralNetworkModels/bc_grade_model_3_grades_10x_512_heavy_HSV" + postfix + "." +
network->getInferenceEngine()->getDefaultFileExtension());
network->setInputConnection(batchGenerator->getOutputPort());
network->setScaleFactor(1.0f / 255.0f);
network->enableRuntimeMeasurements();
auto stitcher = PatchStitcher::New();
stitcher->setInputConnection(network->getOutputPort());
stitcher->enableRuntimeMeasurements();
auto start = std::chrono::high_resolution_clock::now();
DataObject::pointer data;
do {
data = stitcher->updateAndGetOutputData<DataObject>();
} while(!data->isLastFrame());
std::chrono::duration<float, std::milli> timeUsed = std::chrono::high_resolution_clock::now() - start;
std::cout << "RUNTIME WSI BATCH " << engine << std::endl;
std::cout << "=========================================" << std::endl;
std::cout << "Total runtime: " << timeUsed.count() << std::endl;
std::cout << "Patch generator runtime: " << std::endl;
generator->getRuntime("create patch")->print();
std::cout << "NN runtime: " << std::endl;
network->getRuntime("input_processing")->print();
network->getRuntime("inference")->print();
network->getRuntime("output_processing")->print();
std::cout << "Patch stitcher runtime: " << std::endl;
stitcher->getRuntime()->print();
}
}
}
*/
......@@ -10,6 +10,7 @@
#include <FAST/Importers/WholeSlideImageImporter.hpp>
#include <FAST/Algorithms/TissueSegmentation/TissueSegmentation.hpp>
#include <FAST/Tools/CommandLineParser.hpp>
#include <FAST/Algorithms/ImagePatch/ImageToBatchGenerator.hpp>
using namespace fast;
......@@ -20,6 +21,7 @@ int main(int argc, char** argv) {
parser.addOption("disable-case-1");
parser.addOption("disable-case-2");
parser.addOption("disable-case-3");
parser.addOption("disable-case-3-batch");
parser.addOption("disable-warmup");
parser.parse(argc, argv);
const int iterations = 10;
......@@ -27,6 +29,7 @@ int main(int argc, char** argv) {
const bool case1 = !parser.getOption("disable-case-1");
const bool case2 = !parser.getOption("disable-case-2");
const bool case3 = !parser.getOption("disable-case-3");
const bool case3_batch = !parser.getOption("disable-case-3-batch");
if(case1) {
// CASE 1 - ULTRASOUND
......@@ -145,10 +148,10 @@ int main(int argc, char** argv) {
for(int iteration = 0; iteration <= iterations; ++iteration) {
auto importer = ImageFileImporter::New();
importer->setFilename(Config::getTestDataPath() + "/CT/LIDC-IDRI-0072/01-01-2000-CT CHEST W CONT-45499/4-Recon 3-88650/000001.dcm");
importer->setFilename(Config::getTestDataPath() + "/CT/LIDC-IDRI-0072/000001.dcm");
auto generator = PatchGenerator::New();
generator->setPatchSize(512, 512, 64);
generator->setPatchSize(512, 512, 32);
generator->setInputConnection(importer->getOutputPort());
generator->enableRuntimeMeasurements();
......@@ -156,11 +159,11 @@ int main(int argc, char** argv) {
network->setInferenceEngine(engine);
network->getInferenceEngine()->setDeviceType(deviceType.second);
network->setInferenceEngine(engine);
network->load(Config::getTestDataPath() + "/NeuralNetworkModels/lung_nodule_model.pb");
network->load(Config::getTestDataPath() + "/NeuralNetworkModels/lung_nodule_segmentation.pb");
network->setMinAndMaxIntensity(-1200.0f, 400.0f);
network->setScaleFactor(1.0f/(400+1200));
network->setMeanAndStandardDeviation(-1200.0f, 1.0f);
network->setOutputNode(0, "conv3d_18/truediv");
network->setOutputNode(0, "conv3d_14/truediv");
network->setInputConnection(generator->getOutputPort());
network->setResizeBackToOriginalSize(true);
network->setThreshold(0.3);
......@@ -233,7 +236,7 @@ int main(int argc, char** argv) {
for(int iteration = 0; iteration <= iterations; ++iteration) {
auto importer = WholeSlideImageImporter::New();
importer->setFilename(Config::getTestDataPath() + "/CMU-1.tiff");
importer->setFilename(Config::getTestDataPath() + "/WSI/A05.svs");
auto tissueSegmentation = TissueSegmentation::New();
tissueSegmentation->setInputConnection(importer->getOutputPort());
......@@ -249,17 +252,123 @@ int main(int argc, char** argv) {
network->setInferenceEngine(engine);
std::string postfix;
if(engine.substr(0, 10) == "TensorFlow") {
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR);
network->setOutputNode(0, "sequential/dense_1/Softmax", NodeType::TENSOR);
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape{-1, 3, 512, 512});
network->setOutputNode(0, "dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
network->setOutputNode(0, "sequential/dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
} else if(engine == "OpenVINO") {
network->getInferenceEngine()->setDeviceType(deviceType.second);
if(deviceType.first == "VPU") {
postfix = "_fp16";
}
}
network->load(Config::getTestDataPath() + "NeuralNetworkModels/bc_grade_model_3_grades_10x_512_heavy_HSV" + postfix + "." +
network->load(Config::getTestDataPath() + "NeuralNetworkModels/wsi_classification" + postfix + "." +
network->getInferenceEngine()->getDefaultFileExtension());
network->setInputConnection(generator->getOutputPort());
network->setScaleFactor(1.0f / 255.0f);
network->enableRuntimeMeasurements();
auto stitcher = PatchStitcher::New();
stitcher->setInputConnection(network->getOutputPort());
stitcher->enableRuntimeMeasurements();
auto start = std::chrono::high_resolution_clock::now();
DataObject::pointer data;
do {
data = stitcher->updateAndGetOutputData<DataObject>();
} while(!data->isLastFrame());
std::chrono::duration<float, std::milli> timeUsed = std::chrono::high_resolution_clock::now() - start;
std::cout << "Total runtime: " << timeUsed.count() << std::endl;
std::cout << "Patch generator runtime: " << std::endl;
generator->getRuntime("create patch")->print();
std::cout << "NN runtime: " << std::endl;
network->getRuntime()->print();
std::cout << "Patch stitcher runtime: " << std::endl;
stitcher->getRuntime()->print();
if(iteration == 0 && warmupIteration)
continue;
file <<
engine + ";" +
deviceType.first + ";" +
std::to_string(iteration) + ";" +
std::to_string(generator->getRuntime("create patch")->getAverage()) + ";" +
std::to_string(generator->getRuntime("create patch")->getStdDeviation()) + ";" +
std::to_string(network->getRuntime("input_processing")->getAverage()) + ";" +
std::to_string(network->getRuntime("input_processing")->getStdDeviation()) + ";" +
std::to_string(network->getRuntime("inference")->getAverage()) + ";" +
std::to_string(network->getRuntime("inference")->getStdDeviation()) + ";" +
std::to_string(network->getRuntime("output_processing")->getAverage()) + ";" +
std::to_string(network->getRuntime("output_processing")->getStdDeviation()) + ";" +
std::to_string(stitcher->getRuntime("stitch patch")->getAverage()) + ";" +
std::to_string(stitcher->getRuntime("stitch patch")->getStdDeviation()) + ";" +
std::to_string(timeUsed.count())
<< std::endl;
}
}
}
}
if(case3_batch) {
// CASE 3 - WSI CLASSIFICATION with batches
const int batchSize = 16;
const std::string resultFilename = "neural-network-runtimes-case-3-batch.csv";
std::ofstream file(resultFilename.c_str());
// Write header
file << "Engine;Device Type;Iteration;Patch generator AVG;Patch generator STD;NN input AVG;NN input STD;NN inference AVG;NN inference STD;NN output AVG;NN output STD;Patch stitcher AVG;Patch stitcher STD;Total\n";
for(std::string engine : {"TensorRT", "TensorFlowCUDA", "TensorFlowROCm", "OpenVINO"}) {
if(!InferenceEngineManager::isEngineAvailable(engine))
continue;
std::map<std::string, InferenceDeviceType> deviceTypes = {{"ANY", InferenceDeviceType::ANY}};
if(engine == "OpenVINO") {
// On OpenVINO, try all device types
deviceTypes = std::map<std::string, InferenceDeviceType>{
//{"CPU", InferenceDeviceType::CPU},
{"GPU", InferenceDeviceType::GPU},
{"VPU", InferenceDeviceType::VPU},
};
}
for(auto &&deviceType : deviceTypes) {
std::cout << engine << " for device type " << deviceType.first << std::endl;
std::cout << "====================================" << std::endl;
for(int iteration = 0; iteration <= iterations; ++iteration) {
auto importer = WholeSlideImageImporter::New();
importer->setFilename(Config::getTestDataPath() + "/WSI/A05.svs");
auto tissueSegmentation = TissueSegmentation::New();
tissueSegmentation->setInputConnection(importer->getOutputPort());
auto generator = PatchGenerator::New();
generator->setPatchSize(512, 512);
generator->setPatchLevel(0);
generator->setInputConnection(importer->getOutputPort());
generator->setInputConnection(1, tissueSegmentation->getOutputPort());
generator->enableRuntimeMeasurements();
auto batchGenerator = ImageToBatchGenerator::New();
batchGenerator->setMaxBatchSize(16);
auto network = NeuralNetwork::New();
network->setInferenceEngine(engine);
network->getInferenceEngine()->setMaxBatchSize(batchSize);
std::string postfix;
if(engine.substr(0, 10) == "TensorFlow") {
network->setOutputNode(0, "sequential/dense_1/Softmax", NodeType::TENSOR);
} else if(engine == "TensorRT") {
network->setInputNode(0, "input_1", NodeType::IMAGE, TensorShape{-1, 3, 512, 512});
network->setOutputNode(0, "sequential/dense_1/Softmax", NodeType::TENSOR, TensorShape{-1, 3});
} else if(engine == "OpenVINO") {
network->getInferenceEngine()->setDeviceType(deviceType.second);
postfix = "batch_" + std::to_string(batchSize);
if(deviceType.first == "VPU") {
postfix = "_fp16";
}
}
network->load(Config::getTestDataPath() + "NeuralNetworkModels/wsi_classification" + postfix + "." +
network->getInferenceEngine()->getDefaultFileExtension());
network->setInputConnection(generator->getOutputPort());
network->setScaleFactor(1.0f / 255.0f);
......
......@@ -46,7 +46,6 @@ void ImagePyramid::free(ExecutionDevice::pointer device) {
void ImagePyramid::freeAll() {
m_levels.clear();
m_patchCache.clear();
openslide_close(m_fileHandle);
}
......@@ -55,9 +54,6 @@ ImagePyramid::~ImagePyramid() {
}
ImagePyramid::Patch ImagePyramid::getPatch(std::string tile) {
if(m_patchCache.count(tile) > 0)
return m_patchCache[tile];
auto parts = split(tile, "_");
if(parts.size() != 3)
throw Exception("incorrect tile format");
......@@ -70,10 +66,6 @@ ImagePyramid::Patch ImagePyramid::getPatch(std::string tile) {
}
ImagePyramid::Patch ImagePyramid::getPatch(int level, int tile_x, int tile_y) {
std::string tileStr = std::to_string(level) + "_" + std::to_string(tile_x) + "_" + std::to_string(tile_y);
if(m_patchCache.count(tileStr) > 0)
return m_patchCache[tileStr];
// Create patch
int levelWidth = getLevelWidth(level);
int levelHeight = getLevelHeight(level);
......@@ -95,9 +87,6 @@ ImagePyramid::Patch ImagePyramid::getPatch(int level, int tile_x, int tile_y) {
tile.data = std::shared_ptr<uchar[]>(new uchar[bytes]); // TODO use make_shared instead (C++20)
float scale = (float)getFullWidth()/levelWidth;
openslide_read_region(m_fileHandle, (uint32_t *) tile.data.get(), tile.offsetX*scale, tile.offsetY*scale, level, tile.width, tile.height);
m_patchCacheMemoryUsage += bytes;
std::cout << m_patchCacheMemoryUsage/(1024*1024) << " MB usage" << std::endl;
m_patchCache[tileStr] = tile;
return tile;
}
......
......@@ -49,10 +49,6 @@ class FAST_EXPORT ImagePyramid : public SpatialDataObject {
private:
std::vector<Level> m_levels;
std::unordered_map<std::string, Patch> m_patchCache;
uint64_t m_patchCacheMemoryUsage = 0;
openslide_t* m_fileHandle;
};
......
......@@ -4,16 +4,16 @@
* If you edit this example, please also update the wiki and source code file in the repository.
*/
#include <FAST/Tools/CommandLineParser.hpp>
#include "FAST/Importers/WholeSlideImageImporter.hpp"
#include "FAST/Visualization/ImagePyramidRenderer/ImagePyramidRenderer.hpp"
#include "FAST/Visualization/SimpleWindow.hpp"
#include <FAST/Importers/WholeSlideImageImporter.hpp>
#include <FAST/Visualization/ImagePyramidRenderer/ImagePyramidRenderer.hpp>
#include <FAST/Visualization/SimpleWindow.hpp>
using namespace fast;
int main(int argc, char** argv) {
Reporter::setGlobalReportMethod(Reporter::COUT);
CommandLineParser parser("Import image from file example");
parser.addPositionVariable(1, "filename", Config::getTestDataPath() + "/CMU-1.tiff");
parser.addPositionVariable(1, "filename", Config::getTestDataPath() + "/WSI/A05.svs");
parser.parse(argc, argv);
// Import image from file using the ImageFileImporter
......