自己环境中存在OpenCV的前提下,同样使用Cmake的find_package命令可以找到,为此,我们修改CmakeLists文件为:
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(simnet)
find_package(Torch REQUIRED) # 查找libtorch
find_package(OpenCV REQUIRED) # 查找OpenCV
if(NOT Torch_FOUND)
message(FATAL_ERROR "Pytorch Not Found!")
endif(NOT Torch_FOUND)
message(STATUS "Pytorch status:")
message(STATUS " libraries: ${TORCH_LIBRARIES}")
message(STATUS "OpenCV library status:")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
add_executable(simnet test.cpp)
target_link_libraries(simnet ${TORCH_LIBRARIES} ${OpenCV_LIBS})
set_property(TARGET simnet PROPERTY CXX_STANDARD 11)
在Cmake配置后如果正确找到后会显示以下的信息:
-- Caffe2: CUDA detected: 9.2
-- Caffe2: CUDA nvcc is: /usr/local/cuda/bin/nvcc
-- Caffe2: CUDA toolkit directory: /usr/local/cuda
-- Caffe2: Header version is: 9.2
-- Found cuDNN: v7.4.1 (include: /usr/local/cuda/include, library: /usr/local/cuda/lib64/libcudnn.so)
-- Autodetected CUDA architecture(s): 6.1;6.1
-- Added CUDA NVCC flags for: -gencode;arch=compute_61,code=sm_61
-- Pytorch status:
-- libraries: torch;caffe2_library;caffe2_gpu_library;/usr/lib/x86_64-linux-gnu/libcuda.so;/usr/local/cuda/lib64/libnvrtc.so;/usr/local/cuda/lib64/libnvToolsExt.so;/usr/local/cuda/lib64/libcudart_static.a;-lpthread;dl;/usr/lib/x86_64-linux-gnu/librt.so
-- OpenCV library status:
-- version: 4.0.0
-- libraries: opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio
-- include path: /usr/local/include/opencv4
-- Configuring done
-- Generating done
-- Build files have been written to: /home/prototype/CLionProjects/simnet/cmake-build-release
然后我们的C++代码为:
#include <opencv2/opencv.hpp>
#include "torch/script.h"
#include "torch/torch.h"
#include <iostream>
#include <memory>
using namespace std;
// resize并保持图像比例不变
cv::Mat resize_with_ratio(cv::Mat& img)
{
cv::Mat temImage;
int w = img.cols;
int h = img.rows;
float t = 1.;
float len = t * std::max(w, h);
int dst_w = 224, dst_h = 224;
cv::Mat image = cv::Mat(cv::Size(dst_w, dst_h), CV_8UC3, cv::Scalar(128,128,128));
cv::Mat imageROI;
if(len==w)
{
float ratio = (float)h/(float)w;
cv::resize(img,temImage,cv::Size(224,224*ratio),0,0,cv::INTER_LINEAR);
imageROI = image(cv::Rect(0, ((dst_h-224*ratio)/2), temImage.cols, temImage.rows));
temImage.copyTo(imageROI);
}
else
{
float ratio = (float)w/(float)h;
cv::resize(img,temImage,cv::Size(224*ratio,224),0,0,cv::INTER_LINEAR);
imageROI = image(cv::Rect(((dst_w-224*ratio)/2), 0, temImage.cols, temImage.rows));
temImage.copyTo(imageROI);
}
return image;
}
int main(int argc, const char* argv[])
{
if (argc != 2) {
std::cerr << "usage: example-app <path-to-exported-script-module>\n";
return -1;
}
cv::VideoCapture stream(0);
cv::namedWindow("Gesture Detect", cv::WINDOW_AUTOSIZE);
std::shared_ptr<torch::jit::script::Module> module = torch::jit::load(argv[1]);
module->to(at::kCUDA);
cv::Mat frame;
cv::Mat image;
cv::Mat input;
while(1)
{
stream>>frame;
image = resize_with_ratio(frame);
imshow("resized image",image); //显示摄像头的数据
cv::cvtColor(image, input, cv::COLOR_BGR2RGB);
// 下方的代码即将图像转化为Tensor,随后导入模型进行预测
torch::Tensor tensor_image = torch::from_blob(input.data, {1,input.rows, input.cols,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);
tensor_image = tensor_image.to(torch::kCUDA);
torch::Tensor result = module->forward({tensor_image}).toTensor();
auto max_result = result.max(1, true);
auto max_index = std::get<1>(max_result).item<float>();
if(max_index == 0)
cv::putText(frame, "paper", {40, 50}, cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 255, 0), 2);
else if(max_index == 1)
cv::putText(frame, "scissors", {40, 50}, cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 255, 0), 2);
else
cv::putText(frame, "stone", {40, 50}, cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(0, 255, 0), 2);
imshow("Gesture Detect",frame); //显示摄像头的数据
cv::waitKey(30);
}
然后在cmake时添加-DCMAKE_PREFIX_PATH=/path/to/pytorch/torch/lib/tmp_install
引入libtorch路径。
这样我们的程序就可以运行了~
关于这个libtorch-C++的API的具体讲解,因为篇幅原因没有详细写出来,会在之后的文章中进行说明。
上述的编译中可能会出现这个问题,或者其他出现一大堆命名定义但显示未定义的函数:
error: undefined reference to `cv::imread(std::string const&, int)'
如果你的OpenCV在单独编译使用时没有错误,但是一块编译就出现问题,那么这代表我们的libtorch库和OpenCV库冲突了,冲突原因可能是OpenCV编译OpenCV的C++-ABI版本和libtorch中的不同,所以建议OpenCV最好和libtorch在同样的环境下编译。
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
添加我为好友,拉您入交流群!
请使用微信扫一扫!