You need to sign in or sign up before continuing.
未验证 提交 6e8a5e62 编写于 作者: C cnn 提交者: GitHub

[Dygraph] Fix deploy python/cpp infer bugs (#2234)

* use scripts to build on windows flatform, test=dygraph

* Use new preproces OPs in deploy/infer.py, test=dygraph

* fix bug of image_shape can not set 2-dims, test=dygraph

* fix cpp build, test=dygraph

* set param target_size must be [h, w] in Resize function, test=dygraph

* fix bug, test=dygraph

* fix ssd output format (bbox: [N, 6], bbox_num: bbox_num), test=dygraph

* fix ssd prediction in cpp mode, test=dygraph
上级 a0348fdb
......@@ -47,24 +47,14 @@ fluid_inference
### Step4: 编译
#### 通过图形化操作编译CMake
1. 打开Visual Studio 2019 Community,点击`继续但无需代码`
![step2](https://paddleseg.bj.bcebos.com/inference/vs2019_step1.png)
2. 点击: `文件`->`打开`->`CMake`
![step2.1](https://paddleseg.bj.bcebos.com/inference/vs2019_step2.png)
选择项目代码所在路径,并打开`CMakeList.txt`
![step2.2](https://paddleseg.bj.bcebos.com/inference/vs2019_step3.png)
3. 点击:`项目`->`cpp_inference_demo的CMake设置`
![step3](https://paddleseg.bj.bcebos.com/inference/vs2019_step4.png)
1. 进入到`cpp`文件夹
```
cd D:\projects\PaddleDetection\deploy\cpp
```
4. 点击`浏览`,分别设置编译选项指定`CUDA``CUDNN_LIB``OpenCV``Paddle预测库`的路径
2. 使用CMake生成项目文件
三个编译参数的含义说明如下(带*表示仅在使用**GPU版本**预测库时指定, 其中CUDA库版本尽量对齐,**使用9.0、10.0版本,不使用9.2、10.1等版本CUDA库**):
编译参数的含义说明如下(带*表示仅在使用**GPU版本**预测库时指定, 其中CUDA库版本尽量对齐,**使用9.0、10.0版本,不使用9.2、10.1等版本CUDA库**):
| 参数名 | 含义 |
| ---- | ---- |
......@@ -75,23 +65,8 @@ fluid_inference
| USE_PADDLE_20RC1 | 是否使用2.0rc1预测库。如果使用2.0rc1,在windows环境下预测库名称发生变化,且仅支持动态库方式编译 |
**注意:** 1. 使用`CPU`版预测库,请把`WITH_GPU`的勾去掉 2. 如果使用的是`openblas`版本,请把`WITH_MKL`勾去掉
![step4](https://paddleseg.bj.bcebos.com/inference/vs2019_step5.png)
**设置完成后**, 点击上图中`保存并生成CMake缓存以加载变量`
5. 点击`生成`->`全部生成`
![step6](https://paddleseg.bj.bcebos.com/inference/vs2019_step6.png)
#### 通过命令行操作编译CMake
1. 进入到`cpp`文件夹
```
cd D:\projects\PaddleDetection\deploy\cpp
```
2. 使用CMake生成项目文件
执行如下命令项目文件:
```
cmake . -G "Visual Studio 16 2019" -A x64 -T host=x64 -DWITH_GPU=ON -DWITH_MKL=ON -DCMAKE_BUILD_TYPE=Release -DCUDA_LIB=path_to_cuda_lib -DCUDNN_LIB=path_to_cudnn_lib -DPADDLE_DIR=path_to_paddle_lib -DOPENCV_DIR=path_to_opencv
```
......@@ -102,7 +77,8 @@ cmake . -G "Visual Studio 16 2019" -A x64 -T host=x64 -DWITH_GPU=ON -DWITH_MKL=O
```
3. 编译
`Visual Studio 16 2019`打开`cpp`文件夹下的`PaddleObjectDetector.sln`,点击`生成`->`全部生成`
`Visual Studio 16 2019`打开`cpp`文件夹下的`PaddleObjectDetector.sln`,将编译模式设置为`Release`,点击`生成`->`全部生成
### Step5: 预测及可视化
......
......@@ -58,7 +58,7 @@ class InitInfo : public PreprocessOp{
virtual void Run(cv::Mat* im, ImageBlob* data);
};
class Normalize : public PreprocessOp {
class NormalizeImage : public PreprocessOp {
public:
virtual void Init(const YAML::Node& item, const std::vector<int> image_shape) {
mean_ = item["mean"].as<std::vector<float>>();
......@@ -133,13 +133,14 @@ class Preprocessor {
}
std::shared_ptr<PreprocessOp> CreateOp(const std::string& name) {
if (name == "ResizeOp") {
if (name == "Resize") {
return std::make_shared<Resize>();
} else if (name == "PermuteOp") {
} else if (name == "Permute") {
return std::make_shared<Permute>();
} else if (name == "NormalizeImageOp") {
return std::make_shared<Normalize>();
} else if (name == "PadBatchOp" || name == "PadStride") {
} else if (name == "NormalizeImage") {
return std::make_shared<NormalizeImage>();
} else if (name == "PadStride") {
// use PadStride instead of PadBatch
return std::make_shared<PadStride>();
}
std::cerr << "can not find function of OP: " << name << " and return: nullptr" << std::endl;
......
......@@ -131,7 +131,7 @@ void ObjectDetector::Postprocess(
result->clear();
int rh = 1;
int rw = 1;
if (config_.arch_ == "SSD" || config_.arch_ == "Face") {
if (config_.arch_ == "Face") {
rh = raw_mat.rows;
rw = raw_mat.cols;
}
......
......@@ -31,7 +31,7 @@ void InitInfo::Run(cv::Mat* im, ImageBlob* data) {
};
}
void Normalize::Run(cv::Mat* im, ImageBlob* data) {
void NormalizeImage::Run(cv::Mat* im, ImageBlob* data) {
double e = 1.0;
if (is_scale_) {
e /= 255.0;
......@@ -62,6 +62,10 @@ void Permute::Run(cv::Mat* im, ImageBlob* data) {
void Resize::Run(cv::Mat* im, ImageBlob* data) {
auto resize_scale = GenerateScale(*im);
data->input_shape_ = {
static_cast<int>(im->cols * resize_scale.first),
static_cast<int>(im->rows * resize_scale.second)
};
cv::resize(
*im, *im, cv::Size(), resize_scale.first, resize_scale.second, interp_);
data->im_shape_ = {
......@@ -72,24 +76,6 @@ void Resize::Run(cv::Mat* im, ImageBlob* data) {
resize_scale.second,
resize_scale.first,
};
if (keep_ratio_) {
int max_size = input_shape_[1];
// Padding the image with 0 border
cv::copyMakeBorder(
*im,
*im,
0,
max_size - im->rows,
0,
max_size - im->cols,
cv::BORDER_CONSTANT,
cv::Scalar(0));
}
data->input_shape_ = {
static_cast<int>(im->rows),
static_cast<int>(im->cols),
};
}
std::pair<float, float> Resize::GenerateScale(const cv::Mat& im) {
......@@ -145,7 +131,7 @@ void PadStride::Run(cv::Mat* im, ImageBlob* data) {
// Preprocessor op running order
const std::vector<std::string> Preprocessor::RUN_ORDER = {
"InitInfo", "ResizeOp", "NormalizeImageOp", "PadStrideOp", "PermuteOp"
"InitInfo", "Resize", "NormalizeImage", "PadStride", "Permute"
};
void Preprocessor::Run(cv::Mat* im, ImageBlob* data) {
......
......@@ -35,6 +35,7 @@ def decode_image(im_file, im_info):
else:
im = im_file
im_info['im_shape'] = np.array(im.shape[:2], dtype=np.float32)
im_info['scale_factor'] = np.array([1., 1.], dtype=np.float32)
return im, im_info
......@@ -66,8 +67,13 @@ class Resize(object):
im (np.ndarray): processed image (np.ndarray)
im_info (dict): info of processed image
"""
assert len(self.target_size) == 2
assert self.target_size[0] > 0 and self.target_size[1] > 0
im_channel = im.shape[2]
im_scale_y, im_scale_x = self.generate_scale(im)
# set image_shape
im_info['input_shape'][1] = int(im_scale_y * im.shape[0])
im_info['input_shape'][2] = int(im_scale_x * im.shape[1])
im = cv2.resize(
im,
None,
......@@ -78,14 +84,6 @@ class Resize(object):
im_info['im_shape'] = np.array(im.shape[:2]).astype('float32')
im_info['scale_factor'] = np.array(
[im_scale_y, im_scale_x]).astype('float32')
# padding im when image_shape fixed by infer_cfg.yml
if self.keep_ratio and im_info['input_shape'][1] is not None:
max_size = im_info['input_shape'][1]
padding_im = np.zeros(
(max_size, max_size, im_channel), dtype=np.float32)
im_h, im_w = im.shape[:2]
padding_im[:im_h, :im_w, :] = im
im = padding_im
return im, im_info
def generate_scale(self, im):
......@@ -174,7 +172,7 @@ class Permute(object):
class PadStride(object):
""" padding image for model with FPN
""" padding image for model with FPN , instead PadBatch(pad_to_stride, pad_gt) in original config
Args:
stride (bool): model with FPN need image shape % stride == 0
"""
......
......@@ -52,12 +52,6 @@ def _parse_reader(reader_cfg, dataset_cfg, metric, arch, image_shape):
for st in sample_transforms[1:]:
for key, value in st.items():
p = {'type': key}
if key == 'Resize':
if value.get('keep_ratio',
False) and image_shape[1] is not None:
max_size = max(image_shape[1:])
image_shape = [3, max_size, max_size]
value['target_size'] = image_shape[1:]
p.update(value)
preprocess_list.append(p)
batch_transforms = reader_cfg.get('batch_transforms', None)
......@@ -65,9 +59,10 @@ def _parse_reader(reader_cfg, dataset_cfg, metric, arch, image_shape):
methods = [list(bt.keys())[0] for bt in batch_transforms]
for bt in batch_transforms:
for key, value in bt.items():
# for deploy/infer, use PadStride(stride) instead PadBatch(pad_to_stride, pad_gt)
if key == 'PadBatch':
preprocess_list.append({'type': 'PadStride'})
preprocess_list[-1].update({
preprocess_list.append({
'type': 'PadStride',
'stride': value['pad_to_stride']
})
break
......
......@@ -360,8 +360,9 @@ class Trainer(object):
if 'inputs_def' in self.cfg['TestReader']:
inputs_def = self.cfg['TestReader']['inputs_def']
image_shape = inputs_def.get('image_shape', None)
# set image_shape=[3, -1, -1] as default
if image_shape is None:
image_shape = [3, None, None]
image_shape = [3, -1, -1]
self.model.eval()
......
......@@ -54,13 +54,8 @@ class SSD(BaseArch):
def get_pred(self):
bbox_pred, bbox_num = self._forward()
label = bbox_pred[:, 0]
score = bbox_pred[:, 1]
bbox = bbox_pred[:, 2:]
output = {
'bbox': bbox,
'score': score,
'label': label,
'bbox_num': bbox_num
"bbox": bbox_pred,
"bbox_num": bbox_num,
}
return output
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册