Commit 1eff8465 authored by liucong's avatar liucong
Browse files

修改代码

parent 8a0838dd
...@@ -37,6 +37,7 @@ link_libraries(${LIBRARY}) ...@@ -37,6 +37,7 @@ link_libraries(${LIBRARY})
# 添加源文件 # 添加源文件
set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Src/main.cpp set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Src/main.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Src/Classifier.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Src/Classifier.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/CommonUtility.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/Filesystem.cpp) ${CMAKE_CURRENT_SOURCE_DIR}/Src/Utility/Filesystem.cpp)
# 添加可执行目标 # 添加可执行目标
......
...@@ -16,13 +16,17 @@ ...@@ -16,13 +16,17 @@
在将数据输入到模型之前,需要对图像做如下预处理操作: 在将数据输入到模型之前,需要对图像做如下预处理操作:
- resize到224x224 - 图像格式转换,BGR转换为RGB
- 将像素值归一化到[0.0, 1.0]
- 转换数据排布为NCHW - 调整图像大小,并在中心窗口位置裁剪出224x224大小的图像
- normalize操作,对图像减均值再除方差
- 转换数据排布为NCHW
本示例代码采用了OpenCV的cv::dnn::blobFromImages()函数实现了预处理操作: 本示例代码主要采用了OpenCV实现了预处理操作:
```c++ ```c++
ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector<std::vector<ResultOfPrediction>> &predictions) ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector<std::vector<ResultOfPrediction>> &predictions)
...@@ -30,20 +34,46 @@ ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector ...@@ -30,20 +34,46 @@ ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector
... ...
// 预处理 // 预处理
std::vector<cv::Mat> image;
for(int i =0;i<srcImages.size();++i)
{
//BGR转换为RGB
cv::Mat imgRGB;
cv::cvtColor(srcImages[i], imgRGB, cv::COLOR_BGR2RGB);
// 调整大小,保持长宽比
cv::Mat shrink;
float ratio = (float)256 / min(imgRGB.cols, imgRGB.rows);
if(imgRGB.rows > imgRGB.cols)
{
cv::resize(imgRGB, shrink, cv::Size(256, int(ratio * imgRGB.rows)), 0, 0);
}
else
{
cv::resize(imgRGB, shrink, cv::Size(int(ratio * imgRGB.cols), 256), 0, 0);
}
// 裁剪中心窗口
int start_x = shrink.cols/2 - 224/2;
int start_y = shrink.rows/2 - 224/2;
cv::Rect rect(start_x, start_y, 224, 224);
cv::Mat images = shrink(rect);
image.push_back(images);
}
// normalize并转换为NCHW
cv::Mat inputBlob; cv::Mat inputBlob;
cv::dnn::blobFromImages(srcImages, // 输入数据,支持多张图像 Image2BlobParams image2BlobParams;
inputBlob, // 输出数据 image2BlobParams.scalefactor=cv::Scalar(1/58.395, 1/57.12, 1/57.375);
scale, // 缩放系数,这里为1/255.0 image2BlobParams.mean=cv::Scalar(123.675, 116.28, 103.53);
inputSize, // 模型输入大小,这里为28x28 image2BlobParams.swapRB=false;
meanValue, // 均值,这里不需要减均值,所以设置为0.0 blobFromImagesWithParams(image,inputBlob,image2BlobParams);
swapRB, // 多通道图像,这里设置为1
false);
... ...
} }
``` ```
cv::dnn::blobFromImages()函数支持多个输入图像,首先输入图像resize到inputSize,然后减去均值meanValue,最后乘以scale并转换为NCHW,最终将转换好的数据保存到inputBlob中,然后就可以输入到模型中执行推理了。 blobFromImagesWithParams()函数支持多个输入图像,首先输入图像各通道减对应的均值,然后乘以各通道对应的缩放系数,最后转换为NCHW,最终将转换好的数据保存到inputBlob中,然后就可以输入到模型中执行推理了。
......
...@@ -14,27 +14,52 @@ ...@@ -14,27 +14,52 @@
在将数据输入到模型之前,需要对图像做如下预处理操作: 在将数据输入到模型之前,需要对图像做如下预处理操作:
- 转换数据排布为NCHW - 图像格式转换,将BGR转换为RGB
- 将像素值归一化到[0.0, 1.0] - 调整图像大小,使短边为 256,长边等比例缩放
- 裁剪图像,在中心窗口位置裁剪出224x224大小的图像
- normalize操作,对图像减均值再除方差
- 调整输入数据的尺寸为(1, 3, 224, 224) - 调整输入数据的尺寸为(1, 3, 224, 224)
本示例代码采用了OpenCV实现了预处理操作: 本示例代码采用了OpenCV实现了预处理操作:
``` ```
def Preprocessing(pathOfImage): def Preprocessing(pathOfImage):
image = cv2.imread(pathOfImage,cv2.IMREAD_COLOR)
image = cv2.imread(pathOfImage, cv2.IMREAD_COLOR)
# 转换为RGB格式
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 调整图像的尺寸
image = cv2.resize(image, (224,224)) # 调整大小,保持长宽比
# 维度转换HWC->CHW ratio = float(256) / min(image.shape[0], image.shape[1])
if image.shape[0] > image.shape[1]:
new_size = [int(round(ratio * image.shape[0])), 256]
else:
new_size = [256, int(round(ratio * image.shape[1]))]
image = np.array(cv2.resize(image, (new_size[1],new_size[0]))) # w h 格式
# 裁剪中心窗口
h, w, c = image.shape
start_x = w//2 - 224//2
start_y = h//2 - 224//2
image = image[start_y:start_y+224, start_x:start_x+224, :]
# transpose
image = image.transpose(2, 0, 1) image = image.transpose(2, 0, 1)
# 维度拓展,增加batch维度
image = np.expand_dims(image, 0) # 将输入数据转换为float32
image = np.ascontiguousarray(image) img_data = image.astype('float32')
image = image.astype(np.float32)
# 归一化 # normalize
input = image / 255 mean_vec = np.array([123.675, 116.28, 103.53])
return input stddev_vec = np.array([58.395, 57.12, 57.375])
norm_img_data = np.zeros(img_data.shape).astype('float32')
for i in range(img_data.shape[0]):
norm_img_data[i,:,:] = (img_data[i,:,:] - mean_vec[i]) / stddev_vec[i]
# 调整输入数据的尺寸
norm_img_data = norm_img_data.reshape(1, 3, 224, 224).astype('float32')
return norm_img_data
``` ```
...@@ -61,12 +86,8 @@ if __name__ == '__main__': ...@@ -61,12 +86,8 @@ if __name__ == '__main__':
numberOfOutput=outputShape.elements() # 输出节点元素的个数 numberOfOutput=outputShape.elements() # 输出节点元素的个数
# 获取分类结果 # 获取分类结果
result=results[0].tolist() # 将migraphx.argument转换为list
result=np.array(result) result=np.array(result)
# 打印1000个类别的输出值
print(result)
``` ```
- Preprocessing()函数返回输入数据(numpy类型),然后通过{inputName: migraphx.argument(image)}构造一个字典输入模型执行推理,如果模型有多个输入,则在字典中需要添加多个输入数据。 - Preprocessing()函数返回输入数据(numpy类型),然后通过{inputName: migraphx.argument(image)}构造一个字典输入模型执行推理,如果模型有多个输入,则在字典中需要添加多个输入数据。
- model.run()返回模型的推理结果,返回结果是一个list类型,results[0]表示第一个输出节点的输出,是一个migraphx.argument类型,由于示例模型只有一个输出节点,所以results[0]对应resnetv24_dense0_fwd节点,如果想将migraphx.argument类型转换为list类型,可以通过tolist()方法实现。最后,打印出1000个类别的输出值 - model.run()返回模型的推理结果,返回结果是一个list类型,results[0]表示第一个输出节点的输出,是一个migraphx.argument类型,由于示例模型只有一个输出节点,所以results[0]对应resnetv24_dense0_fwd节点。最后,通过np.array(result)获取分类结果
...@@ -8,15 +8,40 @@ import numpy as np ...@@ -8,15 +8,40 @@ import numpy as np
import migraphx import migraphx
def Preprocessing(pathOfImage): def Preprocessing(pathOfImage):
image = cv2.imread(pathOfImage,cv2.IMREAD_COLOR) # cv2.IMREAD_COLOR:彩色图,cv2.IMREAD_GRAYSCALE:灰度图 # 读取图像
image = cv2.imread(pathOfImage, cv2.IMREAD_COLOR)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (224,224))
# 调整大小,使短边为256,保持长宽比
ratio = float(256) / min(image.shape[0], image.shape[1])
if image.shape[0] > image.shape[1]:
new_size = [int(round(ratio * image.shape[0])), 256]
else:
new_size = [256, int(round(ratio * image.shape[1]))]
image = np.array(cv2.resize(image, (new_size[1],new_size[0]))) # w h 格式
# 裁剪中心窗口为224*224
h, w, c = image.shape
start_x = w//2 - 224//2
start_y = h//2 - 224//2
image = image[start_y:start_y+224, start_x:start_x+224, :]
# transpose
image = image.transpose(2, 0, 1) image = image.transpose(2, 0, 1)
image = np.expand_dims(image, 0)
image = np.ascontiguousarray(image) # 将输入数据转换为float32
image = image.astype(np.float32) img_data = image.astype('float32')
input = image / 255
return input # normalize
mean_vec = np.array([123.675, 116.28, 103.53])
stddev_vec = np.array([58.395, 57.12, 57.375])
norm_img_data = np.zeros(img_data.shape).astype('float32')
for i in range(img_data.shape[0]):
norm_img_data[i,:,:] = (img_data[i,:,:] - mean_vec[i]) / stddev_vec[i]
# 调整尺寸
norm_img_data = norm_img_data.reshape(1, 3, 224, 224).astype('float32')
return norm_img_data
if __name__ == '__main__': if __name__ == '__main__':
# 加载模型 # 加载模型
...@@ -25,9 +50,6 @@ if __name__ == '__main__': ...@@ -25,9 +50,6 @@ if __name__ == '__main__':
inputShape=model.get_parameter_shapes()[inputName].lens() inputShape=model.get_parameter_shapes()[inputName].lens()
print("inputName:{0} \ninputShape:{1}".format(inputName,inputShape)) print("inputName:{0} \ninputShape:{1}".format(inputName,inputShape))
# FP16
# migraphx.quantize_fp16(model)
# 编译 # 编译
model.compile(t=migraphx.get_target("gpu"),device_id=0) # device_id: 设置GPU设备,默认为0号设备 model.compile(t=migraphx.get_target("gpu"),device_id=0) # device_id: 设置GPU设备,默认为0号设备
...@@ -45,8 +67,6 @@ if __name__ == '__main__': ...@@ -45,8 +67,6 @@ if __name__ == '__main__':
numberOfOutput=outputShape.elements() # 输出节点元素的个数 numberOfOutput=outputShape.elements() # 输出节点元素的个数
# 获取分类结果 # 获取分类结果
result=results[0].tolist() # 将migraphx.argument转换为list result=np.array(results[0])
result=np.array(result)
# 打印1000个类别的输出
print(result) print(result)
\ No newline at end of file
...@@ -8,21 +8,23 @@ ResNet50模型包含了49个卷积层、一个全连接层。 ...@@ -8,21 +8,23 @@ ResNet50模型包含了49个卷积层、一个全连接层。
## Python版本推理 ## Python版本推理
下面介绍如何运行python代码示例,具体推理代码解析,在Doc/Tutorial_Python.md中有详细说明 下面介绍如何运行Python代码示例,Python示例的详细说明见Doc目录下的Tutorial_Python.md。
### 拉取镜像 ### 下载镜像
在光源可拉取推理的docker镜像,ResNet50模型推理的镜像如下 在光源中下载MIGraphX镜像
```python ```python
docker pull image.sourcefind.cn:5000/dcu/admin/base/custom:ort1.14.0_migraphx3.0.0-dtk22.10.1 docker pull image.sourcefind.cn:5000/dcu/admin/base/custom:ort1.14.0_migraphx3.0.0-dtk22.10.1
``` ```
### 推理示例 ### 设置Python环境变量
1.参考《MIGraphX教程》设置好PYTHONPATH ```
export PYTHONPATH=/opt/dtk/lib:$PYTHONPATH
```
2.安装依赖 ### 安装依赖
```python ```python
# 进入resnet50 migraphx工程根目录 # 进入resnet50 migraphx工程根目录
...@@ -35,7 +37,9 @@ cd Python/ ...@@ -35,7 +37,9 @@ cd Python/
pip install -r requirements.txt pip install -r requirements.txt
``` ```
3.在Python目录下执行如下命令运行该示例程序: ### 运行示例
在Python目录下执行如下命令运行该示例程序:
```python ```python
python Classifier.py python Classifier.py
...@@ -44,18 +48,24 @@ python Classifier.py ...@@ -44,18 +48,24 @@ python Classifier.py
输出结果中,每个值分别对应每个label的输出值。 输出结果中,每个值分别对应每个label的输出值。
``` ```
[ 1.25075293e+00 1.78420877e+00 -2.56109548e+00 -3.44433069e+00 [-2.07137913e-02 2.25237548e-01 -1.98313940e+00 -2.97359991e+00
-2.66113567e+00 1.52841401e+00 7.93735325e-01 -1.26759931e-02 -1.61100197e+00 4.24269080e-01 -9.02939081e-01 1.21229446e+00
... ...
4.39746976e-02 3.43239784e-01 2.75328755e+00 1.70684290e+00 -2.69769251e-01 -4.28011447e-01 1.25102985e+00 9.06333506e-01
8.54880095e-01 2.12219620e+00 2.35758686e+00 -1.06204104e+00] -1.08657002e-01 3.15954179e-01 1.94901276e+00 -5.70572793e-01]
``` ```
## C++版本推理 ## C++版本推理
下面介绍如何运行C++代码示例,具体推理代码解析,在Doc/Tutorial_Cpp.md目录中有详细说明。 下面介绍如何运行C++代码示例,C++示例的详细说明见Doc目录下的Tutorial_Cpp.md。
### 下载镜像
在光源中下载MIGraphX镜像:
参考Python版本推理中的构建安装,在光源中拉取推理的docker镜像。 ```
docker pull image.sourcefind.cn:5000/dcu/admin/base/custom:ort1.14.0_migraphx3.0.0-dtk22.10.1
```
### 安装Opencv依赖 ### 安装Opencv依赖
...@@ -66,10 +76,8 @@ sh ./3rdParty/InstallOpenCVDependences.sh ...@@ -66,10 +76,8 @@ sh ./3rdParty/InstallOpenCVDependences.sh
### 修改CMakeLists.txt ### 修改CMakeLists.txt
- 如果使用ubuntu系统,需要修改CMakeLists.txt中依赖库路径: 如果使用ubuntu系统,需要修改CMakeLists.txt中依赖库路径:
将"${CMAKE_CURRENT_SOURCE_DIR}/depend/lib64/"修改为"${CMAKE_CURRENT_SOURCE_DIR}/depend/lib/" 将"${CMAKE_CURRENT_SOURCE_DIR}/depend/lib64/"修改为"${CMAKE_CURRENT_SOURCE_DIR}/depend/lib/"
- **MIGraphX2.3.0及以上版本需要c++17**
### 安装OpenCV并构建工程 ### 安装OpenCV并构建工程
...@@ -100,9 +108,7 @@ export LD_LIBRARY_PATH=<path_to_resnet50_migraphx>/depend/lib/:$LD_LIBRARY_PATH ...@@ -100,9 +108,7 @@ export LD_LIBRARY_PATH=<path_to_resnet50_migraphx>/depend/lib/:$LD_LIBRARY_PATH
source ~/.bashrc source ~/.bashrc
``` ```
### 推理示例 ### 运行示例
运行ResNet50示例程序,具体执行如下命令:
```python ```python
# 进入resnet50 migraphx工程根目录 # 进入resnet50 migraphx工程根目录
...@@ -118,23 +124,23 @@ cd ./build/ ...@@ -118,23 +124,23 @@ cd ./build/
输出结果中,每个值分别对应每个label的输出值。 输出结果中,每个值分别对应每个label的输出值。
``` ```
label:0,confidence:1.250770 label:0,confidence:-0.020714
label:1,confidence:1.784038 label:1,confidence:0.225238
label:2,confidence:-2.561039 label:2,confidence:-1.983140
label:3,confidence:-3.444281 label:3,confidence:-2.973601
label:4,confidence:-2.661026 label:4,confidence:-1.611002
label:5,confidence:1.528260 label:5,confidence:0.424268
... ...
label:995,confidence:1.706820 label:995,confidence:0.906333
label:996,confidence:0.854793 label:996,confidence:-0.108658
label:997,confidence:2.121985 label:997,confidence:0.315955
label:998,confidence:2.357481 label:998,confidence:1.949013
label:999,confidence:-1.062007 label:999,confidence:-0.570573
``` ```
## 历史版本 ## 历史版本
https://developer.hpccube.com/codes/modelzoo/classifier_migraphx https://developer.hpccube.com/codes/modelzoo/resnet50_migraphx
## 参考资料 ## 参考资料
......
<?xml version="1.0" encoding="GB2312"?> <?xml version="1.0" encoding="GB2312"?>
<opencv_storage> <opencv_storage>
<!--分类器--> <!--分类器-->
<Classifier> <Classifier>
<ModelPath>"../Resource/Models/resnet50-v2-7.onnx"</ModelPath> <ModelPath>"../Resource/Models/resnet50-v2-7.onnx"</ModelPath>
<Scale>0.003922</Scale><!--缩放尺度-->
<MeanValue1>0.0</MeanValue1><!--均值-->
<MeanValue2>0.0</MeanValue2>
<MeanValue3>0.0</MeanValue3>
<SwapRB>1</SwapRB>
<Crop>0</Crop>
<UseInt8>0</UseInt8><!--是否使用int8,不支持--> <UseInt8>0</UseInt8><!--是否使用int8,不支持-->
<UseFP16>0</UseFP16><!--是否使用FP16--> <UseFP16>0</UseFP16><!--是否使用FP16-->
</Classifier> </Classifier>
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <Filesystem.h> #include <Filesystem.h>
#include <SimpleLog.h> #include <SimpleLog.h>
#include <algorithm>
#include <CommonUtility.h>
namespace migraphxSamples namespace migraphxSamples
{ {
...@@ -38,12 +40,6 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat ...@@ -38,12 +40,6 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat
// 获取配置文件参数 // 获取配置文件参数
cv::FileNode netNode = configurationFile["Classifier"]; cv::FileNode netNode = configurationFile["Classifier"];
std::string modelPath=(std::string)netNode["ModelPath"]; std::string modelPath=(std::string)netNode["ModelPath"];
scale=(float)netNode["Scale"];
meanValue.val[0]=(float)netNode["MeanValue1"];
meanValue.val[1]=(float)netNode["MeanValue2"];
meanValue.val[2]=(float)netNode["MeanValue3"];
swapRB=(bool)(int)netNode["SwapRB"];
crop=(bool)(int)netNode["Crop"];
useInt8=(bool)(int)netNode["UseInt8"]; useInt8=(bool)(int)netNode["UseInt8"];
useFP16=(bool)(int)netNode["UseFP16"]; useFP16=(bool)(int)netNode["UseFP16"];
...@@ -79,14 +75,43 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat ...@@ -79,14 +75,43 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat
{ {
srcImages.push_back(srcImage); srcImages.push_back(srcImage);
} }
// 数据预处理
std::vector<cv::Mat> image;
for(int i =0;i<srcImages.size();++i)
{
//BGR转换为RGB
cv::Mat imgRGB;
cv::cvtColor(srcImages[i], imgRGB, cv::COLOR_BGR2RGB);
// 调整大小,使短边为256,保持长宽比
cv::Mat shrink;
float ratio = (float)256 / min(imgRGB.cols, imgRGB.rows);
if(imgRGB.rows > imgRGB.cols)
{
cv::resize(imgRGB, shrink, cv::Size(256, int(ratio * imgRGB.rows)), 0, 0);
}
else
{
cv::resize(imgRGB, shrink, cv::Size(int(ratio * imgRGB.cols), 256), 0, 0);
}
// 裁剪中心窗口为224*224
int start_x = shrink.cols/2 - 224/2;
int start_y = shrink.rows/2 - 224/2;
cv::Rect rect(start_x, start_y, 224, 224);
cv::Mat images = shrink(rect);
image.push_back(images);
}
// normalize并转换为NCHW
cv::Mat inputBlob; cv::Mat inputBlob;
cv::dnn::blobFromImages(srcImages, Image2BlobParams image2BlobParams;
inputBlob, image2BlobParams.scalefactor=cv::Scalar(1/58.395, 1/57.12, 1/57.375);
scale, image2BlobParams.mean=cv::Scalar(123.675, 116.28, 103.53);
inputSize, image2BlobParams.swapRB=false;
meanValue, blobFromImagesWithParams(image,inputBlob,image2BlobParams);
swapRB,
false);
std::unordered_map<std::string, migraphx::argument> inputData; std::unordered_map<std::string, migraphx::argument> inputData;
inputData[inputName]= migraphx::argument{inputShape, (float*)inputBlob.data}; inputData[inputName]= migraphx::argument{inputShape, (float*)inputBlob.data};
std::vector<std::unordered_map<std::string, migraphx::argument>> calibrationData = {inputData}; std::vector<std::unordered_map<std::string, migraphx::argument>> calibrationData = {inputData};
...@@ -114,10 +139,6 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat ...@@ -114,10 +139,6 @@ ErrorCode Classifier::Initialize(InitializationParameterOfClassifier initializat
// log // log
LOG_INFO(stdout,"InputSize:%dx%d\n",inputSize.width,inputSize.height); LOG_INFO(stdout,"InputSize:%dx%d\n",inputSize.width,inputSize.height);
LOG_INFO(stdout,"InputName:%s\n",inputName.c_str()); LOG_INFO(stdout,"InputName:%s\n",inputName.c_str());
LOG_INFO(stdout,"Scale:%.6f\n",scale);
LOG_INFO(stdout,"Mean:%.2f,%.2f,%.2f\n",meanValue.val[0],meanValue.val[1],meanValue.val[2]);
LOG_INFO(stdout,"SwapRB:%d\n",(int)swapRB);
LOG_INFO(stdout,"Crop:%d\n",(int)crop);
LOG_INFO(stdout,"UseInt8:%d\n",(int)useInt8); LOG_INFO(stdout,"UseInt8:%d\n",(int)useInt8);
LOG_INFO(stdout,"UseFP16:%d\n",(int)useFP16); LOG_INFO(stdout,"UseFP16:%d\n",(int)useFP16);
...@@ -133,15 +154,41 @@ ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector ...@@ -133,15 +154,41 @@ ErrorCode Classifier::Classify(const std::vector<cv::Mat> &srcImages,std::vector
return IMAGE_ERROR; return IMAGE_ERROR;
} }
// 数据预处理并转换为NCHW // 数据预处理
std::vector<cv::Mat> image;
for(int i =0;i<srcImages.size();++i)
{
//BGR转换为RGB
cv::Mat imgRGB;
cv::cvtColor(srcImages[i], imgRGB, cv::COLOR_BGR2RGB);
// 调整大小,使短边为256,保持长宽比
cv::Mat shrink;
float ratio = (float)256 / min(imgRGB.cols, imgRGB.rows);
if(imgRGB.rows > imgRGB.cols)
{
cv::resize(imgRGB, shrink, cv::Size(256, int(ratio * imgRGB.rows)), 0, 0);
}
else
{
cv::resize(imgRGB, shrink, cv::Size(int(ratio * imgRGB.cols), 256), 0, 0);
}
// 裁剪中心窗口为224*224
int start_x = shrink.cols/2 - 224/2;
int start_y = shrink.rows/2 - 224/2;
cv::Rect rect(start_x, start_y, 224, 224);
cv::Mat images = shrink(rect);
image.push_back(images);
}
// normalize并转换为NCHW
cv::Mat inputBlob; cv::Mat inputBlob;
cv::dnn::blobFromImages(srcImages, Image2BlobParams image2BlobParams;
inputBlob, image2BlobParams.scalefactor=cv::Scalar(1/58.395, 1/57.12, 1/57.375);
scale, image2BlobParams.mean=cv::Scalar(123.675, 116.28, 103.53);
inputSize, image2BlobParams.swapRB=false;
meanValue, blobFromImagesWithParams(image,inputBlob,image2BlobParams);
swapRB,
false);
// 创建输入数据 // 创建输入数据
std::unordered_map<std::string, migraphx::argument> inputData; std::unordered_map<std::string, migraphx::argument> inputData;
......
...@@ -27,10 +27,6 @@ private: ...@@ -27,10 +27,6 @@ private:
std::string inputName; std::string inputName;
migraphx::shape inputShape; migraphx::shape inputShape;
float scale;
cv::Scalar meanValue;
bool swapRB;
bool crop;
bool useInt8; bool useInt8;
bool useFP16; bool useFP16;
......
...@@ -15,7 +15,7 @@ namespace migraphxSamples ...@@ -15,7 +15,7 @@ namespace migraphxSamples
#define PATH_SEPARATOR '/' #define PATH_SEPARATOR '/'
#endif #endif
#define CONFIG_FILE "../Resource/Configuration.xml" #define CONFIG_FILE "../Resource/Configuration.xml"
typedef enum _ErrorCode typedef enum _ErrorCode
{ {
...@@ -35,18 +35,6 @@ typedef struct _ResultOfPrediction ...@@ -35,18 +35,6 @@ typedef struct _ResultOfPrediction
}ResultOfPrediction; }ResultOfPrediction;
typedef struct _ResultOfDetection
{
cv::Rect boundingBox;
float confidence;
int classID;
std::string className;
bool exist;
_ResultOfDetection():confidence(0.0f),classID(0),exist(true){}
}ResultOfDetection;
typedef struct _InitializationParameterOfClassifier typedef struct _InitializationParameterOfClassifier
{ {
std::string parentPath; std::string parentPath;
......
#include <CommonUtility.h>
using namespace cv;
using namespace cv::dnn;
namespace migraphxSamples
{
void blobFromImagesWithParams(InputArrayOfArrays images_, OutputArray blob_, const Image2BlobParams& param)
{
if (images_.kind() != _InputArray::STD_VECTOR_MAT && images_.kind() != _InputArray::STD_ARRAY_MAT &&
images_.kind() != _InputArray::STD_VECTOR_VECTOR) {
String error_message = "The data is expected as vectors of vectors or vectors of matrices.";
CV_Error(Error::StsBadArg, error_message);
}
CV_CheckType(param.ddepth, param.ddepth == CV_32F || param.ddepth == CV_8U,
"Blob depth should be CV_32F or CV_8U");
Size size = param.size;
std::vector<Mat> images;
images_.getMatVector(images);
CV_Assert(!images.empty());
int nch = images[0].channels();
Scalar scalefactor = param.scalefactor;
if (param.ddepth == CV_8U)
{
CV_Assert(scalefactor == Scalar::all(1.0) && "Scaling is not supported for CV_8U blob depth");
CV_Assert(param.mean == Scalar() && "Mean subtraction is not supported for CV_8U blob depth");
}
for (size_t i = 0; i < images.size(); i++)
{
Size imgSize = images[i].size();
if (size == Size())
size = imgSize;
if (size != imgSize)
{
if (param.paddingmode == DNN_PMODE_CROP_CENTER)
{
float resizeFactor = std::max(size.width / (float)imgSize.width,
size.height / (float)imgSize.height);
resize(images[i], images[i], Size(), resizeFactor, resizeFactor, INTER_LINEAR);
Rect crop(Point(0.5 * (images[i].cols - size.width),
0.5 * (images[i].rows - size.height)),
size);
images[i] = images[i](crop);
}
else
{
if (param.paddingmode == DNN_PMODE_LETTERBOX)
{
float resizeFactor = std::min(size.width / (float)imgSize.width,
size.height / (float)imgSize.height);
int rh = int(imgSize.height * resizeFactor);
int rw = int(imgSize.width * resizeFactor);
resize(images[i], images[i], Size(rw, rh), INTER_LINEAR);
int top = (size.height - rh)/2;
int bottom = size.height - top - rh;
int left = (size.width - rw)/2;
int right = size.width - left - rw;
copyMakeBorder(images[i], images[i], top, bottom, left, right, BORDER_CONSTANT);
}
else
resize(images[i], images[i], size, 0, 0, INTER_LINEAR);
}
}
Scalar mean = param.mean;
if (param.swapRB)
{
std::swap(mean[0], mean[2]);
std::swap(scalefactor[0], scalefactor[2]);
}
if (images[i].depth() == CV_8U && param.ddepth == CV_32F)
images[i].convertTo(images[i], CV_32F);
images[i] -= mean;
multiply(images[i], scalefactor, images[i]);
}
size_t nimages = images.size();
Mat image0 = images[0];
CV_Assert(image0.dims == 2);
if (param.datalayout == DNN_LAYOUT_NCHW)
{
if (nch == 3 || nch == 4)
{
int sz[] = { (int)nimages, nch, image0.rows, image0.cols };
blob_.create(4, sz, param.ddepth);
Mat blob = blob_.getMat();
Mat ch[4];
for (size_t i = 0; i < nimages; i++)
{
const Mat& image = images[i];
CV_Assert(image.depth() == blob_.depth());
nch = image.channels();
CV_Assert(image.dims == 2 && (nch == 3 || nch == 4));
CV_Assert(image.size() == image0.size());
for (int j = 0; j < nch; j++)
ch[j] = Mat(image.rows, image.cols, param.ddepth, blob.ptr((int)i, j));
if (param.swapRB)
std::swap(ch[0], ch[2]);
split(image, ch);
}
}
else
{
CV_Assert(nch == 1);
int sz[] = { (int)nimages, 1, image0.rows, image0.cols };
blob_.create(4, sz, param.ddepth);
Mat blob = blob_.getMat();
for (size_t i = 0; i < nimages; i++)
{
const Mat& image = images[i];
CV_Assert(image.depth() == blob_.depth());
nch = image.channels();
CV_Assert(image.dims == 2 && (nch == 1));
CV_Assert(image.size() == image0.size());
image.copyTo(Mat(image.rows, image.cols, param.ddepth, blob.ptr((int)i, 0)));
}
}
}
else if (param.datalayout == DNN_LAYOUT_NHWC)
{
int sz[] = { (int)nimages, image0.rows, image0.cols, nch};
blob_.create(4, sz, param.ddepth);
Mat blob = blob_.getMat();
int subMatType = CV_MAKETYPE(param.ddepth, nch);
for (size_t i = 0; i < nimages; i++)
{
const Mat& image = images[i];
CV_Assert(image.depth() == blob_.depth());
CV_Assert(image.channels() == image0.channels());
CV_Assert(image.size() == image0.size());
if (param.swapRB)
{
Mat tmpRB;
cvtColor(image, tmpRB, COLOR_BGR2RGB);
tmpRB.copyTo(Mat(tmpRB.rows, tmpRB.cols, subMatType, blob.ptr((int)i, 0)));
}
else
image.copyTo(Mat(image.rows, image.cols, subMatType, blob.ptr((int)i, 0)));
}
}
else
CV_Error(Error::StsUnsupportedFormat, "Unsupported data layout in blobFromImagesWithParams function.");
}
}
// 常用工具
#ifndef __COMMON_UTILITY_H__
#define __COMMON_UTILITY_H__
#include <CommonDefinition.h>
using namespace cv;
using namespace cv::dnn;
namespace migraphxSamples
{
enum DataLayout
{
DNN_LAYOUT_UNKNOWN = 0,
DNN_LAYOUT_ND = 1, //!< OpenCV data layout for 2D data.
DNN_LAYOUT_NCHW = 2, //!< OpenCV data layout for 4D data.
DNN_LAYOUT_NCDHW = 3, //!< OpenCV data layout for 5D data.
DNN_LAYOUT_NHWC = 4, //!< Tensorflow-like data layout for 4D data.
DNN_LAYOUT_NDHWC = 5, //!< Tensorflow-like data layout for 5D data.
DNN_LAYOUT_PLANAR = 6, //!< Tensorflow-like data layout, it should only be used at tf or tflite model parsing.
};
enum ImagePaddingMode
{
DNN_PMODE_NULL = 0, // !< Default. Resize to required input size without extra processing.
DNN_PMODE_CROP_CENTER = 1, // !< Image will be cropped after resize.
DNN_PMODE_LETTERBOX = 2, // !< Resize image to the desired size while preserving the aspect ratio of original image.
};
struct Image2BlobParams
{
Image2BlobParams():scalefactor(Scalar::all(1.0)), size(Size()), mean(Scalar()), swapRB(false), ddepth(CV_32F),
datalayout(DNN_LAYOUT_NCHW), paddingmode(DNN_PMODE_NULL)
{}
Image2BlobParams(const Scalar& scalefactor_, const Size& size_, const Scalar& mean_, bool swapRB_,
int ddepth_, DataLayout datalayout_, ImagePaddingMode mode_):
scalefactor(scalefactor_), size(size_), mean(mean_), swapRB(swapRB_), ddepth(ddepth_),
datalayout(datalayout_), paddingmode(mode_)
{}
Scalar scalefactor; //!< scalefactor multiplier for input image values.
Size size; //!< Spatial size for output image.
Scalar mean; //!< Scalar with mean values which are subtracted from channels.
bool swapRB; //!< Flag which indicates that swap first and last channels
int ddepth; //!< Depth of output blob. Choose CV_32F or CV_8U.
DataLayout datalayout; //!< Order of output dimensions. Choose DNN_LAYOUT_NCHW or DNN_LAYOUT_NHWC.
ImagePaddingMode paddingmode; //!< Image padding mode. @see ImagePaddingMode.
};
void blobFromImagesWithParams(InputArrayOfArrays images_, OutputArray blob_, const Image2BlobParams& param);
}
#endif
...@@ -43,12 +43,12 @@ int main() ...@@ -43,12 +43,12 @@ int main()
for(int i=0;i<predictions.size();++i) for(int i=0;i<predictions.size();++i)
{ {
// 一个batch中第i幅图像的结果 // 一个batch中第i幅图像的结果
printf("========== %d result ==========\n",i); LOG_INFO(stdout,"========== %d result ==========\n",i);
std::vector<migraphxSamples::ResultOfPrediction> resultOfPredictions=predictions[i]; std::vector<migraphxSamples::ResultOfPrediction> resultOfPredictions=predictions[i];
for(int j=0;j<resultOfPredictions.size();++j) for(int j=0;j<resultOfPredictions.size();++j)
{ {
migraphxSamples::ResultOfPrediction prediction=resultOfPredictions[j]; migraphxSamples::ResultOfPrediction prediction=resultOfPredictions[j];
printf("label:%d,confidence:%f\n",prediction.label,prediction.confidence); LOG_INFO(stdout,"label:%d,confidence:%f\n",prediction.label,prediction.confidence);
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment