- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在使用 nppi cuda 库中的 nppi 几何变换函数时,我遇到了一个奇怪的错误。代码在这里:
#include <nppi.h>
#include <nppi_geometry_transforms.h>
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <vector>
void write(const cv::Mat &mat1, const std::string &path) {
auto mat2 = cv::Mat(mat1.rows, mat1.cols, CV_8UC4);
for (int i = 0; i < mat1.rows; i++) {
for (int j = 0; j < mat1.cols; j++) {
auto &bgra = mat2.at<cv::Vec4b>(i, j);
auto &rgb = mat1.at<cv::Vec3b>(i, j);
bgra[0] = rgb[2];
bgra[1] = rgb[1];
bgra[2] = rgb[0];
bgra[3] = UCHAR_MAX;
}
}
std::vector<int> compression_params;
compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);
compression_params.push_back(9);
cv::imwrite(path, mat2, compression_params);
}
int main() {
std::cout << "Hello, World!" << std::endl;
auto mat = cv::Mat(256, 256, CV_8UC3);
for (int i = 0; i < mat.rows; i++) {
for (int j = 0; j < mat.cols; j++) {
auto &rgb = mat.at<cv::Vec3b>(i, j);
rgb[0] = (uint8_t)j;
rgb[1] = (uint8_t)i;
rgb[2] = (uint8_t)(UCHAR_MAX - j);
}
}
write(mat, "./test.png");
uint8_t *gpuBuffer1;
uint8_t *gpuBuffer2;
cudaMalloc(&gpuBuffer1, mat.total());
cudaMalloc(&gpuBuffer2, mat.total());
cudaMemcpy(gpuBuffer1, mat.data, mat.total(), cudaMemcpyHostToDevice);
auto status = nppiResize_8u_C3R(
gpuBuffer1, mat.cols * 3, {.width = mat.cols, .height = mat.rows},
{.x = 0, .y = 0, .width = mat.cols, .height = mat.rows}, gpuBuffer2,
mat.cols * 3, {.width = mat.cols, .height = mat.rows},
{.x = 0, .y = 0, .width = mat.cols, .height = mat.rows},
NPPI_INTER_NN);
if (status != NPP_SUCCESS) {
std::cerr << "Error executing Resize -- code: " << status << std::endl;
}
auto mat2 = cv::Mat(mat.rows, mat.cols, CV_8UC3);
cudaMemcpy(mat2.data, gpuBuffer2, mat.total(), cudaMemcpyDeviceToHost);
write(mat2, "./test1.png");
}
基本上我会显示彩虹图片。然后将其写入 GPU,然后将其调整为完全相同的大小,然后将其复制回主机,然后再次显示。我得到的是大约 2/3 的返回图片中的乱码数据。
第一张图片是输入图片。第二张输入图片为输出图片。
我希望两张图片是一样的。
如果我使用偏移量调整 ROI 并更改目标缓冲区的宽度和高度,则调整大小的图片顶部 1/3 中的像素实际上会正确移动和调整大小。但是图片的其余部分是乱码。不知道出了什么问题。有没有在 cuda nppi 库或图像处理方面有经验的人知道发生了什么事?
为了方便任何想要编译它的人,下面包含了 CMake 文件。您必须将 opencv 和 cuda 工具包安装为 C++ 库:
cmake_minimum_required(VERSION 3.18)
project(test_nppi)
enable_language(CUDA)
set(CMAKE_CXX_STANDARD 17)
find_package(CUDAToolkit REQUIRED)
find_package(OpenCV)
message(STATUS ${CUDAToolkit_INCLUDE_DIRS})
add_executable(test_nppi main.cu)
target_link_libraries(test_nppi ${OpenCV_LIBS} CUDA::nppig)
target_include_directories(test_nppi PUBLIC ${OpenCV_INCLUDE_DIRS} ${CUDAToolkit_INCLUDE_DIRS})
set_target_properties(test_nppi PROPERTIES
CUDA_SEPARABLE_COMPILATION ON)
我之前对单 channel 图片使用过nppi调整大小功能,但没有出现这个问题。 3 channel nppi resize 函数的输出很奇怪,我想我没有完全理解输入参数。由于有3个颜色 channel ,Step乘以3,但所有其他尺寸只是以像素为单位测量尺寸;并且 src 和 destination 的大小相同......不确定我在这里不理解什么。
最佳答案
问题是 mat.total()
等于像素总数,而不是字节总数。
根据 OpenCV documentation :
total () const
Returns the total number of array elements.
在您的代码示例中,mat.total()
等于 256*256
,而总字节数等于 256*256*3
(RGB 每个像素应用 3 个字节)。
(在 OpenCV 术语中,“数组元素”相当于图像像素)。
cudaMemcpy(gpuBuffer1, mat.data, mat.total()...
仅复制图像总字节数的 1/3,因此只有图像数据的上 1/3 有效.
根据 this post ,计算字节数的正确方法是:
size_t mat_size_in_bytes = mat.step[0] * mat.rows;
在大多数情况下,对于 CV_8UC3
,mat.step[0]
= mat.cols*3
,但要涵盖所有情况,我们最好使用 mat.step[0]
。
更正后的代码示例:
#include "nppi.h"
#include "nppi_geometry_transforms.h"
#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include <vector>
void write(const cv::Mat& mat1, const std::string& path) {
auto mat2 = cv::Mat(mat1.rows, mat1.cols, CV_8UC4);
for (int i = 0; i < mat1.rows; i++) {
for (int j = 0; j < mat1.cols; j++) {
auto& bgra = mat2.at<cv::Vec4b>(i, j);
auto& rgb = mat1.at<cv::Vec3b>(i, j);
bgra[0] = rgb[2];
bgra[1] = rgb[1];
bgra[2] = rgb[0];
bgra[3] = UCHAR_MAX;
}
}
std::vector<int> compression_params;
compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);
compression_params.push_back(9);
cv::imwrite(path, mat2, compression_params);
}
int main() {
std::cout << "Hello, World!" << std::endl;
auto mat = cv::Mat(256, 256, CV_8UC3);
auto mat2 = cv::Mat(mat.rows, mat.cols, CV_8UC3);
for (int i = 0; i < mat.rows; i++) {
for (int j = 0; j < mat.cols; j++) {
auto& rgb = mat.at<cv::Vec3b>(i, j);
rgb[0] = (uint8_t)j;
rgb[1] = (uint8_t)i;
rgb[2] = (uint8_t)(UCHAR_MAX - j);
}
}
write(mat, "./test.png");
uint8_t* gpuBuffer1;
uint8_t* gpuBuffer2;
size_t mat_size_in_bytes = mat.step[0] * mat.rows; // https://stackoverflow.com/questions/26441072/finding-the-size-in-bytes-of-cvmat
size_t mat2_size_in_bytes = mat2.step[0] * mat2.rows;
cudaMalloc(&gpuBuffer1, mat_size_in_bytes);
cudaMalloc(&gpuBuffer2, mat2_size_in_bytes);
cudaMemcpy(gpuBuffer1, mat.data, mat_size_in_bytes, cudaMemcpyHostToDevice);
NppiSize oSrcSize = { mat.cols, mat.rows };
NppiRect oSrcRectROI = { 0, 0, mat.cols, mat.rows };
NppiSize oDstSize = { mat2.cols, mat2.rows };
NppiRect oDstRectROI = { 0, 0, mat2.cols, mat2.rows };
auto status = nppiResize_8u_C3R(
gpuBuffer1, mat.step[0], oSrcSize,
oSrcRectROI, gpuBuffer2,
mat2.step[0], oDstSize,
oDstRectROI,
NPPI_INTER_NN);
if (status != NPP_SUCCESS) {
std::cerr << "Error executing Resize -- code: " << status << std::endl;
}
cudaMemcpy(mat2.data, gpuBuffer2, mat2_size_in_bytes, cudaMemcpyDeviceToHost);
write(mat2, "./test1.png");
}
关于c++ - 具有 3 个 channel 的 nppi 调整大小功能得到奇怪的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72588979/
我正在使用 OUTFILE 命令,但由于权限问题和安全风险,我想将 shell 的输出转储到文件中,但出现了一些错误。我试过的 #This is a simple shell to connect t
我刚刚开始学习 Java,我想克服在尝试为这个“问题”创建 Java 程序时出现的障碍。这是我必须创建一个程序来解决的问题: Tandy 喜欢分发糖果,但只有 n 颗糖果。对于她给第 i 个糖果的人,
你好,我想知道我是否可以得到一些帮助来解决我在 C++ 中打印出 vector 内容的问题 我试图以特定顺序在一个或两个函数调用中输出一个类的所有变量。但是我在遍历 vector 时收到一个奇怪的错误
我正在将 intellij (2019.1.1) 用于 java gradle (5.4.1) 项目,并使用 lombok (1.18.6) 来自动生成代码。 Intellij 将生成的源放在 out
编辑:在与 guest271314 交流后,我意识到问题的措辞(在我的问题正文中)可能具有误导性。我保留了旧版本并更好地改写了新版本 背景: 从远程服务器获取 JSON 时,响应 header 包含一
我的问题可能有点令人困惑。我遇到的问题是我正在使用来自 Java 的 StoredProcedureCall 调用过程,例如: StoredProcedureCall call = new Store
在我使用的一些IDL中,我注意到在方法中标记返回值有2个约定-[in, out]和[out, retval]。 当存在多个返回值时,似乎使用了[in, out],例如: HRESULT MyMetho
当我查看 gar -h 的帮助输出时,它告诉我: [...] gar: supported targets: elf64-x86-64 elf32-i386 a.out-i386-linux [...
我想循环遍历一个列表,并以 HTML 格式打印其中的一部分,以代码格式打印其中的一部分。所以更准确地说:我想产生与这相同的输出 1 is a great number 2 is a great
我有下面的tekton管道,并尝试在Google Cloud上运行。集群角色绑定。集群角色。该服务帐户具有以下权限。。例外。不确定需要为服务帐户设置什么权限。
当尝试从 make 过滤非常长的输出以获取特定警告或错误消息时,第一个想法是这样的: $ make | grep -i 'warning: someone set up us the bomb' 然而
我正在创建一个抽象工具类,该类对另一组外部类(不受我控制)进行操作。外部类在某些接口(interface)点概念上相似,但访问它们相似属性的语法不同。它们还具有不同的语法来应用工具操作的结果。我创建了
这个问题已经有答案了: What do numbers starting with 0 mean in python? (9 个回答) 已关闭 7 年前。 在我的代码中使用按位与运算符 (&) 时,我
我写了这段代码来解析输入文件中的行输入格式:电影 ID 可以有多个条目,所以我们应该计算平均值输出:**没有重复(这是问题所在) import re f = open("ratings2.txt",
我需要处理超过 1000 万个光谱数据集。数据结构如下:大约有 1000 个 .fits(.fits 是某种数据存储格式)文件,每个文件包含大约 600-1000 个光谱,其中每个光谱中有大约 450
我编写了一个简单的 C 程序,它读取一个文件并生成一个包含每个单词及其出现频率的表格。 该程序有效,我已经能够在 Linux 上运行的终端中获得显示的输出,但是,我不确定如何获得生成的显示以生成包含词
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
1.普通的输出: print(str)#str是任意一个字符串,数字··· 2.格式化输出: ?
我无法让 logstash 正常工作。 Basic logstash Example作品。但后来我与 Advanced Pipeline Example 作斗争.也许这也可能是 Elasticsear
这是我想要做的: 我想让用户给我的程序一些声音数据(通过麦克风输入),然后保持 250 毫秒,然后通过扬声器输出。 我已经使用 Java Sound API 做到了这一点。问题是它有点慢。从发出声音到
我是一名优秀的程序员,十分优秀!