CUDA小白 - NPP(6) 图像处理 Geometry Transforms (1)

news2025/1/11 5:45:11

cuda小白
原始API链接 NPP

GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》

常见的NppStatus,可以看这里。

Resize

图像尺寸的resize操作。

// 指定x和y的resize尺寸
NppStatus nppiResizeSqrPixel_8u_C3R(const Npp8u *pSrc,
									NppiSize oSrcSize,
									int nSrcStep,
									NppiRect oSrcROI,
									Npp8u *pDst,
									int nDstStep,
									NppiRect oDstROI,
									double nXFactor,
									double nYFactor,
									double nXShift,
									double nYShift,
									int eInterpolation);
// x和y的resize尺寸自动计算
NppStatus nppiResize_8u_C3R(const Npp8u *pSrc,
							int nSrcStep,
							NppiSize oSrcSize,
							NppiRect oSrcRectROI,
							Npp8u *pDst,
							int nDstStep,
							NppiSize oDstSize,
							NppiRect oDstRectROI,
							int eInterpolation);	
// 多batch的resize
// 涉及到一个新的数据类型,NppiResizeBatchCXR
NppStatus nppiResizeBatch_8u_C3R(NppiSize oSmallestSrcSize,
								 NppiRect oSrcRectROI,
								 NppiSize oSmallestDstSize,
								 NppiRect oDstRectROI,
								 int eInterpolation,
								 NppiResizeBatchCXR *pBatchList,
								 unsigned int nBatchSize);	
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  cv::Mat image_dog = cv::imread(directory + "dog.png");
  int image_width = image_dog.cols;
  int image_height = image_dog.rows;
  int image_size = image_width * image_height;

  // =============== device memory ===============
  // input
  uint8_t *in_image;
  cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));
  cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);
  // output
  double scale_w = 1.0 / 4;
  double scale_h = 1.0 / 4;
  uint8_t *out_ptr1, *out_ptr2;
  int dst_width = image_width * scale_w;
  int dst_height = image_height * scale_h;
  cudaMalloc((void**)&out_ptr1, dst_width * dst_height * 3 * sizeof(uint8_t));  // 三通道
  cudaMalloc((void**)&out_ptr2, dst_width * dst_height * 3 * sizeof(uint8_t));  // 三通道

  // roi size
  NppiSize in_size, out_size;
  in_size.width = image_width;
  in_size.height = image_height;
  out_size.width = dst_width;
  out_size.height = dst_height;

  NppiRect rc1, rc2;
  rc1.x = 0;
  rc1.y = 0;
  rc1.width = image_width;
  rc1.height = image_height;
  rc2.x = 0;
  rc2.y = 0;
  rc2.width = dst_width;
  rc2.height = dst_height;

  cv::Mat out_image = cv::Mat::zeros(dst_height, dst_width, CV_8UC3);
  NppStatus status;
  // =============== nppiResizeSqrPixel_8u_C3R ===============
  // resize to half
  status = nppiResizeSqrPixel_8u_C3R(in_image, in_size, image_width * 3, rc1, out_ptr1, 
                                     dst_width * 3, rc2, scale_w, scale_h, 10.0, 50.0, 
                                     NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiResizeSqrPixel_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, dst_width * dst_height * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "resize_sqr.jpg", out_image);

  // =============== nppiResize_8u_C3R ===============
  // resize to half
  status = nppiResize_8u_C3R(in_image, image_width * 3, in_size, rc1, out_ptr2, 
                             dst_width * 3, out_size, rc2, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiResize_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr2, dst_width * dst_height * 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "resize.jpg", out_image);

  // free
  CUDA_FREE(in_image)
  CUDA_FREE(out_ptr1)
  CUDA_FREE(out_ptr2)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

请添加图片描述
注意:
1.resizesqr的接口支持x和y不同scale的resize操作,并且可以添加左上角的offset值(result中的x和y分别添加了10像素和50像素的offset)

Remap

重映射,remap实现功能与原始的Opencv的功能一致。

NppStatus nppiRemap_8u_C3R(const Npp8u *pSrc,
							NppiSize oSrcSize,
							int nSrcStep,
							NppiRect oSrcROI,
							const Npp32f *pXMap,
							int nXMapStep,
							const Npp32f *pYMap,
							int nYMapStep,
							Npp8u *pDst,
							int nDstStep,
							NppiSize oDstSizeROI,
							int eInterpolation);
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  cv::Mat image_dog = cv::imread(directory + "dog.png");
  int image_width = image_dog.cols;
  int image_height = image_dog.rows;
  int image_size = image_width * image_height;

  // =============== device memory ===============
  // input
  uint8_t *in_image;
  cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));
  cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);

  cv::Mat mat_mapx = cv::Mat::zeros(image_height, image_width, CV_32FC1);
  cv::Mat mat_mapy = cv::Mat::zeros(image_height, image_width, CV_32FC1);
  for (int i = 0; i < image_height; ++i) {
    for (int j = 0; j < image_width; ++j) {
      mat_mapx.at<float>(i, j) = (float)j;
      mat_mapy.at<float>(i, j) = (float)(image_height - i - 1);
    }
  }

  float *mapx, *mapy;
  cudaMalloc((void**)&mapx, image_size * sizeof(float));
  cudaMalloc((void**)&mapy, image_size * sizeof(float));
  cudaMemcpy(mapx, mat_mapx.data, image_size * sizeof(float), cudaMemcpyHostToDevice);
  cudaMemcpy(mapy, mat_mapy.data, image_size * sizeof(float), cudaMemcpyHostToDevice);

  // output
  uint8_t *out_ptr1;
  cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t));  // 三通道

  // size
  NppiSize in_size, out_size;
  in_size.width = image_width;
  in_size.height = image_height;
  out_size.width = image_width;
  out_size.height = image_height;

  NppiRect rc1;
  rc1.x = 0;
  rc1.y = 0;
  rc1.width = image_width;
  rc1.height = image_height;

  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  // =============== nppiResizeSqrPixel_8u_C3R ===============
  // resize to half
  status = nppiRemap_8u_C3R(in_image, in_size, image_width * 3, rc1, mapx, 
                            image_width * sizeof(float), mapy, image_width * sizeof(float), 
                            out_ptr1, image_width * 3, out_size, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiRemap_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size* 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "remap.jpg", out_image);

  // free
  CUDA_FREE(in_image)
  CUDA_FREE(mapx)
  CUDA_FREE(mapy)
  CUDA_FREE(out_ptr1)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

请添加图片描述
注意点:

  1. mapx和mapy的数据类型是NPP32f(float)类型,因此在指定x和y的step的时候需要惩乘上float的字节数,不然出来的结果不对。

Rotate

旋转,该模块除了直接提供旋转的接口,还同步提供了根据角度和品阿姨计算旋转矩阵的接口

// 除了当前接口,还提供了一个返回四元素的接口
NppStatus nppiGetRotateBound(NppiRect oSrcROI,
							 double aBoundingBox[2][2],
							 double nAngle,
							 double nShiftX,
							 double nShiftY);
// 旋转
NppStatus nppiRotate_8u_C3R(const Npp8u *pSrc,
							NppiSize oSrcSize,
							int nSrcStep,
							NppiRect oSrcROI,
							Npp8u *pDst,
							int nDstStep,
							NppiRect oDstROI,
							double nAngle,
							double nShiftX,
							double nShiftY,
							int eInterpolation);
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  cv::Mat image_dog = cv::imread(directory + "dog.png");
  int image_width = image_dog.cols;
  int image_height = image_dog.rows;
  int image_size = image_width * image_height;

  // =============== device memory ===============
  // input
  uint8_t *in_image;
  cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));
  cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);

  // output
  uint8_t *out_ptr1;
  cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t));  // 三通道

  // size
  NppiSize in_size, out_size;
  in_size.width = image_width;
  in_size.height = image_height;
  out_size.width = image_width;
  out_size.height = image_height;

  NppiRect rc1;
  rc1.x = 0;
  rc1.y = 0;
  rc1.width = image_width;
  rc1.height = image_height;

  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  // =============== nppiResizeSqrPixel_8u_C3R ===============
  // resize to half
  double angle = 30.0;
  double shift_x = image_width / 4;
  double shift_y = image_height / 4;
  status = nppiRotate_8u_C3R(in_image, in_size, image_width * 3, rc1, out_ptr1, image_width * 3, 
                             rc1, angle, shift_x, shift_y, NPPI_INTER_LINEAR);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiRemap_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size* 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "rotate.jpg", out_image);

  // free
  CUDA_FREE(in_image)
  CUDA_FREE(out_ptr1)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

请添加图片描述

Mirror

主要是用于将图像用于镜像操作。

enum NppiAxis {
	NPP_HORIZONTAL_AXIS,
	NPP_VERTICAL_AXIS,
	NPP_BOTH_AXIS
};
// 新增枚举,用于表示镜像的轴
NppStatus nppiMirror_8u_C3R(const Npp8u *pSrc,
							int nSrcStep,
							Npp8u *pDst,
							int nDstStep,
							NppiSize oROI,
							NppiAxis flip);	
code
#include <iostream>
#include <cuda_runtime.h>
#include <npp.h>
#include <opencv2/opencv.hpp>

#define CUDA_FREE(ptr) { if (ptr != nullptr) { cudaFree(ptr); ptr = nullptr; } }

int main() {
  std::string directory = "../";
  cv::Mat image_dog = cv::imread(directory + "dog.png");
  int image_width = image_dog.cols;
  int image_height = image_dog.rows;
  int image_size = image_width * image_height;

  // =============== device memory ===============
  // input
  uint8_t *in_image;
  cudaMalloc((void**)&in_image, image_size * 3 * sizeof(uint8_t));
  cudaMemcpy(in_image, image_dog.data, image_size * 3 * sizeof(uint8_t), cudaMemcpyHostToDevice);

  // output
  uint8_t *out_ptr1;
  cudaMalloc((void**)&out_ptr1, image_size * 3 * sizeof(uint8_t));  // 三通道

  NppiSize in_size;
  in_size.width = image_width;
  in_size.height = image_height;

  cv::Mat out_image = cv::Mat::zeros(image_height, image_width, CV_8UC3);
  NppStatus status;
  // =============== nppiMirror_8u_C3R ===============
  status = nppiMirror_8u_C3R(in_image, image_width * 3, out_ptr1, image_width * 3, 
                             in_size, NPP_HORIZONTAL_AXIS);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiMirror_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size* 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "mirror_horizontal.jpg", out_image);

  // =============== nppiMirror_8u_C3R ===============
  status = nppiMirror_8u_C3R(in_image, image_width * 3, out_ptr1, image_width * 3, 
                             in_size, NPP_VERTICAL_AXIS);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiMirror_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size* 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "mirror_vertical.jpg", out_image);

  // =============== nppiMirror_8u_C3R ===============
  status = nppiMirror_8u_C3R(in_image, image_width * 3, out_ptr1, image_width * 3, 
                             in_size, NPP_BOTH_AXIS);
  if (status != NPP_SUCCESS) {
    std::cout << "[GPU] ERROR nppiMirror_8u_C3R failed, status = " << status << std::endl;
    return false;
  }
  cudaMemcpy(out_image.data, out_ptr1, image_size* 3, cudaMemcpyDeviceToHost);
  cv::imwrite(directory + "mirror_both.jpg", out_image);

  // free
  CUDA_FREE(in_image)
  CUDA_FREE(out_ptr1)
}
make
cmake_minimum_required(VERSION 3.20)
project(test)

find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(CUDA REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})
file(GLOB CUDA_LIBS "/usr/local/cuda/lib64/*.so")

add_executable(test test.cpp)
target_link_libraries(test
                      ${OpenCV_LIBS}
                      ${CUDA_LIBS}
)
result

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/999409.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Win11自带微软输入法怎么输入π及其他希腊字母

如果用搜狗等第三方输入法的话就没有这些问题了&#xff0c;各种符号很方便。 自带的输入法输入 pi 和 pai 都不能正常输入 π \pi π 参考文章 https://www.cnblogs.com/qq-757617012/p/14078133.html 如果用自带的输入法可以采用以下方式 输入uuxl xl表示“希腊”&#x…

最长回文子串(Longest Palindromic substring)

什么叫回文串 就是正读和反读都是一样的字符串&#xff0c;比如aba,abba,cdc像这样的字符串都是回文字符串 暴力破解法来查找最长的回文子串 这个图解的意思就是我们要拿到每一个右边的数&#xff0c;然后与左边的数一一匹配 下面看一下java的实现代码 package com.pxx;/*** …

详细解析如何用“双指针“解题(面试必备,小白一看就会系类)

一、前言 大家在平时的训练和交流中肯定多少都会听过或者见过用"双指针"去快速的解题&#xff0c;那么大家有没有想过&#xff0c;为什么要用"双指针"呢&#xff1f;这里的"双指针"和我们平时了解的指针一样吗&#xff1f; 其实&#xff0c;这里…

Python数据分析实战-表连接-merge四种连接方式用法(附源码和实现效果)

实现功能 表连接-merge四种连接方式用法&#xff0c; 将两个pandas表根据一个或者多个键&#xff08;列&#xff09;值进行连接。 实现代码 import pandas as pddf1 pd.DataFrame({key: [a, b, d],data1: range(3)}) print(df1)df2 pd.DataFrame({key: [a, b, c, a, b],dat…

电商商品的前后台类目设计思路,小本本记下来(提供获取京东淘宝商品类目信息API 免费测试)

今天&#xff0c;我们来聊聊商品类目的设计思路。 商品是电商的根基&#xff0c;核心目标是销&#xff0c;也就是卖货。卖货可以多层理解&#xff0c;卖给谁&#xff0c;怎么卖&#xff0c;什么货&#xff0c;其实就是人货场的概念。 我理解的货&#xff0c;不仅是商品层面&a…

使用python requests上传文件

import requests# 指定要上传的文件 files {file: (example.txt, open(1.py, rb))}# 发送POST请求上传文件 response requests.post(http://baidu.com, filesfiles, proxies{http: 127.0.0.1:8080})# 检查响应 if response.status_code 200:print(文件上传成功) else:print(…

连续相同idx 性能为4cycle、不同idx性能为2cycle

mem_bypass结合Tdm 技术&#xff08;通信技术知识积累&#xff1a;TDM - 知乎&#xff09;可以对ram的多拍连续访问。 mem_bypass技术的核心就是在下一次的读前&#xff0c;可以cover 上一次的写。 如下图所示&#xff08;读延时为3cycle&#xff09;&#xff1a; 时序1 &am…

ROS路由器环回脚本,实际在用,只需要更新一个IP地址

实际在用的脚本&#xff0c;需要ros版本较高&#xff0c;低版本可以照着自己改改用&#xff0c;亲测可以。 #取当前拨号ip地址 :global ednsiph [ /ip address get [/ip address find interface"pppoe-out1" ] address ] :global newip [:pick \$ednsiph 0 [:find \…

【chromium】windows 获取源码到本地

从github的chromium 镜像git clone 到2.5G失败了官方说不能,要去 windows_build_instructions vs2017和19都是32位的 vs2022是x64的 vs2022_install You may also have to set variable vs2022_install to your installation path of Visual Studio 2022,

移动中兴ZXHN F6610M光猫拨号密码查询

宽带到期&#xff0c;移动新换了个光猫&#xff0c;型号中兴ZXHN F6610M 光猫默认提供了user账号&#xff0c;但是这个账号基本只有查看权限。 超级账号CMCCAdmin aDm8H%MdA密码并不管用。 问装维&#xff0c;装维不给&#xff0c;曲线救国通过某二手平台查到了。 1.通过超密…

windows操作系统通过浏览器调用本地程序

通过浏览器调用本地程序通常被认为是危险的行为&#xff0c;是被禁止的&#xff0c;但在基于B/S架构的一体机项目中会用到关闭或重启操作系统的操作。此时需要在前端页面有相应的功能按钮并能实现相应的功能。 通过浏览器调用本地应用程序通常需要使用浏览器扩展或本地应用程序…

Transformer(二)—— ResNet(残差网络)

Transformer&#xff08;二&#xff09;—— ResNet&#xff08;残差网络&#xff09; 一、背景1.1 梯度消失/爆炸1.2 网络退化(Degradation) 二、思路2.1 为什么需要更深的网络2.2 理想中的深网络表现 三、实践和实验效果3.1 构造恒等映射&#xff1a;残差学习&#xff08;res…

AIRIOT训练营沈阳站圆满结束|手把手教你搞定物联网应用开发

8月28日-9月1日&#xff0c;由航天科技控股集团有限公司&#xff08;以下简称“航天科技”&#xff09;主办的《AIRIOT物联网平台应用与实战》训练营在沈阳圆满结束&#xff0c;来自上海电机学院、中渝软通信息技术、北京华天机电研究所、北京环卫集团、 中国恩菲 等多家企业…

easypoi模板导出、一张sheet有多个不同表格、带一张或多张echars图表

前言 昨天遇到个有点复杂的excel需要导出&#xff0c;一张sheet里面有两个不同的表格&#xff0c;然后还有几张echars图表要加进去。总共分为上下两个部分&#xff0c;上面是表格一&#xff1b;下面又分为左右两个部分&#xff0c;左边是表格二&#xff0c;右边是几张echars图…

过等保三级的好处是什么?谁能简单说说?

虽然国家已经严格落地执行了等保2.0政策&#xff0c;但还有少数小伙伴对于等保政策不是很了解&#xff0c;有小伙伴问过等保三级的好处是什么&#xff1f;谁能简单说说&#xff1f;这里就来一起聊聊。 过等保三级的好处是什么&#xff1f; 好处1、遵循国家法律法规要求&…

气象观测站:观测原理及优势,助力气象精准预报

随着全球气候变化日益严重&#xff0c;气象观测站在现代社会中的地位愈发凸显。 一、气象观测站的观测原理 气象观测站主要通过各种传感器来测量大气的温度、湿度、风速、风向、气压、太阳辐射等基本气象要素。这些传感器需要具备高精度和高稳定性&#xff0c;以确保观测数据…

DAY02_瑞吉外卖——完善登录功能新增员工员工分页查询启用/禁用员工账号编辑员工信息

目录 1. 完善登录功能1.1 问题分析1.2 思路分析1.3 代码实现1.4 功能测试 2. 新增员工2.1 需求分析2.2 数据模型2.3 程序执行流程2.4 代码实现2.5 功能测试2.6 全局异常处理2.6.1 思路分析2.6.2 全局异常处理器2.6.3 测试 3. 员工分页查询3.1 需求分析3.2 程序执行流程3.2.1 页…

实现在外网SSH远程访问内网树莓派的详细教程

文章目录 如何在局域网外SSH远程访问连接到家里的树莓派&#xff1f;如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar4.2 cpolar进行token认证4.3 配置cpol…

PyTorch深度学习实战(15)——迁移学习

PyTorch深度学习实战&#xff08;15&#xff09;——迁移学习 0. 前言1. 迁移学习1.1 迁移学习基本概念1.2 迁移学习的重要性1.3 ImageNet1.4 迁移学习流程 2. VGG16 架构3. 使用预训练 VGG16 模型实现猫狗分类小结系列链接 0. 前言 迁移学习( Transfer Learning )是一种利用从…

利用evo将kitti数据集真值轨迹由kitti格式转为tum格式

&#xff08;1&#xff09;首先是序列对应问题&#xff1a; 00: 2011_10_03_drive_0027 01: 2011_10_03_drive_0042 02: 2011_10_03_drive_0034 03: 2011_09_26_drive_0067 04: 2011_09_30_drive_0016 05: 2011_09_30_drive_0018 06: 2011_09_30_drive_0020 07: 2011_09_30_dr…