Skip to content
Snippets Groups Projects
Commit 51ac0f53 authored by shibo19's avatar shibo19
Browse files

同步yolov4/edsr模型至master

parent 5a62d07d
No related branches found
No related tags found
No related merge requests found
Showing
with 2422 additions and 22 deletions
......@@ -29,11 +29,6 @@ input_air_path=$1
aipp_cfg_file=$2
output_om_path=$3
export install_path=/usr/local/Ascend/
export ASCEND_ATC_PATH=${install_path}/atc
export ASCEND_SLOG_PRINT_TO_STDOUT=1
echo "Input AIR file path: ${input_air_path}"
echo "Output OM file path: ${output_om_path}"
......
......@@ -24,6 +24,14 @@
#include "acl/acl.h"
namespace localParameter {
const uint32_t VECTOR_FIRST_INDEX = 0;
const uint32_t VECTOR_SECOND_INDEX = 1;
const uint32_t VECTOR_THIRD_INDEX = 2;
const uint32_t VECTOR_FOURTH_INDEX = 3;
const uint32_t VECTOR_FIFTH_INDEX = 4;
}
namespace {
// Output Tensor
const int OUTPUT_TENSOR_SIZE = 4;
......@@ -133,39 +141,45 @@ bool MaskRcnnMindsporePost::IsValidTensors(const std::vector<TensorBase> &tensor
}
uint32_t total_num = classNum_ * rpnMaxNum_;
if (bboxShape[VECTOR_SECOND_INDEX] != total_num) {
LogError << "The output tensor is mismatched: " << total_num << "/" << bboxShape[VECTOR_SECOND_INDEX] << ").";
if (bboxShape[localParameter::VECTOR_SECOND_INDEX] != total_num) {
LogError << "The output tensor is mismatched: " << total_num << "/"
<< bboxShape[localParameter::VECTOR_SECOND_INDEX] << ").";
return false;
}
if (bboxShape[VECTOR_THIRD_INDEX] != OUTPUT_BBOX_TWO_INDEX_SHAPE) {
LogError << "The number of bbox[" << VECTOR_THIRD_INDEX << "] dimensions (" << bboxShape[VECTOR_THIRD_INDEX]
if (bboxShape[localParameter::VECTOR_THIRD_INDEX] != OUTPUT_BBOX_TWO_INDEX_SHAPE) {
LogError << "The number of bbox[" << localParameter::VECTOR_THIRD_INDEX << "] dimensions ("
<< bboxShape[localParameter::VECTOR_THIRD_INDEX]
<< ") is not equal to (" << OUTPUT_BBOX_TWO_INDEX_SHAPE << ")";
return false;
}
auto classShape = tensors[OUTPUT_CLASS_INDEX].GetShape();
if (classShape[VECTOR_SECOND_INDEX] != total_num) {
LogError << "The output tensor is mismatched: (" << total_num << "/" << classShape[VECTOR_SECOND_INDEX]
if (classShape[localParameter::VECTOR_SECOND_INDEX] != total_num) {
LogError << "The output tensor is mismatched: (" << total_num << "/"
<< classShape[localParameter::VECTOR_SECOND_INDEX]
<< "). ";
return false;
}
auto maskShape = tensors[OUTPUT_MASK_INDEX].GetShape();
if (maskShape[VECTOR_SECOND_INDEX] != total_num) {
LogError << "The output tensor is mismatched: (" << total_num << "/" << maskShape[VECTOR_SECOND_INDEX] << ").";
if (maskShape[localParameter::VECTOR_SECOND_INDEX] != total_num) {
LogError << "The output tensor is mismatched: (" << total_num << "/"
<< maskShape[localParameter::VECTOR_SECOND_INDEX] << ").";
return false;
}
auto maskAreaShape = tensors[OUTPUT_MASK_AREA_INDEX].GetShape();
if (maskAreaShape[VECTOR_SECOND_INDEX] != total_num) {
LogError << "The output tensor is mismatched: (" << total_num << "/" << maskAreaShape[VECTOR_SECOND_INDEX]
if (maskAreaShape[localParameter::VECTOR_SECOND_INDEX] != total_num) {
LogError << "The output tensor is mismatched: (" << total_num << "/"
<< maskAreaShape[localParameter::VECTOR_SECOND_INDEX]
<< ").";
return false;
}
if (maskAreaShape[VECTOR_THIRD_INDEX] != maskSize_) {
LogError << "The output tensor of mask is mismatched: (" << maskAreaShape[VECTOR_THIRD_INDEX] << "/"
if (maskAreaShape[localParameter::VECTOR_THIRD_INDEX] != maskSize_) {
LogError << "The output tensor of mask is mismatched: ("
<< maskAreaShape[localParameter::VECTOR_THIRD_INDEX] << "/"
<< maskSize_ << ").";
return false;
}
......@@ -186,8 +200,8 @@ static void GetDetectBoxesTopK(std::vector<MxBase::DetectBox> &detBoxes, size_t
detBoxes.erase(detBoxes.begin() + kVal, detBoxes.end());
}
void MaskRcnnMindsporePost::GetValidDetBoxes(const std::vector<TensorBase> &tensors, std::vector<DetectBox> &detBoxes,
const uint32_t batchNum) {
void MaskRcnnMindsporePost::GetValidDetBoxes(const std::vector<TensorBase> &tensors,
std::vector<DetectBox> &detBoxes, const uint32_t batchNum) {
LogInfo << "Begin to GetValidDetBoxes Mask GetValidDetBoxes.";
auto *bboxPtr = reinterpret_cast<aclFloat16 *>(GetBuffer(tensors[OUTPUT_BBOX_INDEX], batchNum));
auto *labelPtr = reinterpret_cast<int32_t *>(GetBuffer(tensors[OUTPUT_CLASS_INDEX], batchNum));
......@@ -228,8 +242,8 @@ APP_ERROR MaskRcnnMindsporePost::GetMaskSize(const ObjectInfo &objInfo, const Re
int width = static_cast<int>(objInfo.x1 - objInfo.x0 + 1);
int height = static_cast<int>(objInfo.y1 - objInfo.y0 + 1);
if (width < 1 || height < 1) {
LogError << "The mask bbox is invalid, will be ignored, bboxWidth: " << width << ", bboxHeight: " << height
<< ".";
LogError << "The mask bbox is invalid, will be ignored, bboxWidth: " <<
width << ", bboxHeight: " << height << ".";
return APP_ERR_COMM_FAILURE;
}
......@@ -238,7 +252,8 @@ APP_ERROR MaskRcnnMindsporePost::GetMaskSize(const ObjectInfo &objInfo, const Re
return APP_ERR_OK;
}
APP_ERROR MaskRcnnMindsporePost::MaskPostProcess(ObjectInfo &objInfo, void *maskPtr, const ResizedImageInfo &imgInfo) {
APP_ERROR MaskRcnnMindsporePost::MaskPostProcess(ObjectInfo &objInfo, void *maskPtr,
const ResizedImageInfo &imgInfo) {
// resize
cv::Mat maskMat(maskSize_, maskSize_, CV_32FC1);
auto *maskAclPtr = reinterpret_cast<aclFloat16 *>(maskPtr);
......
This diff is collapsed.
aipp_op {
aipp_mode : static
input_format : RGB888_U8
related_input_rank : 0
csc_switch : false
rbuv_swap_switch : true
matrix_r0c0 : 256
matrix_r0c1 : 0
matrix_r0c2 : 359
matrix_r1c0 : 256
matrix_r1c1 : -88
matrix_r1c2 : -183
matrix_r2c0 : 256
matrix_r2c1 : 454
matrix_r2c2 : 0
input_bias_0 : 0
input_bias_1 : 128
input_bias_2 : 128
mean_chn_0 : 124
mean_chn_1 : 117
mean_chn_2 : 104
var_reci_chn_0 : 0.0171247538316637
var_reci_chn_1 : 0.0175070028011204
var_reci_chn_2 : 0.0174291938997821
}
\ No newline at end of file
#!/usr/bin/env bash
# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
model_path=$1
output_model_name=$2
atc \
--model=$model_path \
--framework=1 \
--output=$output_model_name \
--input_format=NCHW --input_shape="actual_input_1:1,3,416,416" \
--enable_small_channel=1 \
--log=error \
--soc_version=Ascend310 \
--insert_op_conf=./aipp.config
\ No newline at end of file
# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================
import argparse
import json
import os
from collections import defaultdict
import cv2
parser = argparse.ArgumentParser(description='YOLOV4')
parser.add_argument('--data_url', type=str, default='./datasets', help='coco2017 datasets')
parser.add_argument('--train_url', type=str, default='./infer/data/models/', help='save txt file')
parser.add_argument('--val_url', type=str, default='./infer/data/images/', help='coco2017 val infer datasets')
args_opt, _ = parser.parse_known_args()
def name_box_parse(json_path):
with open(json_path, encoding='utf-8') as f:
data = json.load(f)
annotations = data['annotations']
for ant in annotations:
image_id = ant['image_id']
name = str("%012d.jpg" % image_id)
cat = ant['category_id']
if 1 <= cat <= 11:
cat = cat - 1
elif 13 <= cat <= 25:
cat = cat - 2
elif 27 <= cat <= 28:
cat = cat - 3
elif 31 <= cat <= 44:
cat = cat - 5
elif 46 <= cat <= 65:
cat = cat - 6
elif cat == 67:
cat = cat - 7
elif cat == 70:
cat = cat - 9
elif 72 <= cat <= 82:
cat = cat - 10
elif 84 <= cat <= 90:
cat = cat - 11
name_box_id[name].append([ant['bbox'], cat])
name_box_id = defaultdict(list)
id_name = dict()
name_box_parse(os.path.join(args_opt.data_url, 'annotations', 'instances_val2017.json'))
with open(os.path.join(args_opt.train_url, 'trainval.txt'), 'w') as g:
ii = 0
for idx, key in enumerate(name_box_id.keys()):
print('trainval', key.split('/')[-1])
g.write('%d ' % ii)
ii += 1
g.write(os.path.join(args_opt.val_url, key))
print(os.path.join(args_opt.data_url, 'val2017', key))
img = cv2.imread(os.path.join(args_opt.data_url, 'val2017', key))
h, w, c = img.shape
g.write(' %d %d' % (w, h))
box_infos = name_box_id[key]
for info in box_infos:
x_min = int(info[0][0])
y_min = int(info[0][1])
x_max = x_min + int(info[0][2])
y_max = y_min + int(info[0][3])
box_info = " %d %d %d %d %d" % (
int(info[1]), x_min, y_min, x_max, y_max
)
g.write(box_info)
g.write('\n')
#Copyright 2022 Huawei Technologies Co., Ltd
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
#http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
import os
import json
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval
def get_image_id(label_file):
"""
:param: label file path, default is coco2017_minival.txt
:return: image id
"""
image_list = []
with open(label_file, 'r')as f_read:
ban_list = f_read.read().split('\n')[:-1]
for item in ban_list:
image_path = item.split(' ')[1]
image_name = image_path.split('/')[-1]
image_id = image_name.split('.')[0].split('_')[-1]
image_list.append(int(image_id))
return image_list
def get_category_id(class_id):
"""
:param: class id which corresponding coco.names
:return: category id is used in instances_val2017.json
"""
if 0 <= class_id <= 10:
class_id = class_id + 1
elif 11 <= class_id <= 23:
class_id = class_id + 2
elif 24 <= class_id <= 25:
class_id = class_id + 3
elif 26 <= class_id <= 39:
class_id = class_id + 5
elif 40 <= class_id <= 59:
class_id = class_id + 6
elif class_id == 60:
class_id = class_id + 7
elif class_id == 61:
class_id = class_id + 9
elif 62 <= class_id <= 72:
class_id = class_id + 10
elif 73 <= class_id <= 79:
class_id = class_id + 11
return class_id
def get_img_set(anno_json_path):
"""Get image path and annotation from COCO."""
need_img_ids = []
coco = COCO(anno_json_path)
image_ids = coco.getImgIds()
print("first dataset is {}".format(len(image_ids)))
for img_id in image_ids:
iscrowd = False
anno_ids = coco.getAnnIds(imgIds=img_id, iscrowd=None)
anno = coco.loadAnns(anno_ids)
for label in anno:
iscrowd = iscrowd or label["iscrowd"]
if iscrowd:
continue
need_img_ids.append(img_id)
return need_img_ids
def get_dict_from_file(file_path, id_list):
"""
:param: file_path contain all infer result
:param: id_list contain all images id which is corresponding instances_val2017.json
:return: dict_list contain infer result of every images
"""
print(len(id_list))
ls = []
image_dict = {}
count = -1
with open(file_path, 'r')as fs:
ban_list = fs.read().split('\n')
for item in ban_list:
if item == '':
continue
if item[0] != '#':
count = count + 1
continue
image_list = item.split(',')
image_dict['image_id'] = id_list[count]
image_dict['category_id'] = get_category_id(int(image_list[-1].strip().split(' ')[-1]))
bbox_list = [float(i) for i in image_list[1].strip().split(' ')[1:]]
bbox_list[2] = bbox_list[2] - bbox_list[0]
bbox_list[3] = bbox_list[3] - bbox_list[1]
image_dict['bbox'] = bbox_list
image_dict['score'] = float(image_list[2].strip().split(' ')[-1])
ls.append(image_dict.copy())
return ls
def get_img_id(file_name):
"""
get image id list from result data
"""
ls = []
myset = []
annos = json.load(open(file_name, 'r'))
for anno in annos:
ls.append(anno['image_id'])
myset = {}.fromkeys(ls).keys()
return myset
if __name__ == "__main__":
ban_path = './trainval.txt'
input_file = './result/result.txt'
if not os.path.exists(ban_path):
print('The infer text file does not exist.')
if not os.path.exists(input_file):
print('The result text file does not exist.')
image_id_list = get_image_id(ban_path)
result_dict = get_dict_from_file(input_file, image_id_list)
json_file_name = './result.json'
with open(json_file_name, 'w') as f:
json.dump(result_dict, f)
# set iouType to 'segm', 'bbox' or 'keypoints'
ann_type = ('segm', 'bbox', 'keypoints')
# specify type here
ann_type = ann_type[1]
coco_gt_file = './instances_val2017.json'
coco_gt = COCO(coco_gt_file)
coco_dt_file = './result.json'
coco_dt = coco_gt.loadRes(coco_dt_file)
coco_eval = COCOeval(coco_gt, coco_dt, ann_type)
coco_eval.params.imgIds = get_img_set(coco_gt_file)
coco_eval.evaluate()
coco_eval.accumulate()
coco_eval.summarize()
# hyper-parameter
CLASS_NUM=80
BIASES_NUM=18
BIASES=12,16,19,36,40,28,36,75,76,55,72,146,142,110,192,243,459,401
SCORE_THRESH=0.001
OBJECTNESS_THRESH=0.001
IOU_THRESH=0.6
YOLO_TYPE=3
ANCHOR_DIM=3
MODEL_TYPE=0
RESIZE_FLAG=0
\ No newline at end of file
#!/bin/bash
# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
docker_image=$1
share_dir=$2
data_dir=$3
echo "$1"
echo "$2"
if [ -z "${docker_image}" ]; then
echo "please input docker_image"
exit 1
fi
if [ ! -d "${share_dir}" ]; then
echo "please input share directory that contains dataset, models and codes"
exit 1
fi
docker run -it \
--device=/dev/davinci0 \
--device=/dev/davinci_manager \
--device=/dev/devmm_svm \
--device=/dev/hisi_hdc \
--privileged \
-v //usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v ${data_dir}:${data_dir} \
-v ${share_dir}:${share_dir} \
-u root \
${docker_image} \
/bin/bash
cmake_minimum_required(VERSION 3.10.0)
project(Yolov4post)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
#set(PLUGIN_NAME "Yolov4_mindspore_post")
set(TARGET_LIBRARY Yolov4_mindspore_post)
set(TARGET_MAIN Yolov4_mindspore)
set(ACL_LIB_PATH $ENV{ASCEND_HOME}/ascend-toolkit/latest/acllib)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories($ENV{MX_SDK_HOME}/include)
include_directories($ENV{MX_SDK_HOME}/opensource/include)
include_directories($ENV{MX_SDK_HOME}/opensource/include/opencv4)
include_directories($ENV{MX_SDK_HOME}/opensource/include/gstreamer-1.0)
include_directories($ENV{MX_SDK_HOME}/opensource/include/glib-2.0)
include_directories($ENV{MX_SDK_HOME}/opensource/lib/glib-2.0/include)
link_directories($ENV{MX_SDK_HOME}/lib)
link_directories($ENV{MX_SDK_HOME}/opensource/lib/)
add_compile_options(-std=c++11 -fPIC -fstack-protector-all -pie -Wno-deprecated-declarations)
add_compile_options("-DPLUGIN_NAME=${PLUGIN_NAME}")
add_compile_options("-Dgoogle=mindxsdk_private")
add_definitions(-DENABLE_DVPP_INTERFACE)
#message("ACL_LIB_PATH:${ACL_LIB_PATH}/lib64/.")
#include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${ACL_LIB_PATH}/include)
link_directories(${ACL_LIB_PATH}/lib64/)
add_library(${TARGET_LIBRARY} SHARED src/PostProcess/Yolov4MindsporePost.cpp)
target_link_libraries(${TARGET_LIBRARY} glib-2.0 gstreamer-1.0 gobject-2.0 gstbase-1.0 gmodule-2.0)
target_link_libraries(${TARGET_LIBRARY} plugintoolkit mxpidatatype mxbase)
target_link_libraries(${TARGET_LIBRARY} -Wl,-z,relro,-z,now,-z,noexecstack -s)
message("TARGET_LIBRARY:${TARGET_LIBRARY}.")
add_executable(${TARGET_MAIN} src/main.cpp src/Yolov4Detection.cpp)
target_link_libraries(${TARGET_MAIN} ${TARGET_LIBRARY} glog cpprest mxbase libascendcl.so opencv_world)
#!/bin/bash
# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================
# env
rm -r build
mkdir -p build
cd build || exit
function make_plugin() {
if ! cmake ..;
then
echo "cmake failed."
return 1
fi
if ! (make);
then
echo "make failed."
return 1
fi
return 0
}
if make_plugin;
then
echo "INFO: Build successfully."
else
echo "ERROR: Build failed."
fi
cd - || exit
#!/bin/bash
# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
# Simple log helper functions
info() { echo -e "\033[1;34m[INFO ][MxStream] $1\033[1;37m" ; }
warn() { echo >&2 -e "\033[1;31m[WARN ][MxStream] $1\033[1;37m" ; }
export LD_LIBRARY_PATH=${MX_SDK_HOME}/lib:${MX_SDK_HOME}/opensource/lib:${MX_SDK_HOME}/opensource/lib64:/usr/local/Ascend/${ASCEND_VERSION}/latest/acllib/lib64:${LD_LIBRARY_PATH}
export GST_PLUGIN_SCANNER=${MX_SDK_HOME}/opensource/libexec/gstreamer-1.0/gst-plugin-scanner
export GST_PLUGIN_PATH=${MX_SDK_HOME}/opensource/lib/gstreamer-1.0:${MX_SDK_HOME}/lib/plugins
#to set PYTHONPATH, import the StreamManagerApi.py
export PYTHONPATH=$PYTHONPATH:${MX_SDK_HOME}/python
python3 object_task_metric.py
exit 0
/*
* Copyright 2021 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Yolov4MindsporePost.h"
#include <algorithm>
#include <string>
#include <memory>
#include "MxBase/Log/Log.h"
#include "MxBase/CV/ObjectDetection/Nms/Nms.h"
namespace {
const int SCALE = 32;
const int BIASESDIM = 2;
const int OFFSETWIDTH = 2;
const int OFFSETHEIGHT = 3;
const int OFFSETBIASES = 1;
const int OFFSETOBJECTNESS = 1;
const int NHWC_HEIGHTINDEX = 1;
const int NHWC_WIDTHINDEX = 2;
const int NCHW_HEIGHTINDEX = 2;
const int NCHW_WIDTHINDEX = 3;
const int YOLO_INFO_DIM = 5;
auto uint8Deleter = [] (uint8_t* p) { };
} // namespace
namespace localParameter {
const uint32_t VECTOR_FIRST_INDEX = 0;
const uint32_t VECTOR_SECOND_INDEX = 1;
const uint32_t VECTOR_THIRD_INDEX = 2;
const uint32_t VECTOR_FOURTH_INDEX = 3;
const uint32_t VECTOR_FIFTH_INDEX = 4;
}
namespace MxBase {
Yolov4PostProcess& Yolov4PostProcess::operator=(const Yolov4PostProcess &other) {
if (this == &other) {
return *this;
}
ObjectPostProcessBase::operator=(other);
objectnessThresh_ = other.objectnessThresh_; // Threshold of objectness value
iouThresh_ = other.iouThresh_;
anchorDim_ = other.anchorDim_;
biasesNum_ = other.biasesNum_;
yoloType_ = other.yoloType_;
modelType_ = other.modelType_;
inputType_ = other.inputType_;
biases_ = other.biases_;
return *this;
}
APP_ERROR Yolov4PostProcess::Init(const std::map<std::string, std::shared_ptr<void>>& postConfig) {
LogDebug << "Start to Init Yolov4PostProcess.";
APP_ERROR ret = ObjectPostProcessBase::Init(postConfig);
if (ret != APP_ERR_OK) {
LogError << GetError(ret) << "Fail to superInit in ObjectPostProcessBase.";
return ret;
}
configData_.GetFileValue<int>("BIASES_NUM", biasesNum_);
std::string str;
configData_.GetFileValue<std::string>("BIASES", str);
configData_.GetFileValue<float>("OBJECTNESS_THRESH", objectnessThresh_);
configData_.GetFileValue<float>("IOU_THRESH", iouThresh_);
configData_.GetFileValue<int>("YOLO_TYPE", yoloType_);
configData_.GetFileValue<int>("MODEL_TYPE", modelType_);
configData_.GetFileValue<int>("YOLO_VERSION", yoloVersion_);
configData_.GetFileValue<int>("INPUT_TYPE", inputType_);
configData_.GetFileValue<int>("ANCHOR_DIM", anchorDim_);
ret = GetBiases(str);
if (ret != APP_ERR_OK) {
LogError << GetError(ret) << "Failed to get biases.";
return ret;
}
LogDebug << "End to Init Yolov4PostProcess.";
return APP_ERR_OK;
}
APP_ERROR Yolov4PostProcess::DeInit() {
return APP_ERR_OK;
}
bool Yolov4PostProcess::IsValidTensors(const std::vector<TensorBase> &tensors) {
if (tensors.size() != (size_t)yoloType_) {
LogError << "number of tensors (" << tensors.size() << ") " << "is unequal to yoloType_("
<< yoloType_ << ")";
return false;
}
if (yoloVersion_ == YOLOV4_VERSION) {
for (size_t i = 0; i < tensors.size(); i++) {
auto shape = tensors[i].GetShape();
if (shape.size() < localParameter::VECTOR_FIFTH_INDEX) {
LogError << "dimensions of tensor [" << i << "] is less than "
<< localParameter::VECTOR_FIFTH_INDEX << ".";
return false;
}
uint32_t channelNumber = 1;
int startIndex = modelType_ ? localParameter::VECTOR_SECOND_INDEX : localParameter::VECTOR_FOURTH_INDEX;
int endIndex = modelType_ ? (shape.size() - localParameter::VECTOR_THIRD_INDEX) : shape.size();
for (int j = startIndex; j < endIndex; j++) {
channelNumber *= shape[j];
}
if (channelNumber != anchorDim_ * (classNum_ + YOLO_INFO_DIM)) {
LogError << "channelNumber(" << channelNumber << ") != anchorDim_ * (classNum_ + 5).";
return false;
}
}
}
return true;
}
void Yolov4PostProcess::ObjectDetectionOutput(const std::vector<TensorBase>& tensors,
std::vector<std::vector<ObjectInfo>>& objectInfos,
const std::vector<ResizedImageInfo>& resizedImageInfos) {
LogDebug << "Yolov4PostProcess start to write results.";
if (tensors.size() == 0) {
return;
}
auto shape = tensors[0].GetShape();
if (shape.size() == 0) {
return;
}
uint32_t batchSize = shape[0];
for (uint32_t i = 0; i < batchSize; i++) {
std::vector<std::shared_ptr<void>> featLayerData = {};
std::vector<std::vector<size_t>> featLayerShapes = {};
for (uint32_t j = 0; j < tensors.size(); j++) {
auto dataPtr = reinterpret_cast<uint8_t *> (tensors[j].GetBuffer()) +
i * tensors[j].GetByteSize() / batchSize;
std::shared_ptr<void> tmpPointer;
tmpPointer.reset(dataPtr, uint8Deleter);
featLayerData.push_back(tmpPointer);
shape = tensors[j].GetShape();
std::vector<size_t> featLayerShape(shape.size());
transform(shape.begin(), shape.end(), featLayerShape.begin(), [](uint32_t s) { return (size_t)s; });
featLayerShapes.push_back(featLayerShape);
}
std::vector<ObjectInfo> objectInfo;
GenerateBbox(featLayerData, objectInfo, featLayerShapes, resizedImageInfos[i].widthResize,
resizedImageInfos[i].heightResize);
MxBase::NmsSort(objectInfo, iouThresh_);
objectInfos.push_back(objectInfo);
}
LogDebug << "Yolov4PostProcess write results success.";
}
APP_ERROR Yolov4PostProcess::Process(const std::vector<TensorBase> &tensors,
std::vector<std::vector<ObjectInfo>> &objectInfos,
const std::vector<ResizedImageInfo> &resizedImageInfos,
const std::map<std::string, std::shared_ptr<void>> &configParamMap) {
LogDebug << "Start to Process Yolov4PostProcess.";
APP_ERROR ret = APP_ERR_OK;
auto inputs = tensors;
ret = CheckAndMoveTensors(inputs);
if (ret != APP_ERR_OK) {
LogError << "CheckAndMoveTensors failed. ret=" << ret;
return ret;
}
ObjectDetectionOutput(inputs, objectInfos, resizedImageInfos);
for (uint32_t i = 0; i < resizedImageInfos.size(); i++) {
CoordinatesReduction(i, resizedImageInfos[i], objectInfos[i]);
}
LogObjectInfos(objectInfos);
LogDebug << "End to Process Yolov4PostProcess.";
return APP_ERR_OK;
}
void Yolov4PostProcess::CompareProb(int& classID, float& maxProb, float classProb, int classNum) {
if (classProb > maxProb) {
maxProb = classProb;
classID = classNum;
}
}
void Yolov4PostProcess::SelectClassNHWC(std::shared_ptr<void> netout, NetInfo info,
std::vector<MxBase::ObjectInfo>& detBoxes, int stride) {
const int offsetY = 1;
for (int j = 0; j < stride; ++j) {
for (int k = 0; k < info.anchorDim; ++k) {
int bIdx = (info.bboxDim + 1 + info.classNum) * info.anchorDim * j +
k * (info.bboxDim + 1 + info.classNum);
int oIdx = bIdx + info.bboxDim; // objectness index
float objectness = static_cast<float *>(netout.get())[oIdx];
if (objectness <= objectnessThresh_) {
continue;
}
int classID = -1;
float maxProb = scoreThresh_;
for (int c = 0; c < info.classNum; ++c) {
float clsProb = static_cast<float *>(netout.get())[bIdx +
(info.bboxDim + OFFSETOBJECTNESS + c)] * objectness;
CompareProb(classID, maxProb, clsProb, c);
}
if (classID < 0) continue;
MxBase::ObjectInfo det;
float x = static_cast<float *>(netout.get())[bIdx];
float y = static_cast<float *>(netout.get())[bIdx + offsetY];
float width = static_cast<float *>(netout.get())[bIdx + OFFSETWIDTH];
float height = static_cast<float *>(netout.get())[bIdx + OFFSETHEIGHT];
det.x0 = std::max(0.0f, x - width / COORDINATE_PARAM);
det.x1 = std::min(1.0f, x + width / COORDINATE_PARAM);
det.y0 = std::max(0.0f, y - height / COORDINATE_PARAM);
det.y1 = std::min(1.0f, y + height / COORDINATE_PARAM);
det.classId = classID;
det.className = configData_.GetClassName(classID);
det.confidence = maxProb;
if (det.confidence < separateScoreThresh_[classID]) continue;
detBoxes.emplace_back(det);
}
}
}
void Yolov4PostProcess::GenerateBbox(std::vector<std::shared_ptr<void>> featLayerData,
std::vector<MxBase::ObjectInfo> &detBoxes,
const std::vector<std::vector<size_t>>& featLayerShapes, const int netWidth,
const int netHeight) {
NetInfo netInfo;
netInfo.anchorDim = anchorDim_;
netInfo.bboxDim = BOX_DIM;
netInfo.classNum = classNum_;
netInfo.netWidth = netWidth;
netInfo.netHeight = netHeight;
for (int i = 0; i < yoloType_; ++i) {
int widthIndex_ = modelType_ ? NCHW_WIDTHINDEX : NHWC_WIDTHINDEX;
int heightIndex_ = modelType_ ? NCHW_HEIGHTINDEX : NHWC_HEIGHTINDEX;
OutputLayer layer = {featLayerShapes[i][widthIndex_], featLayerShapes[i][heightIndex_]};
int logOrder = log(featLayerShapes[i][widthIndex_] * SCALE / netWidth) / log(BIASESDIM);
int startIdx = (yoloType_ - 1 - logOrder) * netInfo.anchorDim * BIASESDIM;
int endIdx = startIdx + netInfo.anchorDim * BIASESDIM;
int idx = 0;
for (int j = startIdx; j < endIdx; ++j) {
layer.anchors[idx++] = biases_[j];
}
int stride = layer.width * layer.height;
std::shared_ptr<void> netout = featLayerData[i];
SelectClassNHWC(netout, netInfo, detBoxes, stride);
}
}
APP_ERROR Yolov4PostProcess::GetBiases(std::string& strBiases) {
if (biasesNum_ <= 0) {
LogError << GetError(APP_ERR_COMM_INVALID_PARAM) << "Failed to get biasesNum (" << biasesNum_ << ").";
return APP_ERR_COMM_INVALID_PARAM;
}
biases_.clear();
int i = 0;
int num = strBiases.find(",");
while (num >= 0 && i < biasesNum_) {
std::string tmp = strBiases.substr(0, num);
num++;
strBiases = strBiases.substr(num, strBiases.size());
biases_.push_back(stof(tmp));
i++;
num = strBiases.find(",");
}
if (i != biasesNum_ - 1 || strBiases.size() == 0) {
LogError << GetError(APP_ERR_COMM_INVALID_PARAM) << "biasesNum (" << biasesNum_
<< ") is not equal to total number of biases (" << strBiases <<").";
return APP_ERR_COMM_INVALID_PARAM;
}
biases_.push_back(stof(strBiases));
return APP_ERR_OK;
}
#ifndef ENABLE_POST_PROCESS_INSTANCE
extern "C" {
std::shared_ptr<MxBase::Yolov4PostProcess> GetObjectInstance() {
LogInfo << "Begin to get Yolov4PostProcess instance.";
auto instance = std::make_shared<Yolov4PostProcess>();
LogInfo << "End to get Yolov4PostProcess instance.";
return instance;
}
}
#endif
} // namespace MxBase
/*
* Copyright 2021 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef YOLOV4_POST_PROCESS_H
#define YOLOV4_POST_PROCESS_H
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <memory>
#include <opencv4/opencv2/opencv.hpp>
#include "MxBase/ErrorCode/ErrorCode.h"
#include "MxBase/CV/Core/DataType.h"
#include "MxBase/PostProcessBases/ObjectPostProcessBase.h"
const float DEFAULT_OBJECTNESS_THRESH = 0.3;
const float DEFAULT_IOU_THRESH = 0.45;
const int DEFAULT_ANCHOR_DIM = 3;
const int DEFAULT_BIASES_NUM = 18;
const int DEFAULT_YOLO_TYPE = 3;
const int DEFAULT_YOLO_VERSION = 4;
const int YOLOV3_VERSION = 3;
const int YOLOV4_VERSION = 4;
const int YOLOV5_VERSION = 5;
const int ANCHOR_NUM = 6;
struct OutputLayer {
size_t width;
size_t height;
float anchors[ANCHOR_NUM];
};
struct NetInfo {
int anchorDim;
int classNum;
int bboxDim;
int netWidth;
int netHeight;
};
namespace MxBase {
class Yolov4PostProcess : public ObjectPostProcessBase {
public:
Yolov4PostProcess() = default;
~Yolov4PostProcess() = default;
Yolov4PostProcess(const Yolov4PostProcess &other) = default;
Yolov4PostProcess &operator=(const Yolov4PostProcess &other);
APP_ERROR Init(const std::map<std::string, std::shared_ptr<void>> &postConfig) override;
APP_ERROR DeInit() override;
APP_ERROR Process(const std::vector<TensorBase> &tensors, std::vector<std::vector<ObjectInfo>> &objectInfos,
const std::vector<ResizedImageInfo> &resizedImageInfos = {},
const std::map<std::string, std::shared_ptr<void>> &configParamMap = {}) override;
protected:
bool IsValidTensors(const std::vector<TensorBase> &tensors);
void ObjectDetectionOutput(const std::vector<TensorBase> &tensors,
std::vector<std::vector<ObjectInfo>> &objectInfos,
const std::vector<ResizedImageInfo> &resizedImageInfos = {});
void CompareProb(int& classID, float& maxProb, float classProb, int classNum);
void SelectClassNHWC(std::shared_ptr<void> netout, NetInfo info, std::vector<MxBase::ObjectInfo>& detBoxes,
int stride);
void GenerateBbox(std::vector<std::shared_ptr<void>> featLayerData,
std::vector<MxBase::ObjectInfo> &detBoxes,
const std::vector<std::vector<size_t>>& featLayerShapes,
const int netWidth, const int netHeight);
APP_ERROR GetBiases(std::string& strBiases);
protected:
float objectnessThresh_ = DEFAULT_OBJECTNESS_THRESH; // Threshold of objectness value
float iouThresh_ = DEFAULT_IOU_THRESH; // Non-Maximum Suppression threshold
int anchorDim_ = DEFAULT_ANCHOR_DIM;
int biasesNum_ = DEFAULT_BIASES_NUM; // anchors, generate from train data, coco dataset
int yoloType_ = DEFAULT_YOLO_TYPE;
int modelType_ = 0;
int yoloVersion_ = DEFAULT_YOLO_VERSION;
int inputType_ = 0;
std::vector<float> biases_ = {};
};
#ifndef ENABLE_POST_PROCESS_INSTANCE
extern "C" {
std::shared_ptr<MxBase::Yolov4PostProcess> GetObjectInstance();
}
#endif
} // namespace MxBase
#endif
/*
* Copyright 2021 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Yolov4Detection.h"
#include <unistd.h>
#include <sys/stat.h>
#include <utility>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "MxBase/DeviceManager/DeviceManager.h"
#include "MxBase/Log/Log.h"
namespace {
const uint32_t YUV_BYTE_NU = 3;
const uint32_t YUV_BYTE_DE = 2;
const uint32_t VPC_H_ALIGN = 2;
} // namespace
APP_ERROR Yolov4DetectionOpencv::LoadLabels(const std::string &labelPath, std::map<int, std::string> &labelMap) {
std::ifstream infile;
// open label file
infile.open(labelPath, std::ios_base::in);
std::string s;
// check label file validity
if (infile.fail()) {
LogError << "Failed to open label file: " << labelPath << ".";
return APP_ERR_COMM_OPEN_FAIL;
}
labelMap.clear();
// construct label map
int count = 0;
while (std::getline(infile, s)) {
if (s[0] == '#') {
continue;
}
size_t eraseIndex = s.find_last_not_of("\r\n\t");
if (eraseIndex != std::string::npos) {
s.erase(eraseIndex + 1, s.size() - eraseIndex);
}
labelMap.insert(std::pair<int, std::string>(count, s));
count++;
}
infile.close();
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::Init(const InitParam &initParam) {
deviceId_ = initParam.deviceId;
APP_ERROR ret = MxBase::DeviceManager::GetInstance()->InitDevices();
if (ret != APP_ERR_OK) {
LogError << "Init devices failed, ret=" << ret << ".";
return ret;
}
ret = MxBase::TensorContext::GetInstance()->SetContext(initParam.deviceId);
if (ret != APP_ERR_OK) {
LogError << "Set context failed, ret=" << ret << ".";
return ret;
}
dvppWrapper_ = std::make_shared<MxBase::DvppWrapper>();
ret = dvppWrapper_->Init();
if (ret != APP_ERR_OK) {
LogError << "DvppWrapper init failed, ret=" << ret << ".";
return ret;
}
model_ = std::make_shared<MxBase::ModelInferenceProcessor>();
ret = model_->Init(initParam.modelPath, modelDesc_);
if (ret != APP_ERR_OK) {
LogError << "ModelInferenceProcessor init failed, ret=" << ret << ".";
return ret;
}
MxBase::ConfigData configData;
const std::string checkTensor = initParam.checkTensor ? "true" : "false";
configData.SetJsonValue("CLASS_NUM", std::to_string(initParam.classNum));
configData.SetJsonValue("BIASES_NUM", std::to_string(initParam.biasesNum));
configData.SetJsonValue("BIASES", initParam.biases);
configData.SetJsonValue("OBJECTNESS_THRESH", initParam.objectnessThresh);
configData.SetJsonValue("IOU_THRESH", initParam.iouThresh);
configData.SetJsonValue("SCORE_THRESH", initParam.scoreThresh);
configData.SetJsonValue("YOLO_TYPE", std::to_string(initParam.yoloType));
configData.SetJsonValue("MODEL_TYPE", std::to_string(initParam.modelType));
configData.SetJsonValue("INPUT_TYPE", std::to_string(initParam.inputType));
configData.SetJsonValue("ANCHOR_DIM", std::to_string(initParam.anchorDim));
configData.SetJsonValue("CHECK_MODEL", checkTensor);
auto jsonStr = configData.GetCfgJson().serialize();
std::map<std::string, std::shared_ptr<void>> config;
config["postProcessConfigContent"] = std::make_shared<std::string>(jsonStr);
config["labelPath"] = std::make_shared<std::string>(initParam.labelPath);
post_ = std::make_shared<MxBase::Yolov4PostProcess>();
ret = post_->Init(config);
if (ret != APP_ERR_OK) {
LogError << "Resnet50PostProcess init failed, ret=" << ret << ".";
return ret;
}
// load labels from file
ret = LoadLabels(initParam.labelPath, labelMap_);
if (ret != APP_ERR_OK) {
LogError << "Failed to load labels, ret=" << ret << ".";
return ret;
}
LogInfo << "End to Init Yolov4DetectionOpencv.";
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::DeInit() {
dvppWrapper_->DeInit();
model_->DeInit();
post_->DeInit();
MxBase::DeviceManager::GetInstance()->DestroyDevices();
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::ReadImage(const std::string &imgPath, cv::Mat &imageMat) {
imageMat = cv::imread(imgPath, cv::IMREAD_COLOR);
imageWidth_ = imageMat.cols;
imageHeight_ = imageMat.rows;
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::Resize(cv::Mat &srcImageMat, cv::Mat &dstImageMat) {
static constexpr uint32_t resizeHeight = 608;
static constexpr uint32_t resizeWidth = 608;
cv::resize(srcImageMat, dstImageMat, cv::Size(resizeWidth, resizeHeight));
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::CVMatToTensorBase(const cv::Mat &imageMat, MxBase::TensorBase &tensorBase) {
const uint32_t dataSize = imageMat.cols * imageMat.rows * MxBase::YUV444_RGB_WIDTH_NU;
MxBase::MemoryData memoryDataDst(dataSize, MxBase::MemoryData::MEMORY_DEVICE, deviceId_);
MxBase::MemoryData memoryDataSrc(imageMat.data, dataSize, MxBase::MemoryData::MEMORY_HOST_MALLOC);
APP_ERROR ret = MxBase::MemoryHelper::MxbsMallocAndCopy(memoryDataDst, memoryDataSrc);
if (ret != APP_ERR_OK) {
LogError << GetError(ret) << "Memory malloc failed.";
return ret;
}
std::vector<uint32_t> shape = {imageMat.rows * MxBase::YUV444_RGB_WIDTH_NU, static_cast<uint32_t>(imageMat.cols)};
tensorBase = MxBase::TensorBase(memoryDataDst, false, shape, MxBase::TENSOR_DTYPE_UINT8);
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::Inference(const std::vector<MxBase::TensorBase> &inputs,
std::vector<MxBase::TensorBase> &outputs) {
auto dtypes = model_->GetOutputDataType();
for (size_t i = 0; i < modelDesc_.outputTensors.size(); ++i) {
std::vector<uint32_t> shape = {};
for (size_t j = 0; j < modelDesc_.outputTensors[i].tensorDims.size(); ++j) {
shape.push_back((uint32_t)modelDesc_.outputTensors[i].tensorDims[j]);
}
MxBase::TensorBase tensor(shape, dtypes[i], MxBase::MemoryData::MemoryType::MEMORY_DEVICE, deviceId_);
APP_ERROR ret = MxBase::TensorBase::TensorBaseMalloc(tensor);
if (ret != APP_ERR_OK) {
LogError << "TensorBaseMalloc failed, ret=" << ret << ".";
return ret;
}
outputs.push_back(tensor);
}
MxBase::DynamicInfo dynamicInfo = {};
dynamicInfo.dynamicType = MxBase::DynamicType::STATIC_BATCH;
auto startTime = std::chrono::high_resolution_clock::now();
APP_ERROR ret = model_->ModelInference(inputs, outputs, dynamicInfo);
auto endTime = std::chrono::high_resolution_clock::now();
double costMs = std::chrono::duration<double, std::milli>(endTime - startTime).count();
g_inferCost.push_back(costMs);
if (ret != APP_ERR_OK) {
LogError << "ModelInference failed, ret=" << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::PostProcess(const std::vector<MxBase::TensorBase> &outputs,
std::vector<std::vector<MxBase::ObjectInfo>> &objInfos) {
MxBase::ResizedImageInfo imgInfo;
imgInfo.widthOriginal = imageWidth_;
imgInfo.heightOriginal = imageHeight_;
imgInfo.widthResize = 608;
imgInfo.heightResize = 608;
imgInfo.resizeType = MxBase::RESIZER_STRETCHING;
std::vector<MxBase::ResizedImageInfo> imageInfoVec = {};
imageInfoVec.push_back(imgInfo);
APP_ERROR ret = post_->Process(outputs, objInfos, imageInfoVec);
if (ret != APP_ERR_OK) {
LogError << "Process failed, ret=" << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::WriteResult(const std::vector<std::vector<MxBase::ObjectInfo>> &objInfos) {
std::string resultPathName = "result";
uint32_t batchSize = objInfos.size();
// create result directory when it does not exit
if (access(resultPathName.c_str(), 0) != 0) {
int ret = mkdir(resultPathName.c_str(), S_IRUSR | S_IWUSR | S_IXUSR);
if (ret != 0) {
LogError << "Failed to create result directory: " << resultPathName << ", ret = " << ret;
return APP_ERR_COMM_OPEN_FAIL;
}
}
// create result file under result directory
resultPathName = resultPathName + "/result.txt";
std::ofstream tfile(resultPathName, std::ofstream::app);
if (tfile.fail()) {
LogError << "Failed to open result file: " << resultPathName;
return APP_ERR_COMM_OPEN_FAIL;
}
// write inference result into file
for (uint32_t i = 0; i < batchSize; i++) {
tfile << "Object detected num is " << objInfos[i].size() << std::endl;
for (uint32_t j = 0; j < objInfos[i].size(); j++) {
tfile << "#Obj: " << j << ", box: " << objInfos[i][j].x0 << " " << objInfos[i][j].y0 << " "
<< objInfos[i][j].x1 << " " << objInfos[i][j].y1
<< ", confidence: " << objInfos[i][j].confidence << ", label: " << labelMap_[objInfos[i][j].classId]
<< ", id: " << objInfos[i][j].classId << std::endl;
}
}
tfile.close();
return APP_ERR_OK;
}
APP_ERROR Yolov4DetectionOpencv::Process(const std::string &imgPath) {
// process image
cv::Mat imageMat;
APP_ERROR ret = ReadImage(imgPath, imageMat);
if (ret != APP_ERR_OK) {
LogError << "ReadImage failed, ret=" << ret << ".";
return ret;
}
ret = Resize(imageMat, imageMat);
if (ret != APP_ERR_OK) {
LogError << "Resize failed, ret=" << ret << ".";
return ret;
}
std::vector<MxBase::TensorBase> inputs = {};
std::vector<MxBase::TensorBase> outputs = {};
MxBase::TensorBase tensorBase;
ret = CVMatToTensorBase(imageMat, tensorBase);
if (ret != APP_ERR_OK) {
LogError << "CVMatToTensorBase failed, ret=" << ret << ".";
return ret;
}
inputs.push_back(tensorBase);
ret = Inference(inputs, outputs);
if (ret != APP_ERR_OK) {
LogError << "Inference failed, ret=" << ret << ".";
return ret;
}
std::vector<std::vector<MxBase::ObjectInfo>> objInfos;
ret = PostProcess(outputs, objInfos);
if (ret != APP_ERR_OK) {
LogError << "PostProcess failed, ret=" << ret << ".";
return ret;
}
ret = WriteResult(objInfos);
if (ret != APP_ERR_OK) {
LogError << "Save result failed, ret=" << ret << ".";
return ret;
}
imageMat.release();
return APP_ERR_OK;
}
/*
* Copyright 2021 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MXBASE_YOLOV4DETECTIONOPENCV_H
#define MXBASE_YOLOV4DETECTIONOPENCV_H
#include <vector>
#include <memory>
#include <map>
#include <string>
#include <opencv2/opencv.hpp>
#include "MxBase/DvppWrapper/DvppWrapper.h"
#include "MxBase/ModelInfer/ModelInferenceProcessor.h"
#include "PostProcess/Yolov4MindsporePost.h"
#include "MxBase/Tensor/TensorContext/TensorContext.h"
extern std::vector<double> g_inferCost;
struct InitParam {
uint32_t deviceId;
std::string labelPath;
bool checkTensor;
std::string modelPath;
uint32_t classNum;
uint32_t biasesNum;
std::string biases;
std::string objectnessThresh;
std::string iouThresh;
std::string scoreThresh;
uint32_t yoloType;
uint32_t modelType;
uint32_t inputType;
uint32_t anchorDim;
};
class Yolov4DetectionOpencv {
public:
APP_ERROR Init(const InitParam &initParam);
APP_ERROR DeInit();
APP_ERROR ReadImage(const std::string &imgPath, cv::Mat &imageMat);
APP_ERROR Resize(cv::Mat &srcImageMat, cv::Mat &dstImageMat);
APP_ERROR CVMatToTensorBase(const cv::Mat &imageMat, MxBase::TensorBase &tensorBase);
APP_ERROR Inference(const std::vector<MxBase::TensorBase> &inputs, std::vector<MxBase::TensorBase> &outputs);
APP_ERROR PostProcess(const std::vector<MxBase::TensorBase> &outputs,
std::vector<std::vector<MxBase::ObjectInfo>> &objInfos);
APP_ERROR Process(const std::string &imgPath);
APP_ERROR LoadLabels(const std::string &labelPath, std::map<int, std::string> &labelMap);
APP_ERROR WriteResult(const std::vector<std::vector<MxBase::ObjectInfo>> &objInfos);
private:
std::shared_ptr<MxBase::DvppWrapper> dvppWrapper_;
std::shared_ptr<MxBase::ModelInferenceProcessor> model_;
std::shared_ptr<MxBase::Yolov4PostProcess> post_;
MxBase::ModelDesc modelDesc_;
std::map<int, std::string> labelMap_;
uint32_t deviceId_ = 0;
uint32_t imageWidth_ = 0;
uint32_t imageHeight_ = 0;
};
#endif
/*
* Copyright 2022 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <vector>
#include "Yolov4Detection.h"
#include "MxBase/Log/Log.h"
std::vector<double> g_inferCost;
void SplitString(const std::string &s, std::vector<std::string> *v, const std::string &c) {
std::string::size_type pos1, pos2;
pos2 = s.find(c);
pos1 = 0;
while (std::string::npos != pos2) {
v->push_back(s.substr(pos1, pos2 - pos1));
pos1 = pos2 + c.size();
pos2 = s.find(c, pos1);
}
if (pos1 != s.length()) {
v->push_back(s.substr(pos1));
}
}
void InitYolov4Param(InitParam *initParam) {
initParam->deviceId = 0;
initParam->labelPath = "../data/models/coco2017.names";
initParam->checkTensor = true;
initParam->modelPath = "../data/models/yolov4.om";
initParam->classNum = 80;
initParam->biasesNum = 18;
initParam->biases = "12,16,19,36,40,28,36,75,76,55,72,146,142,110,192,243,459,401";
initParam->objectnessThresh = "0.001";
initParam->iouThresh = "0.6";
initParam->scoreThresh = "0.001";
initParam->yoloType = 3;
initParam->modelType = 0;
initParam->inputType = 0;
initParam->anchorDim = 3;
}
APP_ERROR ReadImagesPath(const std::string &path, std::vector<std::string> *imagesPath) {
std::ifstream inFile;
inFile.open(path, std::ios_base::in);
std::string line;
// Check images path file validity
if (inFile.fail()) {
LogError << "Failed to open label file: " << path;
return APP_ERR_COMM_OPEN_FAIL;
}
std::vector<std::string> vectorStr;
std::string splitStr = " ";
// construct label map
while (std::getline(inFile, line)) {
if (line[0] == '#') {
continue;
}
vectorStr.clear();
SplitString(line, &vectorStr, splitStr);
imagesPath->push_back(vectorStr[1]);
}
inFile.close();
return APP_ERR_OK;
}
int main(int argc, char* argv[]) {
if (argc <= 1) {
LogWarn << "Please input image path, such as './yolov4 infer.txt'.";
return APP_ERR_OK;
}
InitParam initParam;
InitYolov4Param(&initParam);
auto yolov4 = std::make_shared<Yolov4DetectionOpencv>();
APP_ERROR ret = yolov4->Init(initParam);
if (ret != APP_ERR_OK) {
LogError << "Yolov4DetectionOpencv init failed, ret=" << ret << ".";
return ret;
}
LogInfo << "End to Init yolov4.";
std::string inferText = argv[1];
std::vector<std::string> imagesPath;
ret = ReadImagesPath(inferText, &imagesPath);
if (ret != APP_ERR_OK) {
LogError << "ReadImagesPath failed, ret=" << ret << ".";
return ret;
}
for (uint32_t i = 0; i < imagesPath.size(); i++) {
LogInfo << "read image path " << imagesPath[i];
ret = yolov4->Process(imagesPath[i]);
if (ret != APP_ERR_OK) {
LogError << "Yolov4DetectionOpencv process failed, ret=" << ret << ".";
yolov4->DeInit();
return ret;
}
}
yolov4->DeInit();
double costSum = 0;
for (uint32_t i = 0; i < g_inferCost.size(); i++) {
costSum += g_inferCost[i];
}
LogInfo << "Infer images sum " << g_inferCost.size() << ", cost total time: " << costSum << " ms.";
LogInfo << "The throughput: " << g_inferCost.size() * 1000 / costSum << " images/sec.";
return APP_ERR_OK;
}
{
"im_yolov4": {
"stream_config": {
"deviceId": "0"
},
"appsrc0": {
"props": {
"blocksize": "409600"
},
"factory": "appsrc",
"next": "mxpi_imagedecoder0"
},
"mxpi_imagedecoder0": {
"props": {
"handleMethod": "opencv"
},
"factory": "mxpi_imagedecoder",
"next": "mxpi_imageresize0"
},
"mxpi_imageresize0": {
"props": {
"parentName": "mxpi_imagedecoder0",
"handleMethod": "opencv",
"resizeHeight": "608",
"resizeWidth": "608",
"resizeType": "Resizer_Stretch"
},
"factory": "mxpi_imageresize",
"next": "mxpi_tensorinfer0"
},
"mxpi_tensorinfer0": {
"props": {
"dataSource": "mxpi_imageresize0",
"modelPath": "../data/models/yolov4.om",
"waitingTime": "3000",
"outputDeviceId": "-1"
},
"factory": "mxpi_tensorinfer",
"next": "mxpi_objectpostprocessor0"
},
"mxpi_objectpostprocessor0": {
"props": {
"dataSource": "mxpi_tensorinfer0",
"postProcessConfigPath": "../data/models/yolov4_coco2017_acc_test.cfg",
"labelPath": "../data/models/coco2017.names",
"postProcessLibPath": "./mxpi/build/libyolov4_mindspore_post.so"
},
"factory": "mxpi_objectpostprocessor",
"next": "mxpi_dataserialize0"
},
"mxpi_dataserialize0": {
"props": {
"outputDataKeys": "mxpi_objectpostprocessor0"
},
"factory": "mxpi_dataserialize",
"next": "appsink0"
},
"appsink0": {
"props": {
"blocksize": "4096000"
},
"factory": "appsink"
}
}
}
#!/bin/bash
# Copyright 2021 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
# Simple log helper functions
info() { echo -e "\033[1;34m[INFO ][MxStream] $1\033[1;37m" ; }
warn() { echo >&2 -e "\033[1;31m[WARN ][MxStream] $1\033[1;37m" ; }
export LD_LIBRARY_PATH=${MX_SDK_HOME}/lib:${MX_SDK_HOME}/opensource/lib:${MX_SDK_HOME}/opensource/lib64:/usr/local/Ascend/${ASCEND_VERSION}/latest/acllib/lib64:${LD_LIBRARY_PATH}
export GST_PLUGIN_SCANNER=${MX_SDK_HOME}/opensource/libexec/gstreamer-1.0/gst-plugin-scanner
export GST_PLUGIN_PATH=${MX_SDK_HOME}/opensource/lib/gstreamer-1.0:${MX_SDK_HOME}/lib/plugins
#to set PYTHONPATH, import the StreamManagerApi.py
export PYTHONPATH=$PYTHONPATH:${MX_SDK_HOME}/python
python3 object_task_metric.py
exit 0
# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ============================================================================
import json
import os
from StreamManagerApi import StreamManagerApi, MxDataInput
def read_file_list(input_file):
"""
:param infer file content:
0 xxx/xxx/a.jpg 1920 1080 0 453 369 473 391 1 588 245 608 268
1 xxx/xxx/b.jpg 1920 1080 1 466 403 485 422 2 793 300 809 320
...
:return image path list
"""
image_file_list = []
if not os.path.exists(input_file):
print('input file does not exists.')
with open(input_file, "r") as fs:
for line in fs.readlines():
line = line.strip('\n').split(' ')[1]
image_file_list.append(line)
return image_file_list
def save_infer_result(result_dir, result):
"""
save infer result to the file, Write format:
Object detected num is 5
#Obj: 1, box: 453 369 473 391, confidence: 0.3, label: person, id: 0
...
:param result_dir is the dir of save result
:param result content bbox and class_id of all object
"""
load_dict = json.loads(result)
if load_dict.get('MxpiObject') is None:
with open(result_dir + '/result.txt', 'a+') as f_write:
f_write.write("")
else:
res_vec = load_dict.get('MxpiObject')
with open(result_dir + '/result.txt', 'a+') as f_write:
object_list = 'Object detected num is ' + str(len(res_vec)) + '\n'
f_write.writelines(object_list)
for index, object_item in enumerate(res_vec):
class_info = object_item.get('classVec')[0]
object_info = '#Obj: ' + str(index) + ', box: ' + \
str(object_item.get('x0')) + ' ' + \
str(object_item.get('y0')) + ' ' + \
str(object_item.get('x1')) + ' ' + \
str(object_item.get('y1')) + ', confidence: ' + \
str(class_info.get('confidence')) + ', label: ' + \
class_info.get('className') + ', id: ' + \
str(class_info.get('classId')) + '\n'
f_write.writelines(object_info)
if __name__ == '__main__':
# init stream manager
stream_manager = StreamManagerApi()
ret = stream_manager.InitManager()
if ret != 0:
print("Failed to init Stream manager, ret=%s" % str(ret))
exit()
# create streams by pipeline config file
with open("./config/yolov4.pipeline", 'rb') as f:
pipeline = f.read()
ret = stream_manager.CreateMultipleStreams(pipeline)
if ret != 0:
print("Failed to create Stream, ret=%s" % str(ret))
exit()
# Construct the input of the stream
data_input = MxDataInput()
infer_file = './trainval.txt'
file_list = read_file_list(infer_file)
res_dir_name = 'result'
if not os.path.exists(res_dir_name):
os.makedirs(res_dir_name)
for file_path in file_list:
print(file_path)
file_name = file_path.split('/')[-1]
if not (file_name.lower().endswith(".jpg") or file_name.lower().endswith(".jpeg")):
continue
with open(file_path, 'rb') as f:
data_input.data = f.read()
# Inputs data to a specified stream based on streamName.
stream_name = b'im_yolov4'
inplugin_id = 0
unique_id = stream_manager.SendData(stream_name, inplugin_id, data_input)
if unique_id < 0:
print("Failed to send data to stream.")
exit()
# Obtain the inference result by specifying streamName and uniqueId.
mstimeout = 5000
infer_result = stream_manager.GetResult(stream_name, unique_id, mstimeout)
if infer_result.errorCode != 0:
print("GetResultWithUniqueId error. errorCode=%d, errorMsg=%s" % (
infer_result.errorCode, infer_result.data.decode()))
exit()
save_infer_result(res_dir_name, infer_result.data.decode())
# destroy streams
stream_manager.DestroyAllStreams()
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