Ubuntu24环境下OpenCV与Libtorch混合使用链接错误求助
问题:Ubuntu 24 + CLion中OpenCV与Libtorch混合编译出现未定义引用错误
错误现象
同时使用OpenCV和Libtorch的代码编译时,出现以下链接错误:
main.cpp:34:(.text+0xa28): undefined reference to `cv::putText(cv::_InputOutputArray const&, std::string const&, cv::Point_<int>, int, double, cv::Scalar_<double>, int, int, bool)' main.cpp:45:(.text+0xbb1): undefined reference to `cv::VideoCapture::VideoCapture(std::string const&, int)' main.cpp:64:(.text+0xe04): undefined reference to `cv::imshow(std::string const&, cv::_InputArray const&)'
单独使用OpenCV或单独使用Libtorch的程序均可正常编译运行,仅在混合项目中出现上述问题。
可正常运行的单独项目CMake配置
纯OpenCV项目CMakeLists.txt
cmake_minimum_required(VERSION 3.28) project(libtorch) find_package (OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) set(CMAKE_CXX_STANDARD 17) add_executable(libtorch main.cpp) target_link_libraries(libtorch ${OpenCV_LIBS})
纯Libtorch项目CMakeLists.txt
cmake_minimum_required(VERSION 3.28) project(libtorch) find_package(Torch REQUIRED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") add_executable(libtorch main.cpp) target_link_libraries(libtorch "${TORCH_LIBRARIES}") set_property(TARGET libtorch PROPERTY CXX_STANDARD 17)
出错的混合项目CMakeLists.txt
cmake_minimum_required(VERSION 3.28) project(libtorch) find_package (OpenCV REQUIRED) find_package(Torch REQUIRED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") add_executable(libtorch main.cpp) target_link_libraries(libtorch ${OpenCV_LIBS}) target_link_libraries(libtorch "${TORCH_LIBRARIES}") set_property(TARGET libtorch PROPERTY CXX_STANDARD 17)
CLion中使用的CMake参数:-DCMAKE_PREFIX_PATH=/usr/include/libtorch/share/cmake/Torch/
出错的混合代码
#include <torch/script.h> #include <opencv2/opencv.hpp> #include <iostream> const int INPUT_WIDTH = 320; const int INPUT_HEIGHT = 320; const float SCORE_THRESHOLD = 0.5; const float NMS_THRESHOLD = 0.5; const int PERSON_CLASS_ID = 1; const std::string VIDEO_PATH = "path"; const std::string MODEL_PATH = "ssdlite320_mobilenet_v3_large.pt"; torch::Tensor preprocess_image(cv::Mat& image) { cv::Mat resized; resize(image, resized, cv::Size(INPUT_WIDTH, INPUT_HEIGHT)); cvtColor(resized, resized, cv::COLOR_BGR2RGB); torch::Tensor tensor_image = torch::from_blob(resized.data, {1, INPUT_HEIGHT, INPUT_WIDTH, 3}, torch::kByte); tensor_image = tensor_image.permute({0, 3, 1, 2}); tensor_image = tensor_image.toType(torch::kFloat); tensor_image = tensor_image.div(255); return tensor_image; } void draw_predictions(cv::Mat& image, const torch::Tensor& predictions) { auto pred_accessor = predictions.accessor<float, 2>(); for (int i = 0; i < predictions.size(0); ++i) { if (pred_accessor[i][5] == PERSON_CLASS_ID && pred_accessor[i][4] > SCORE_THRESHOLD) { int x1 = static_cast<int>(pred_accessor[i][0] * image.cols); int y1 = static_cast<int>(pred_accessor[i][1] * image.rows); int x2 = static_cast<int>(pred_accessor[i][2] * image.cols); int y2 = static_cast<int>(pred_accessor[i][3] * image.rows); rectangle(image, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(0, 255, 0), 2); putText(image, "Person", cv::Point(x1, y1 - 10), cv::FONT_HERSHEY_SIMPLEX, 0.9, cv::Scalar(0, 255, 0), 2); } } } int main() { torch::jit::script::Module model = torch::jit::load(MODEL_PATH); model.eval(); cv::VideoCapture cap(VIDEO_PATH); if (!cap.isOpened()) { std::cerr << "Error opening video file" << std::endl; return -1; } cv::Mat frame; while (cap.read(frame)) { torch::Tensor input_tensor = preprocess_image(frame); std::vector<torch::jit::IValue> inputs; inputs.push_back(input_tensor); torch::Tensor output = model.forward(inputs).toTensor(); torch::Tensor predictions = output.squeeze().detach(); draw_predictions(frame, predictions); imshow("Person Detection", frame); if (cv::waitKey(1) == 27) break; } cap.release(); cv::destroyAllWindows(); return 0; }
可正常运行的纯OpenCV代码
#include <opencv2/opencv.hpp> #include <iostream> const std::string videoPath = "path"; void preprocessFrame(cv::Mat& frame) { cv::resize(frame, frame, cv::Size(240, 160)); } void applyBackgroundSubtraction(cv::Mat& frame, cv::Ptr<cv::BackgroundSubtractor>& bgSubtractor, cv::Mat& fgMask) { bgSubtractor->apply(frame, fgMask); } void applyNoiseReduction(cv::Mat& fgMask) { cv::GaussianBlur(fgMask, fgMask, cv::Size(15, 15), 0); cv::erode(fgMask, fgMask, cv::Mat(), cv::Point(-1, -1), 2); cv::dilate(fgMask, fgMask, cv::Mat(), cv::Point(-1, -1), 2); } int main() { cv::VideoCapture cap(videoPath); if (!cap.isOpened()) { std::cerr << "Error: Could not open the video file!" << std::endl; return -1; } cv::Ptr<cv::BackgroundSubtractor> bgSubtractor = cv::createBackgroundSubtractorKNN(100, 2000, false); cv::Mat frame, fgMask; while (cap.read(frame)) { if (frame.empty()) break; preprocessFrame(frame); applyBackgroundSubtraction(frame, bgSubtractor, fgMask); applyNoiseReduction(fgMask); cv::imshow("Foreground Mask (Noise Reduced)", fgMask); if (cv::waitKey(30) == 27) break; } cap.release(); cv::destroyAllWindows(); return 0; }
解决方案
问题根源在于链接顺序及ABI兼容性,按以下步骤修复:
- 调整链接顺序:将Libtorch的链接放在OpenCV之前,修改后的CMakeLists.txt如下:
cmake_minimum_required(VERSION 3.28) project(libtorch) find_package(OpenCV REQUIRED) find_package(Torch REQUIRED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}") add_executable(libtorch main.cpp) # 先链接Libtorch,再链接OpenCV target_link_libraries(libtorch "${TORCH_LIBRARIES}" ${OpenCV_LIBS}) set_property(TARGET libtorch PROPERTY CXX_STANDARD 17)
确保ABI兼容:Libtorch默认使用C17编译,需保证OpenCV也使用相同C标准。若OpenCV为源码编译,需指定
CMAKE_CXX_STANDARD=17;Ubuntu 24 apt安装的OpenCV默认符合要求。清理CMake缓存:在CLion中执行
File -> Reload CMake Project,或手动删除build目录后重新编译,避免旧缓存干扰。
内容的提问来源于stack exchange,提问作者Oleg Chaika
相关产品推荐
相关产品推荐

