Skip to content

Commit 7802def

Browse files
Speed up builds and adapt to OpenCV-free result types.
Use Ninja and ccache in CI, compile app sources once via a static library, skip fetched subproject tests, pin vision-core to the new result-type commit, and convert rendering through opencv_interop. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 3db12ff commit 7802def

22 files changed

Lines changed: 836 additions & 746 deletions

.github/actions/install-linux-deps/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ runs:
99
run: |
1010
sudo apt-get update
1111
sudo apt-get install -y --no-install-recommends \
12-
cmake build-essential git wget \
12+
cmake build-essential git wget ninja-build ccache \
1313
libopencv-dev \
1414
libgoogle-glog-dev \
1515
libcurl4-openssl-dev \

.github/workflows/ci.yml

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ jobs:
2424
- name: Install shared dependencies
2525
uses: ./.github/actions/install-linux-deps
2626

27+
- name: Set up ccache
28+
uses: hendrikmuhs/ccache-action@v1
29+
with:
30+
key: ${{ github.job }}-${{ runner.os }}
31+
2732
- name: Cache CMake build
2833
uses: actions/cache@v4
2934
with:
@@ -33,10 +38,12 @@ jobs:
3338

3439
- name: Configure
3540
run: |
36-
cmake -B build \
41+
cmake -B build -G Ninja \
3742
-DDEFAULT_BACKEND=OPENCV_DNN \
43+
-DVISION_CORE_VERSION=develop \
3844
-DENABLE_APP_TESTS=ON \
39-
-DCMAKE_BUILD_TYPE=Release
45+
-DCMAKE_BUILD_TYPE=Release \
46+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
4047
4148
- name: Check model-type docs are in sync
4249
run: |
@@ -78,6 +85,11 @@ jobs:
7885
tar -xzf onnxruntime-linux-x64-gpu-${ORT_VERSION}.tgz -C ~
7986
rm onnxruntime-linux-x64-gpu-${ORT_VERSION}.tgz
8087
88+
- name: Set up ccache
89+
uses: hendrikmuhs/ccache-action@v1
90+
with:
91+
key: ${{ github.job }}-${{ runner.os }}
92+
8193
- name: Cache CMake build
8294
uses: actions/cache@v4
8395
with:
@@ -87,12 +99,13 @@ jobs:
8799

88100
- name: Configure
89101
run: |
90-
cmake -B build \
102+
cmake -B build -G Ninja \
91103
-DDEFAULT_BACKEND=ONNX_RUNTIME \
92104
-DORT_VERSION=${ORT_VERSION} \
93105
-DONNX_RUNTIME_DIR=$HOME/onnxruntime-linux-x64-gpu-${ORT_VERSION} \
94106
-DENABLE_APP_TESTS=OFF \
95-
-DCMAKE_BUILD_TYPE=Release
107+
-DCMAKE_BUILD_TYPE=Release \
108+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
96109
97110
- name: Build
98111
run: cmake --build build --config Release --parallel $(nproc)
@@ -125,6 +138,11 @@ jobs:
125138
unzip -q libtorch.zip -d ~
126139
rm libtorch.zip
127140
141+
- name: Set up ccache
142+
uses: hendrikmuhs/ccache-action@v1
143+
with:
144+
key: ${{ github.job }}-${{ runner.os }}
145+
128146
- name: Cache CMake build
129147
uses: actions/cache@v4
130148
with:
@@ -134,12 +152,13 @@ jobs:
134152

135153
- name: Configure
136154
run: |
137-
cmake -B build \
155+
cmake -B build -G Ninja \
138156
-DDEFAULT_BACKEND=LIBTORCH \
139157
-DCMAKE_PREFIX_PATH=$HOME/libtorch \
140158
-DLIBTORCH_DIR=$HOME/libtorch \
141159
-DENABLE_APP_TESTS=OFF \
142-
-DCMAKE_BUILD_TYPE=Release
160+
-DCMAKE_BUILD_TYPE=Release \
161+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
143162
144163
- name: Build
145164
run: cmake --build build --config Release --parallel $(nproc)

CMakeLists.txt

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,35 @@ endif()
1313

1414
project(vision-inference VERSION ${PROJECT_SEMVER})
1515

16+
include(cmake/CompileSpeed.cmake)
17+
1618
# Set C++ standard
1719
set(CMAKE_CXX_STANDARD 20)
1820
set(CMAKE_CXX_STANDARD_REQUIRED ON)
21+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
22+
23+
set(PROJECT_WARNING_FLAGS
24+
-Wall
25+
-Wextra
26+
-Wpedantic
27+
-Wshadow
28+
-Wnon-virtual-dtor
29+
-Wold-style-cast
30+
-Wcast-align
31+
-Wunused
32+
-Woverloaded-virtual
33+
-Wconversion
34+
-Wsign-conversion
35+
-Wnull-dereference
36+
-Wdouble-promotion
37+
-Wformat=2
38+
-Wimplicit-fallthrough
39+
)
40+
41+
option(WERROR "Treat compiler warnings as errors" OFF)
42+
if(WERROR)
43+
list(APPEND PROJECT_WARNING_FLAGS -Werror)
44+
endif()
1945

2046
option(ENABLE_APP_TESTS "Enable unit testing for app module" OFF)
2147
if(ENABLE_APP_TESTS)
@@ -67,8 +93,16 @@ FetchContent_Declare(
6793
GIT_TAG ${VIDEOCAPTURE_VERSION} # Use specific version instead of master
6894
)
6995

70-
# Disable neuriplo's tests so it doesn't require GTest
96+
# Disable subproject tests and sample apps when fetched as dependencies.
7197
set(BUILD_INFERENCE_ENGINE_TESTS OFF CACHE BOOL "" FORCE)
98+
set(BUILD_TESTS OFF CACHE BOOL "" FORCE)
99+
100+
# Prefer a sibling checkout during local cross-repo development.
101+
set(_VISION_CORE_SIBLING "${CMAKE_CURRENT_SOURCE_DIR}/../vision-core")
102+
if(EXISTS "${_VISION_CORE_SIBLING}/CMakeLists.txt")
103+
set(FETCHCONTENT_SOURCE_DIR_VISION-CORE "${_VISION_CORE_SIBLING}" CACHE PATH "" FORCE)
104+
endif()
105+
72106
FetchContent_MakeAvailable(neuriplo VideoCapture vision-core)
73107
message(STATUS "vision-core_SOURCE_DIR: ${vision-core_SOURCE_DIR}")
74108
message(STATUS "neuriplo_SOURCE_DIR: ${neuriplo_SOURCE_DIR}")

app/CMakeLists.txt

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,4 @@
1-
# Fetch the VideoCapture project from GitHub with specific version
2-
include(FetchContent)
3-
FetchContent_Declare(
4-
VideoCapture
5-
GIT_REPOSITORY https://github.com/olibartfast/VideoCapture.git
6-
GIT_TAG ${VIDEOCAPTURE_VERSION}
7-
)
8-
# Pass video backend options to VideoCapture library
9-
set(USE_GSTREAMER ${USE_GSTREAMER})
10-
set(USE_FFMPEG ${USE_FFMPEG})
11-
FetchContent_MakeAvailable(VideoCapture)
12-
message(STATUS "VideoCapture_SOURCE_DIR: ${VideoCapture_SOURCE_DIR}")
13-
message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
14-
15-
# Define sources using CMAKE_CURRENT_SOURCE_DIR instead of CMAKE_SOURCE_DIR
16-
set(SOURCES
17-
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
1+
set(APP_LIB_SOURCES
182
${CMAKE_CURRENT_SOURCE_DIR}/src/VisionApp.cpp
193
${CMAKE_CURRENT_SOURCE_DIR}/src/InferencePipeline.cpp
204
${CMAKE_CURRENT_SOURCE_DIR}/src/CLICommands.cpp
@@ -23,13 +7,10 @@ set(SOURCES
237
${CMAKE_CURRENT_SOURCE_DIR}/src/utils.cpp
248
${CMAKE_CURRENT_SOURCE_DIR}/src/CommandLineParser.cpp
259
)
26-
add_executable(${PROJECT_NAME} ${SOURCES})
27-
include(${CMAKE_SOURCE_DIR}/cmake/Sanitizers.cmake)
28-
enable_target_sanitizers(${PROJECT_NAME})
2910

11+
add_library(vision-inference-app STATIC ${APP_LIB_SOURCES})
3012

31-
# Set include directories
32-
target_include_directories(${PROJECT_NAME} PRIVATE
13+
target_include_directories(vision-inference-app PUBLIC
3314
${CMAKE_CURRENT_SOURCE_DIR}/inc
3415
${CMAKE_CURRENT_SOURCE_DIR}/src
3516
${VideoCapture_SOURCE_DIR}/include
@@ -40,15 +21,37 @@ target_include_directories(${PROJECT_NAME} PRIVATE
4021
${GLOG_INCLUDE_DIRS}
4122
)
4223

43-
# Link libraries
44-
target_link_libraries(${PROJECT_NAME} PRIVATE
24+
target_link_libraries(vision-inference-app PUBLIC
4525
glog::glog
4626
${OpenCV_LIBS}
4727
neuriplo
4828
VideoCapture
4929
vision-core
5030
)
5131

32+
if(MSVC)
33+
target_compile_options(vision-inference-app PRIVATE /W4)
34+
else()
35+
target_compile_options(vision-inference-app PRIVATE ${PROJECT_WARNING_FLAGS})
36+
endif()
37+
38+
add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
39+
include(${CMAKE_SOURCE_DIR}/cmake/Sanitizers.cmake)
40+
enable_target_sanitizers(${PROJECT_NAME})
41+
42+
target_include_directories(${PROJECT_NAME} PRIVATE
43+
${CMAKE_CURRENT_SOURCE_DIR}/inc
44+
${CMAKE_CURRENT_SOURCE_DIR}/src
45+
)
46+
47+
target_link_libraries(${PROJECT_NAME} PRIVATE vision-inference-app)
48+
49+
if(MSVC)
50+
target_compile_options(${PROJECT_NAME} PRIVATE /W4)
51+
else()
52+
target_compile_options(${PROJECT_NAME} PRIVATE ${PROJECT_WARNING_FLAGS})
53+
endif()
54+
5255
include(${CMAKE_SOURCE_DIR}/cmake/LinkBackend.cmake)
5356

5457
if(ENABLE_APP_TESTS)

app/inc/CommandLineParser.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
class CommandLineParser {
55
public:
6-
static AppConfig parseCommandLineArguments(int argc, char *argv[]);
6+
static AppConfig parseCommandLineArguments(int argc, char *argv[]);
77

88
private:
9-
static const std::string params;
10-
static void printHelpMessage(const cv::CommandLineParser& parser);
11-
static void validateArguments(const cv::CommandLineParser& parser);
9+
static const std::string params;
10+
static void printHelpMessage(const cv::CommandLineParser &parser);
11+
static void validateArguments(const cv::CommandLineParser &parser);
1212
};

app/inc/VisionApp.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
class VisionApp {
88
public:
9-
explicit VisionApp(const AppConfig &config);
9+
explicit VisionApp(const AppConfig &app_config);
1010
int run();
1111

1212
private:

app/inc/utils.hpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
#include <opencv2/opencv.hpp>
33
#include <string>
44

5-
bool isDirectory(const std::string& path);
6-
bool isFile(const std::string& path);
7-
void draw_label(cv::Mat& input_image, const std::string& label, float confidence, int left, int top);
8-
std::vector<std::string> readLabelNames(const std::string& fileName);
9-
std::string getFileExtension(const std::string& filename);
5+
bool isDirectory(const std::string &path);
6+
bool isFile(const std::string &path);
7+
void draw_label(cv::Mat &input_image, const std::string &label,
8+
float confidence, int left, int top);
9+
std::vector<std::string> readLabelNames(const std::string &fileName);
10+
std::string getFileExtension(const std::string &filename);
1011
std::string getGPUModel();
1112
std::vector<std::string> getGPUModels();
1213
std::string getCPUInfo();
1314
bool hasNvidiaGPU();
14-
std::vector<std::string> split(const std::string& s, char delimiter);
15-
std::vector<std::vector<int64_t>> parseInputSizes(const std::string& input);
16-
std::string normalizeModelType(const std::string& model_type);
15+
std::vector<std::string> split(const std::string &s, char delimiter);
16+
std::vector<std::vector<int64_t>> parseInputSizes(const std::string &input);
17+
std::string normalizeModelType(const std::string &model_type);

app/src/CLICommands.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "CLICommands.hpp"
22

33
#include "VideoCaptureFactory.hpp"
4+
#include "vision-core/core/opencv_interop.hpp"
45

56
#include <chrono>
67
#include <filesystem>
@@ -115,15 +116,15 @@ void processVideo(InferencePipeline &pipeline, const std::string &source) {
115116
auto duration =
116117
std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
117118
.count();
118-
double fps = 1000.0 / duration;
119+
double fps = 1000.0 / static_cast<double>(duration);
119120
std::string fpsText = "FPS: " + std::to_string(fps);
120121
cv::putText(frame, fpsText, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1,
121122
cv::Scalar(0, 255, 0), 2);
122123

123124
pipeline.renderResults(results, frame);
124125

125126
cv::imshow("opencv feed", frame);
126-
char key = cv::waitKey(1);
127+
const int key = cv::waitKey(1);
127128
if (key == 27 || key == 'q') {
128129
LOG(INFO) << "Exit requested";
129130
break;
@@ -148,7 +149,7 @@ void processVideoClassification(InferencePipeline &pipeline,
148149

149150
cv::Mat frame;
150151
std::vector<cv::Mat> frameBuffer;
151-
frameBuffer.reserve(requiredFrames);
152+
frameBuffer.reserve(static_cast<size_t>(requiredFrames));
152153

153154
while (videoInterface->readFrame(frame)) {
154155
frameBuffer.push_back(frame.clone());
@@ -165,7 +166,7 @@ void processVideoClassification(InferencePipeline &pipeline,
165166
auto duration =
166167
std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
167168
.count();
168-
double fps = 1000.0 / duration;
169+
double fps = 1000.0 / static_cast<double>(duration);
169170
std::string fpsText = "FPS: " + std::to_string(fps);
170171

171172
cv::Mat displayFrame = frameBuffer.back().clone();
@@ -178,7 +179,7 @@ void processVideoClassification(InferencePipeline &pipeline,
178179
frameBuffer.erase(frameBuffer.begin());
179180
}
180181

181-
char key = cv::waitKey(1);
182+
const int key = cv::waitKey(1);
182183
if (key == 27 || key == 'q') {
183184
LOG(INFO) << "Exit requested";
184185
break;
@@ -229,7 +230,7 @@ void processOpticalFlow(InferencePipeline &pipeline) {
229230
if (std::holds_alternative<vision_core::OpticalFlow>(prediction)) {
230231
vision_core::OpticalFlow flow =
231232
std::get<vision_core::OpticalFlow>(prediction);
232-
flow.flow.copyTo(image);
233+
vision_core::toCvMat(flow.flow).copyTo(image);
233234
}
234235
}
235236

@@ -358,9 +359,10 @@ int BenchmarkCommand::execute(InferencePipeline &pipeline) {
358359
std::chrono::duration_cast<std::chrono::milliseconds>(end - start)
359360
.count();
360361
LOG(INFO) << "Iteration " << i << ": " << duration << "ms";
361-
total_time += duration;
362+
total_time += static_cast<double>(duration);
362363
}
363-
double average_time = total_time / pipeline.config.benchmark_iterations;
364+
double average_time =
365+
total_time / static_cast<double>(pipeline.config.benchmark_iterations);
364366
LOG(INFO) << "Average inference time over "
365367
<< pipeline.config.benchmark_iterations
366368
<< " iterations: " << average_time << "ms";

app/src/InferencePipeline.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,9 @@ void InferencePipelineBuilder::setupBackend(InferencePipeline &pipeline) const {
178178
LOG(INFO) << "CPU info " << getCPUInfo();
179179
LOG(INFO) << "GPU info: " << getGPUModel();
180180
const auto use_gpu = config_.use_gpu && hasNvidiaGPU();
181-
pipeline.engine =
182-
setup_inference_engine(buildEngineWeights(config_), use_gpu,
183-
config_.batch_size, config_.input_sizes);
181+
pipeline.engine = setup_inference_engine(
182+
buildEngineWeights(config_), use_gpu,
183+
static_cast<size_t>(config_.batch_size), config_.input_sizes);
184184
if (!pipeline.engine) {
185185
throw std::runtime_error("Can't setup an inference engine for " +
186186
config_.weights);

0 commit comments

Comments
 (0)