前言
3519A nnie SDK只支持BGR以及yuv格式的数据输入。那么当手头刚好只有jpeg/png等图片文件时,怎么来进行目标识别呢?一般的思路是用opencv来读取图片文件,然后再转换成BGR/YUV等格式,最后扔到NNIE模块来进行深度学习推理。
BGR文件数据格式
nnie sample里面提供的测试图片有后缀名为bgr的文件,例如dog_bick_car.bgr。在sample code里面直接通过fopen fread之类C文件API来读取二进制数据到buffer,然后再调用nnie forward API进行图像识别。
可是实际应用中,拿到的图片往往是jpeg/png等格式,所以需要先调用opencv库函数进行转换。而要正确的转换,就先要知道bgr文件的数据格式,亦即GBG的排列顺序。下面代码就是将sample里面的bgr按bgrbgrbgr... ...格式重构成Mat类型,然后进行显示,看看显示跟预期是否一致。
FILE *fp;
fp = fopen("D:/work/dog_bike_car_416x416.bgr", "rb");
unsigned char img_data[416x416x3];
fread(img_data, 1, 416x416x3, fp);
fclose(fp);
Mat img = Mat(416, 416, CV_8UC3, img_data);
imshow("hello", img);
结果发现,显示不正确,如下所示:
后来,通过试验,发现它是按BBBB....GGGG....RRRR...排列的。其相应读取转换代码如下:
//img_data是按BBBB...GGGG...RRRR...排列的(bgr文件格式)
//img_data_conv按BGRBGRBGR... ...排列的(OPencv Mat排列格式)
unsigned char img_data[416 * 416 * 3], img_data_conv[416 * 416 * 3];
FILE *fp;
fp = fopen("D:/work/dog_bike_car_416x416.bgr", "rb");
int channels = 3;
int width = 416;
int height = 416;
fread(img_data, 1, width*height*channels, fp);
fclose(fp);
for (int h = 0; h < height; h++)
for (int w = 0; w < width; w++)
for (int c = 0; c < channels; c++)
{
img_data_conv[h * width * channels + w * channels + c] = img_data[(height * width) * c + h * width + w];
}
Mat img_test = Mat(width, height, CV_8UC3, img_data_conv);
imshow("hello", img_test);
其显示如下,是正确的。
小结
上面代码 写的比较粗糙,硬代码很多,也没考虑效率,大家理解就行。 此外,本文主要是通过实验来明确海思sample里面bgr文件的数据格式, 并没有提供bgrbgr...转换成b...g...r...代码,但是参考上面代码就应该很容易实现,说白了就是一逆过程。