该测试样例是进行手写数字识别,使用 Visual Studio 2022 打开 tensorRT安装目录下的 samples 下的 sampleOnnxMNIST 工程( 例如我的是 D:\install\tensorRT\TensorRT-8.6.1.6\samples\sampleOnnxMNIST ),执行输出结果:
成功识别出数字0,再测试一下:
成功识别出数字4,但是我想手动识别一个手写数字的图片呢?如何传参呢?也没找见可以传图片的地方呀?怎么办?一个方法是看官方文档,例如 readme什么的,如果英文不好,或者懒得翻阅文档,可以根据日志顺腾摸瓜找到入口,我们 看控制台每次都会输出字符串 "Input:" 和 Output:,这个肯定是程序中例如使用 cout输出的,直接在 文件 sampleOnnxMNIST.cpp 中全局搜索 "Input:":
稍加阅读便可发现,该方法的主要作用是:
bool SampleOnnxMNIST::processInput(const samplesCommon::BufferManager& buffers){
const int inputH = mInputDims.d[2];
const int inputW = mInputDims.d[3];
// Read a random digit file
// 读取一个随机数字文件
srand(unsigned(time(nullptr)));
std::vector<uint8_t> fileData(inputH * inputW);
// 计算一个随机的 0~9的数字
mNumber = rand() % 10;
// (locateFile(std::to_string(mNumber) + ".pgm", mParams.dataDirs) 的作用是 使用 文件夹集合
// mParams.dataDirs 和 一个文件名( 例如 1.pgm、2.pgm ...,这些文件其实在 D:\install\tensorRT\TensorRT-8.6.1.6\data\mnist 下 ) 来获取一个绝对文件路径
// 所以我们改造下,直接写死 D:/code/python_code/test_0001/test.pgm
// readPGMFile(locateFile(std::to_string(mNumber) + ".pgm", mParams.dataDirs), fileData.data(), inputH, inputW);
readPGMFile( "D:/code/python_code/test_0001/test.pgm", fileData.data(), inputH, inputW);
// Print an ascii representation
// 将数字文件以 ASCII 码的形式打印出来
sample::gLogInfo << "Input:" << std::endl;
for (int i = 0; i < inputH * inputW; i++){
// 遍历数字图片中的每个像素,将像素的值转换成 可见的 ASCII 码( 每读到一个宽度( 28 )个,就换行 ),
// 然后拼接到 sample::gLogInfo 中
// 由于控制台输出的 图片的 ASCII 的形式的宽比较窄,所以这里我加了一个空格,即 '? ""' 改为了 '? " "'
sample::gLogInfo << (" .:-=+*#%@"[fileData[i] / 26]) << (((i + 1) % inputW) ? " " : "\n");
}
// 将 sample::gLogInfo 整个打印出来,也就是看到的类似一个图片的 28x28的区域
sample::gLogInfo << std::endl;
float* hostDataBuffer = static_cast<float*>(buffers.getHostBuffer(mParams.inputTensorNames[0]));
for (int i = 0; i < inputH * inputW; i++){
hostDataBuffer[i] = 1.0 - float(fileData[i] / 255.0);
}
return true;
}
.pgm 是什么文件:
.pgm是Portable Gray Map(便携式灰度图)的缩写,是灰度图像格式中一种最简单的格式标准1。PGM文件的后缀名为“.pgm”,它由两部分数据组成,分别是文件头部分和像素数据部分。文件头部分包含了PGM文件的格式类型(P2或P5)、图像的宽度、图像的高度以及图像灰度值可能的最大值,这些信息都是以ASCII码形式存储的,因此可以直接用记事本打开查看1。
PGM格式图像分为P2和P5两种类型:
P2类型:每个像素用字符串表示,每个像素之间用空格分开,图像每一行结束时要换行。当数据超过一定长度(如70个字节),会自动换行。P2格式是可读的,可以直接用记事本打开1。
P5类型:每个像素用二进制表示,每个像素之间及两行数据之间都没有空格或其他间隔。用记事本打开P5格式的PGM文件可能会看到乱码1。
PGM格式是一种灰度图像的存储格式,适用于存储单通道的图像数据,特别在黑白超声图像系统中经常使用23。它既可以用记事本等文本编辑器查看文件头信息,也可以用ACDSee、Photoshop等软件查看图像内容1。此外,在OpenCV库与Python结合使用的背景下,通过拍照选区生成PGM图片格式的文件是一个常见的需求,特别是在人脸识别领域,用于收集和准备训练数据2。
我们打开 D:\install\tensorRT\TensorRT-8.6.1.6\data\mnist\1.pgm,发现是二进制形式的:
可以使用 python 将 图片文件转换为 .pgm 文件( 参考 windows环境 python + opencv 加载 onnx 人脸检测模型识别人脸测试 搭建 python + opencv 环境 )
image2pgm_test.py:
import cv2
# 读取图片并转换为灰度图像
img = cv2.imread('6.jpeg', cv2.IMREAD_GRAYSCALE)
# 保存为PGM格式
cv2.imwrite('test.pgm', img)
下载一张数字6的手写图片:
将像素尺寸修改为 28x28,然后执行 python image2pgm_test.py 生成了 test.pgm,再在 Visual Studio 2022 中运行 sampleOnnxMNIST:
可以看出识别成6的相似度最高
数字4的测试效果: