环境搭建
CmakeLists.txt
代码语言:javascript
复制cmake_minimum_required (VERSION 3.8)
project(SOLDIER)
set(Torch_DIR "/libtorch/share/cmake/Torch")
set(PYTHON_EXECUTABLE "/usr/bin/python3")
find_package(Torch REQUIRED)
find_package(OpenCV REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_BUILD_TYPE Debug)
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(run main.cpp src/Gun.cpp src/Soldier.cpp)
target_link_libraries(run "${OpenCV_LIBS}" "${TORCH_LIBRARIES}")
set_property(TARGET run PROPERTY CXX_STANDARD 14)
张量基本操作
代码语言:javascript
复制#include <iostream>
#include<torch/torch.h>
using namespace std;
// 张量 创建一个{3,4}的张量
auto b = torch::rand({3,4});
std::cout<<"创建的张量:"<<b<<std::endl;
b.print();
// 创建张量
at::Tensor a = at::ones({2, 2}, at::kInt);
at::Tensor c = at::randn({2, 2});
c = c.to(at::kInt);
std::cout<<"ones tensor size:"<<b.sizes()<<std::endl; //只打印维度信息
c.print();//打印维度和数据类型
// 判段cuda是否有效
bool result = torch::cuda::is_available();
std::cout<<result<<std::endl;
//test torch
auto device = torch::Device(torch::kCUDA);
std::cout<<device<<std::endl;
//初始化张量的值
torch::Tensor allZeros = torch::zeros({5,7});
//定义一定维度的单位张量 对角线为1 其余为0
auto beye = torch::eye(5);
// 一定维度的张量并设置初始值
auto weight = torch::full({3,4},10);
// 以另一个张量初始化另外一个张量
auto weight_copy = torch::full_like(weight.toType(torch::kFloat),2.5);
// 定义n行1列的张量,并初始化值
auto test = torch::tensor({1,2,3,4,5,6,7,8});
// 定义一个在[0,1]之间的符合均匀分布的随机值初始化
auto tensorrands = torch::rand({3,4});
// 定义一个5行6列的张量
tensorrands = torch::randn({5,6});
// 数组转化为张量
int aa[4] = {1,2,3,4};
auto aaa = torch::from_blob(aa,{2,2},torch::kFloat);
//使用容器来初始化张量
vector<int> aaaa = {1,2,3};
auto aaaaTensor = torch::from_blob(aaaa.data(),{1,1,1,3},torch::kFloat);
std::cout<< aaaaTensor<<std::endl;
//神经网络的输入通常为一张单通道灰度图或一张三通道的彩色图,如果输入为Opencv Mat格式的三通道彩色图,
//我们需要格外注意数据维度的顺序,因为Mat格式的三通道图像与libtorch Tensor张量的数据维度是不一样的,
//前者是[Height, Width, channels],后者是[channels, Height, Width],如果展开成一维向量来看,
//Opencv Mat存储RGB图像的顺序为(每个R、G、B像素点交替存储)
// 使用torch::from_blob创建的张量是与传入的指针共用内存,没有开辟内存
// 重新创建内存需要需要使用clone 函数
auto newaaa = torch::from_blob(aa,{2,2},torch::kFloat).clone();
// 张量拼接
torch::Tensor a1 = torch::rand({ 2,3 }); //2行3列
torch::Tensor a2 = torch::rand({ 2,1 }); //2行1列
torch::Tensor cat_1 = torch::cat({ a1, a2 }, 1); //dim参数为1表示按列拼接
// 张量切片与索引
//linspace(1, 75, 75)为取范围再1~75之间、长度为75的数组,也即1、2、3、...、75
auto newnew = torch::linspace(1, 75, 75).reshape({ 3, 5, 5 }); //start -- end -- length
cout << newnew << endl;
//对于所有第1维度、第2维度,取第3维度索引号为2的数据
auto bx = newnew.index({ "...", 2 });
cout << bx << endl;
auto bx1 = newnew.index({ "...", 2, 3 }); //对所有第1维度,取第2维度索引号为2、第3维度索引号为3的数据
auto bx2 = newnew.index({ 2, "...", 3 }); //对索引号为2的第1维度、索引号为3的第3维度,取所有第2维度数据
auto bx3 = newnew.index({1,2}); //读取第一维度的的1,和第二维度的2的所有数据
// 通过索引赋值
// newnew.index_put_({"...","...",1},100);
// std::cout<<newnew<<std::endl;
// 切片
// auto newslice = newnew.index({"...",Slice(1)});
// cout<< newslice << endl;
// 张量的压缩与扩张
auto tensorA = torch::zeros({1,5,3,1});//定义一个1*5*3*1的张量
std::cout << tensorA.sizes() << std::endl;
// 删除长度为1的维度改成5*3
auto tensorB = torch::squeeze(tensorA);
std::cout << tensorB.sizes()<<std::endl;
// 删除第0维度,变成5*3*1
tensorB = torch::squeeze(tensorA, 0);
std::cout << "删除第0维度,变成5*3*1:"<<tensorB.sizes()<<std::endl;
// 在第0维度增加一个长度为1的维度,变成1*1*5*3*1
tensorB = torch::unsqueeze(tensorA, 0);
std::cout << "在第0维度增加一个长度为1的维度,变成1*1*5*3*1:"<<tensorB.sizes()<<std::endl;
// 张量对应位置的计算
auto tensorC = torch::randint(0,10,{3,5});
std::cout<<tensorC<<std::endl;
auto tensorD = torch::randint(0,10,{3,5});
std::cout << tensorD << std::endl;
auto tensorE= tensorC tensorD;
std::cout<<"加法结果:"<<tensorE <<std::endl;
//两个张量维度不同
// 需要满足两个条件:1. 每个张量至少有一个维度;2. 两个张量对应的位置的维度要么相同要么其中一个维度为1,要么不存在
auto atensor = torch::randint(0, 10, { 1, 4, 4 });
cout << atensor << endl;
auto btensor = torch::randint(0, 10, { 3, 1, 4 });
cout << btensor << endl;
auto ctensor = atensor btensor;
cout << ctensor << endl;
// 求张量最大值和最小值
//求张量a第0维度的最大值
std::tuple<torch::Tensor, torch::Tensor> max_classes = (torch::max)(atensor, 0);
auto max_1 = std::get<0>(max_classes); //求得最大值
auto max_index = std::get<1>(max_classes); //求得最大值的索引
cout << max_1 << endl;
cout << max_index << endl;
// 操作第0维度
// 无论张量有多少维度,变量[2] 都是对第一维度的特征进行操作
auto tensorG = torch::rand({3,4,5});
std::cout << tensorG << std::endl;
tensorG[1] = torch::zeros({4,5});//将a的第0维度的索引号1张量重新赋值
std::cout << tensorG << std::endl;
// 张量的堆叠
auto linetensorA = torch::linspace(1,10,10).reshape({2,5});
auto linetensorB = torch::linspace(21,30,10).reshape({2,5});
//生成维度为2*5的张量a
//生成维度为2*5的张量b
auto linetensorC = torch::stack({ linetensorA, linetensorB}, 0);
cout << "linetensorC"<<linetensorC <<"linetensorB"<< linetensorB<<endl;
// 调整维度顺序
auto tensorH = torch::randn({ 3, 4, 5 });
cout << "调整前:"<<tensorH.sizes() << endl;
auto tensorI = tensorH.permute({ 1,0,2 }); //将第0维度和第1维度交换顺序
cout << "调整后:"<<tensorI.sizes() << endl;
// 改变张量的形状
auto tensorJ = tensorH.view({12,5});
auto tensorK = tensorH.reshape({12,5});
auto tensorL = tensorH.contiguous().view({12,5});
cout << tensorJ << tensorK << tensorJ <<endl;
```