仿射变换旋转功能错误问题求助
已解决发表于2024-07-22 14:50:08
0 查看
环境情况
- CANN:8.0RC1
- SDK:6.0RC1
- 设备:Atlas 300I Pro
样例代码
#include "seeker/logger.h"
#include "seeker/loggerApi.h"
#include "opencv2/opencv.hpp"=
#include "MxBase/MxBase.h"
//定义mxVision以向量方式处理图像数据时的数据结构
#include "MxBase/E2eInfer/Tensor/Tensor.h"
//定义向量裁剪、裁剪缩放、格式转换功能
#include "MxBase/E2eInfer/Tensor/TensorDvpp.h"
//定义向量仿射变换功能
#include "MxBase/E2eInfer/TensorOperation/TensorWarping.h"
//定义向量背景替换、透明图片叠加功能
#include "MxBase/E2eInfer/TensorOperation/TensorFusion.h"
//定义DVPP侧图像数据使用的数据结构,可以通过该数据结构转换成向量进行处理
#include "MxBase/E2eInfer/Image/Image.h"
//定义硬件设备初始化等功能
#include "MxBase/DeviceManager/DeviceManager.h"
#include "acl/acl.h"
#include <iostream>
#include <vector>
#include <cmath>
#define ALIGN_UP(num, align) (((num) + (align) - 1) & ~((align) - 1))
std::vector<std::vector<float>> rotationMatrix(float angle) {
float angleRad = angle * M_PI / 180.0;
float cosTheta = cos(angleRad);
float sinTheta = sin(angleRad);
std::vector<std::vector<float>> rotationMatrix = {
{cosTheta, sinTheta, 0},
{-sinTheta, cosTheta, 0}
};
return rotationMatrix;
}
void rotateNewSize(int& new_w, int& new_h, int old_w, int old_h, int angle) {
new_w = fabs(sin(M_PI * (double)(angle / 180.0))) * old_h + fabs(cos(M_PI * (double)(angle / 180.0))) * old_w;
new_h = fabs(sin(M_PI * (double)(angle / 180.0))) * old_w + fabs(cos(M_PI * (double)(angle / 180.0))) * old_h;
}
int main(int argc, char* argv[]) {
if (argc < 2) {
E_LOG("Please use ./xxx {$deviceId} and try again");
return 0;
}
I_LOG("start warpAffine test");
int deviceId = std::atoi(argv[1]);
using namespace MxBase;
MxInit();
{
APP_ERROR result = APP_ERR_OK;
//加载素材图片
cv::Mat srcMatHost = cv::imread("21.png", cv::IMREAD_UNCHANGED);
cv::cvtColor(srcMatHost, srcMatHost, cv::COLOR_BGRA2RGBA);
cv::resize(srcMatHost, srcMatHost, cv::Size(300, 300));
I_LOG("load source picture success");
//将素材图片存入Tensor
std::vector<uint32_t> srcS{ 1, (uint32_t)srcMatHost.rows, (uint32_t)srcMatHost.cols, 4 };
void* cpySrcData = malloc(srcMatHost.rows * srcMatHost.step);
memcpy(cpySrcData, srcMatHost.data, srcMatHost.rows * srcMatHost.step);
Tensor srcTensor(cpySrcData, srcS, TensorDType::UINT8);
I_LOG("fill source picture in Tensor success");
//上传素材向量至Device侧
result = srcTensor.ToDevice(deviceId);
if (result != APP_ERR_OK) {
E_LOG("upload source tensor to device failed");
return -1;
}
I_LOG("upload source tensor success");
//计算目标尺寸和旋转矩阵
int newW = 0;
int newH = 0;
rotateNewSize(newW, newH, srcMatHost.cols, srcMatHost.rows, 45);
std::vector<std::vector<float>> vec = rotationMatrix(45);
I_LOG("calculation destination size={}x{} success", newW, newH);
//构造结果张量
size_t dstSize = (size_t)newW * newH;
void* cpyDstData = malloc(dstSize);
memset(cpyDstData, 0, dstSize);
std::vector<uint32_t> dstS{ 1, (uint32_t)newH, (uint32_t)newW, 4 };
Tensor dstTenosr(cpyDstData, dstS, TensorDType::UINT8);
result = dstTenosr.ToDevice(deviceId);
if (result != APP_ERR_OK) {
E_LOG("upload destination tensor to device failed");
return -1;
}
I_LOG("build and upload destination tensor success");
//素材张量旋转
result = WarpAffineHiper(srcTensor, dstTenosr, vec, PaddingMode::PADDING_CONST, 255, WarpAffineMode::INTER_LINEAR);
if (result != APP_ERR_OK) {
E_LOG("use WarpAffineHiper failed");
return -1;
}
I_LOG("warp affine tensor success");
//下载结果张量至Host侧
result = dstTenosr.ToHost();
if (result != APP_ERR_OK) {
E_LOG("download dst tensor to host failed");
return -1;
}
I_LOG("download dst tensor success");
cv::Mat dstMat(newH, newW, CV_8UC3);
dstMat.data = (uint8_t*)dstTenosr.GetData();
cv::cvtColor(dstMat, dstMat, cv::COLOR_RGB2BGR);
cv::imwrite("dst.png", dstMat);
I_LOG("write dst mat success");
if (cpySrcData) free(cpySrcData);
if (cpyDstData) free(cpyDstData);
}
MxDeInit();
I_LOG("warpAffine test finish");
return 0;
} 问题
- 根据文档描述,输入输出的维度均要求四维NHWC,在样例代码中输入输出都是4通道,那N应该是多少?
- 根据文档描述,输出Tensor若为空Tensor,应该使用TensorMalloc(),然而这个接口之后不再维护,所以样例中选择自己构造上传,这样是正确的吗?输出Tensor不为空是什么意思?
- 仿射变换接口第五个参数borderValue是做什么用的?设置多大比较合适。
本帖最后由 匿名用户 于 2024/12/05 17:34:11 编辑
环境情况
样例代码
#include "seeker/logger.h" #include "seeker/loggerApi.h" #include "opencv2/opencv.hpp"= #include "MxBase/MxBase.h" //定义mxVision以向量方式处理图像数据时的数据结构 #include "MxBase/E2eInfer/Tensor/Tensor.h" //定义向量裁剪、裁剪缩放、格式转换功能 #include "MxBase/E2eInfer/Tensor/TensorDvpp.h" //定义向量仿射变换功能 #include "MxBase/E2eInfer/TensorOperation/TensorWarping.h" //定义向量背景替换、透明图片叠加功能 #include "MxBase/E2eInfer/TensorOperation/TensorFusion.h" //定义DVPP侧图像数据使用的数据结构,可以通过该数据结构转换成向量进行处理 #include "MxBase/E2eInfer/Image/Image.h" //定义硬件设备初始化等功能 #include "MxBase/DeviceManager/DeviceManager.h" #include "acl/acl.h" #include <iostream> #include <vector> #include <cmath> #define ALIGN_UP(num, align) (((num) + (align) - 1) & ~((align) - 1)) std::vector<std::vector<float>> rotationMatrix(float angle) { float angleRad = angle * M_PI / 180.0; float cosTheta = cos(angleRad); float sinTheta = sin(angleRad); std::vector<std::vector<float>> rotationMatrix = { {cosTheta, sinTheta, 0}, {-sinTheta, cosTheta, 0} }; return rotationMatrix; } void rotateNewSize(int& new_w, int& new_h, int old_w, int old_h, int angle) { new_w = fabs(sin(M_PI * (double)(angle / 180.0))) * old_h + fabs(cos(M_PI * (double)(angle / 180.0))) * old_w; new_h = fabs(sin(M_PI * (double)(angle / 180.0))) * old_w + fabs(cos(M_PI * (double)(angle / 180.0))) * old_h; } int main(int argc, char* argv[]) { if (argc < 2) { E_LOG("Please use ./xxx {$deviceId} and try again"); return 0; } I_LOG("start warpAffine test"); int deviceId = std::atoi(argv[1]); using namespace MxBase; MxInit(); { APP_ERROR result = APP_ERR_OK; //加载素材图片 cv::Mat srcMatHost = cv::imread("21.png", cv::IMREAD_UNCHANGED); cv::cvtColor(srcMatHost, srcMatHost, cv::COLOR_BGRA2RGBA); cv::resize(srcMatHost, srcMatHost, cv::Size(300, 300)); I_LOG("load source picture success"); //将素材图片存入Tensor std::vector<uint32_t> srcS{ 1, (uint32_t)srcMatHost.rows, (uint32_t)srcMatHost.cols, 4 }; void* cpySrcData = malloc(srcMatHost.rows * srcMatHost.step); memcpy(cpySrcData, srcMatHost.data, srcMatHost.rows * srcMatHost.step); Tensor srcTensor(cpySrcData, srcS, TensorDType::UINT8); I_LOG("fill source picture in Tensor success"); //上传素材向量至Device侧 result = srcTensor.ToDevice(deviceId); if (result != APP_ERR_OK) { E_LOG("upload source tensor to device failed"); return -1; } I_LOG("upload source tensor success"); //计算目标尺寸和旋转矩阵 int newW = 0; int newH = 0; rotateNewSize(newW, newH, srcMatHost.cols, srcMatHost.rows, 45); std::vector<std::vector<float>> vec = rotationMatrix(45); I_LOG("calculation destination size={}x{} success", newW, newH); //构造结果张量 size_t dstSize = (size_t)newW * newH; void* cpyDstData = malloc(dstSize); memset(cpyDstData, 0, dstSize); std::vector<uint32_t> dstS{ 1, (uint32_t)newH, (uint32_t)newW, 4 }; Tensor dstTenosr(cpyDstData, dstS, TensorDType::UINT8); result = dstTenosr.ToDevice(deviceId); if (result != APP_ERR_OK) { E_LOG("upload destination tensor to device failed"); return -1; } I_LOG("build and upload destination tensor success"); //素材张量旋转 result = WarpAffineHiper(srcTensor, dstTenosr, vec, PaddingMode::PADDING_CONST, 255, WarpAffineMode::INTER_LINEAR); if (result != APP_ERR_OK) { E_LOG("use WarpAffineHiper failed"); return -1; } I_LOG("warp affine tensor success"); //下载结果张量至Host侧 result = dstTenosr.ToHost(); if (result != APP_ERR_OK) { E_LOG("download dst tensor to host failed"); return -1; } I_LOG("download dst tensor success"); cv::Mat dstMat(newH, newW, CV_8UC3); dstMat.data = (uint8_t*)dstTenosr.GetData(); cv::cvtColor(dstMat, dstMat, cv::COLOR_RGB2BGR); cv::imwrite("dst.png", dstMat); I_LOG("write dst mat success"); if (cpySrcData) free(cpySrcData); if (cpyDstData) free(cpyDstData); } MxDeInit(); I_LOG("warpAffine test finish"); return 0; }问题