分类 初探TensorRT 下的文章

坑0 cv::Mat对象内存问题

image-20230601123926445

同时 OpenCV使用引用计数机制来管理cv::Mat对象的内存,这意味着当复制一个cv::Mat对象时,实际上只会增加引用计数,而不会复制底层数据。

坑1 cv::imwrite()保存问题

cv::imwrite()函数用于将图像保存到文件中。默认情况下,它期望输入图像的像素类型是8位无符号整数(CV_8U)。如果使用

convertTo(normalized_image, CV_32FC3, 1.0 / 255.0);

转成了fp32格式,将无法使用cv::imwrite()保存。

坑2 “通道转换”和“convertTo”归一化的先后顺序问题

由于读取cv::imread("inference/car.jpg")读取的cv::Mat,在内存中的typeCV_8UC3,使用resized_image.convertTo(normalized_image, CV_32FC3, 1.0 / 255.0);会将其转换成fp32,在内存中占用内存空间不同,之后使用cv::cvtColor(image, converted_image, cv::COLOR_BGR2RGB);会造成一些奇奇怪怪的错误.......

坑3 opencv读取的格式和yolov5推理格式的区别

这里说的格式,代表opencv 读取的数据通道顺序为(高,宽,BGR),而yolov5需要的是(RGB,高,宽),顺序不同,且色彩通道顺序也不同。在数据处理时需要额外注意!!!

结论

cv::Mat convertBGRtoRGB(const cv::Mat& image)
{
    cv::Mat converted_image;
    cv::cvtColor(image, converted_image, cv::COLOR_BGR2RGB);
    return converted_image;
}
cv::Mat padToSquare(const cv::Mat& image, const cv::Scalar& color)
{
    int max_dim = std::max(image.rows, image.cols);
    int top = 0, bottom = 0, left = 0, right = 0;

    if (image.rows < max_dim) {
        int diff = max_dim - image.rows;
        top = diff / 2;
        bottom = diff - top;
    }
    else if (image.cols < max_dim) {
        int diff = max_dim - image.cols;
        left = diff / 2;
        right = diff - left;
    }

    cv::Mat padded_image;
    cv::copyMakeBorder(image, padded_image, top, bottom, left, right, cv::BORDER_CONSTANT, color);
    return padded_image;
}
void preprocess(cv::Mat &src,cv::Mat &dst){
  cv::Mat coner_img = convertBGRtoRGB(src);    # 先bgr转rgb
  cv::Scalar fill_color(116, 116, 116);
  cv::Mat squared_image = padToSquare(coner_img, fill_color);  # 补灰色到图片成为方形
  cv::Mat resized_image;
  cv::Size target_size(640, 640);                             
  cv::resize(squared_image, resized_image, target_size);            # resize 640 不会变形
  src = resized_image;
  cv::Mat normalized_image;
  resized_image.convertTo(normalized_image, CV_32FC3, 1.0 / 255.0);    # 归一化/255
  dst = normalized_image;
}

在copy内存前做 (高,宽, RGB)=>>>>(RGB,高,宽)

struct Image {
  const float *rgbprt = nullptr;   // 32fp指针
  int width = 0, height = 0, size = 0;  // 多少个float
  Image() = default;
  Image(const float *rgbprt, int width, int height,int size) : rgbprt(rgbprt), width(width), height(height),size(size){}
};

yolo::Image cvimg(const cv::Mat &image) { 
  std::shared_ptr<std::vector<float>> inputData = std::make_shared<std::vector<float>>();
  inputData->reserve(image.cols * image.rows * 3);
  for (int c = 0; c < 3; ++c) {
      for (int i = 0; i < image.rows; ++i) {
          for (int j = 0; j < image.cols; ++j) {
              float tmp = image.at<cv::Vec3f>(i, j)[c];
              inputData->push_back(tmp);
          }
      }
  }
  return yolo::Image(inputData->data(), image.cols, image.rows,image.cols*image.rows*image.channels()); 
}

0.安装说明

CUDA_PATH       = /usr/local/cuda
TRT_PATH    = /opt/TensorRT-8.6.1.6

1.CMakeLists.txt

cmake_minimum_required(VERSION 3.14) ##最低版本

project(main) ##项目名称

#cuda TensorRT opencv2的include路径
include_directories(/usr/local/cuda/include)
include_directories(/opt/TensorRT-8.6.1.6/include)
include_directories(/usr/include/opencv2)
#编译器相关设置
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CMAKE_CXX_COMPILER "/usr/local/cuda/bin/nvcc")
add_compile_options(-std=c++14 -O3 -UDEBUG -Xcompiler -fPIC -use_fast_math -g)
#set(CMAKE_CXX_FLAGS "-std=c++14 -O3 -UDEBUG -Xcompiler  -fPIC -use_fast_math")
#为工程添加可执行文件
set(CMAKE_VERBOSE_MAKEFILE on)
set ( PRJ_SRC_LIST )
file ( GLOB root_src_files "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" )
list ( APPEND PRJ_SRC_LIST ${root_src_files} )
# file ( GLOB root_src_files "${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp" )
# list ( APPEND PRJ_SRC_LIST ${root_src_files} )

# 指定链接库的路径
link_directories(/usr/local/cuda/lib64 /opt/TensorRT-8.6.1.6/lib /opt/TensorRT-8.6.1.6/lib/stubs /usr/local/lib)

# 编译所有cpp
add_executable(main ${PRJ_SRC_LIST})


set ( PRJ_LIBRARIES )
# 指定.a静态链接库 和 .so 动态链接库  名称 
# target_link_libraries(onnxTmp ${PRJ_LIBRARIES} cudart_static nvrtc nvptxcompiler_static nvonnxparser nvinfer_static cudnn_static_stub_trt cublas_static_stub_trt cublasLt_static_stub_trt)
target_link_libraries(main ${PRJ_LIBRARIES} cudart_static nvrtc nvptxcompiler_static nvonnxparser nvinfer cudnn_static_stub_trt cublas_static_stub_trt cublasLt_static_stub_trt opencv_gapi opencv_highgui opencv_ml opencv_objdetect opencv_photo opencv_stitching opencv_video opencv_calib3d opencv_features2d opencv_dnn opencv_flann opencv_videoio opencv_imgcodecs opencv_imgproc opencv_core)

# 
#使用cuda
set_target_properties(Main PROPERTIES CUDA_SEPARABLE_COMPILATION ON)

# cmake .. -DCMAKE_SKIP_BUILD_RPATH=TRUE

2.编译CMD

mkdir build
cd build
cmake .. -DCMAKE_SKIP_BUILD_RPATH=TRUE
make

0.安装说明

CUDA_PATH       = /usr/local/cuda
TRT_PATH    = /opt/TensorRT-8.6.1.6

1.Makefile.inc

CUDA_PATH       = /usr/local/cuda
TRT_PATH    = /opt/TensorRT-8.6.1.6
CXX            = $(CUDA_PATH)/bin/nvcc
CXXFLAGS         = -std=c++14 -O0 -UDEBUG -Xcompiler -fPIC -use_fast_math  $(INCLUDE) -g
INCLUDE        += -I. -I../../include -I../../../include
INCLUDE          = -I$(CUDA_PATH)/include
INCLUDE         += -I$(TRT_PATH)/include
INCLUDE        += -I/usr/include/opencv2
LDFLAGS          = -L$(CUDA_PATH)/lib64 -lcudart -lnvrtc -lnvptxcompiler_static
LDFLAGS         += -L$(TRT_PATH)/lib -lnvinfer_static -lcudnn -lnvonnxparser 
LDFLAGS         += -L$(TRT_PATH)/lib/stubs/ -lcublas_static_stub_trt -lcublasLt_static_stub_trt
LDFLAGS         += -L/usr/local/lib -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_dnn -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core

2.Makefile

include Makefile.inc

SRC1         = ${wildcard *.cpp}
SRC2         = ${wildcard *.cu}
OBJ1         = $(SRC1:.cpp=.o)
OBJ2         = $(SRC2:.cu=.o)
OBJ          = $(OBJ1) $(OBJ2) 

$(info $(OBJ))

TARGET1 = main
TARGET2 = test

all:$(TARGET1)

$(TARGET1):$(OBJ)
    $(CXX) -g $(LDFLAGS) -o $@ $^

%.o: %.cpp
    $(CXX) -g $(CXXFLAGS) -c -o $@ $^
%.o: %.cu
    $(CXX) -g $(CXXFLAGS) -c -o $@ $^



clean:
    rm -rf ./*.d ./*.o ./*.so $(TARGET1) ./*.plan ./*.jpg