From 4b2cd2afc28480e059f65ced3f228c6602f4d3fb Mon Sep 17 00:00:00 2001 From: cchenghao <867240157@qq.com> Date: Mon, 5 Dec 2022 20:22:00 +0800 Subject: [PATCH] Modify comments and readme --- MobileStereoNet/README.md | 43 +++++---- MobileStereoNet/RESOURCES/result.png | Bin 38892 -> 0 bytes MobileStereoNet/camera_configs.py | 4 +- MobileStereoNet/main.py | 135 +++++++++++++++++++++++++++ MobileStereoNet/yolo_deep.py | 107 --------------------- MobileStereoNet/yolov3_infer.py | 26 +++--- 6 files changed, 176 insertions(+), 139 deletions(-) delete mode 100644 MobileStereoNet/RESOURCES/result.png create mode 100644 MobileStereoNet/main.py delete mode 100644 MobileStereoNet/yolo_deep.py diff --git a/MobileStereoNet/README.md b/MobileStereoNet/README.md index af3c73a..f029779 100644 --- a/MobileStereoNet/README.md +++ b/MobileStereoNet/README.md @@ -6,7 +6,7 @@ 样例输入:双目相机拍摄的两张jpg图片 -样例输出:物体的三维坐标 +样例输出:物体的三维坐标和距离 ### 1.1 支持的产品 @@ -19,7 +19,7 @@ ### 1.3 软件方案介绍 -本方案中,利用Opencv对输入图片进行畸变矫正,然后采用yolov3预训练模型对矫正图片进行物体识别,最终根据识别得到的生成框坐标输出物体的三维坐标。 +本方案中,利用Opencv对输入图片进行畸变矫正,然后采用yolov3预训练模型对矫正图片进行物体识别,最终根据识别得到的生成框坐标输出物体的三维坐标和距离。 表1.1 系统方案中各模块功能: @@ -28,9 +28,9 @@ | 1 | 图像输入 | 使用Opencv的imread读入图片 | | 2 | 图像放缩 | 使用Opencv的resize放缩检测图片到416*416大小 | | 3 | 畸变矫正 | 利用Opencv和相机参数重构图片 | -| 4 | 视察计算 | 使用Opencv的SGBM方法计算图片视差 | +| 4 | 视差计算 | 使用Opencv的SGBM方法计算图片视差 | | 5 | 物体检测 | 利用Yolov3的检测模型,检测图片中物体并得到检测框坐标 | -| 6 | 结果输出 | 根据检测框坐标输出物体的三维坐标 | +| 6 | 结果输出 | 根据检测框坐标输出物体的三维坐标和距离 | @@ -44,9 +44,12 @@ │ ├── yolov3_tf_bs1_fp16.cfg # yolov3后处理配置 │ └── yolov3_tf_aipp.om ├── image # 存放测试图片 -|── camera_configs.py # 相机参数文件 -|── yolov3_infer.py # 获取坐标文件 -|── yolov3_infer.py # yolov3模型推理文件 +├── RESOURCES +│ └── flow.png +├── camera_configs.py # 获取相机参数 +├── camera.xml # 相机参数文件 +├── main.py # 获取坐标文件 +├── yolov3_infer.py # yolov3模型推理文件 ├── ExportStereoParams.m # matlab导出xml函数 └── README.md ``` @@ -64,9 +67,9 @@ 1、由于yolov3模型限制,仅支持获取在`./models/yolov3.names`文件中的**80**种物体的三维坐标。 -2、对超出相机标定范围的物体定位,结果不是很理想。 +2、对超出相机标定范围的物体定位,误差可能会很大。 -3、不同标定相机需要对`yolo_deep.py`文件中函数**stereo_match**的**numDisparities**和**uniquenessRatio**这两个主要参数进行调整。 +3、不同标定相机需要对`main.py`文件中函数**stereo_match**的**numDisparities**和**uniquenessRatio**这两个主要参数进行调整。注意**numDisparities**参数必须可以被16整除,**uniquenessRatio**参数值通常在5-15范围内。 ## 2 环境依赖 @@ -90,7 +93,7 @@ ## 依赖安装 -创建虚拟环境后运行如下命令: +创建虚拟环境并激活后运行如下命令: ``` pip install opencv-python @@ -103,23 +106,31 @@ pip install opencv-python **步骤1** -[下载YOLOv3模型](https://www.hiascend.com/zh/software/modelzoo/models/detail/C/210261e64adc42d2b3d84c447844e4c7/1)放入`./model`文件夹中。 +[下载YOLOv3模型](https://ascend-repo-modelzoo.obs.cn-east-2.myhuaweicloud.com/c-version/YoloV3_for_TensorFlow/zh/1.6/m/YOLOv3_TensorFlow_1.6_model.zip)并解压,将其中的`yolov3_tf_aipp.om`放入`./model`文件夹中。 **步骤2** -将matlab标定导出的xml相机参数文件放入项目根目录中。 +使用Matlab标定双目相机,然后用提供的`ExportStereoParams.m`文件将相机参数导出成`camera.xml`文件,放入项目根目录中。 + +双目相机标定方法可以参考此处:[Link](https://blog.csdn.net/qq_38236355/article/details/89280633) **步骤3** -自行选择两张jpg文件,放入`./image`文件夹中,再执行 +使用步骤2标定的相机拍摄双目照片,放入`./image`文件夹中。注意如果相机拍出来的左右图片在一张图上,则需要自行分割为两张大小一样的图片,确保左右图片张数相等。根据放入的图片名称修改`main.py`中`LEFTIMG`和`RIGHTIMG`的图片命名格式,再执行: ``` -python yolo_deep.py +python main.py ``` 结果展示: -![pic](RESOURCES/result.png) +``` +The result of case 10: + +Pixel coordinates x = 500, y = 248 +3D coordinates (305.618927, 90.307648, 2773.036865) mm +umbrella's actual distance: 2.791289 m +``` ## 4 常见问题 @@ -135,4 +146,4 @@ E20221122 15:43:32.366075 9866 MxOmModelDesc.cpp:138] Infer failed, result is n **解决方案:** -同时使用dvpp和`yolov3_tf_aipp.om`模型时会报上述错误。解决方式一,将B_USEDVPP设置为False,使用opencv处理图片。解决方式二,将模型换成`yolov3_tf_bs1_fp16.om` \ No newline at end of file +同时设置`B_USEDVPP=True`和使用`yolov3_tf_aipp.om`模型时会报上述错误。解决方式一,将B_USEDVPP设置为False,使用opencv处理图片。解决方式二,将模型换成`yolov3_tf_bs1_fp16.om` \ No newline at end of file diff --git a/MobileStereoNet/RESOURCES/result.png b/MobileStereoNet/RESOURCES/result.png deleted file mode 100644 index 69e1fe2b502ce8186c153eb515b025634b8812b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38892 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 m + print("{}'s actual distance: {:f} m\n".format(name, distance)) + + os.remove("SGBM_left.jpg") diff --git a/MobileStereoNet/yolo_deep.py b/MobileStereoNet/yolo_deep.py deleted file mode 100644 index 43b5485..0000000 --- a/MobileStereoNet/yolo_deep.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright(C) 2022. Huawei Technologies Co.,Ltd. All rights reserved. -# -# 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 math -import collections -import cv2 -import numpy as np -import camera_configs -from yolov3_infer import yolo_infer - -LEFTIMG_PATH = "./image/left_0.jpg" -RIGHTIMG_PATH = "./image/right_0.jpg" -YOLO_RESIZELEN = 416 - - -def get_rectify(height, width): - left_matrix = camera_configs.left_camera_matrix - right_matrix = camera_configs.right_camera_matrix - left_distortion = camera_configs.left_distortion - right_distortion = camera_configs.right_distortion - R = camera_configs.R - T = camera_configs.T - - # 图像尺寸 - size = (width, height) - - # 进行立体更正 - R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(left_matrix, left_distortion, - right_matrix, right_distortion, size, R, T) - # 计算更正map - left_map1, left_map2 = cv2.initUndistortRectifyMap(left_matrix, left_distortion, R1, P1, size, cv2.CV_16SC2) - right_map1, right_map2 = cv2.initUndistortRectifyMap(right_matrix, right_distortion, R2, P2, size, cv2.CV_16SC2) - - Camera = collections.namedtuple('Camera', ['left_map1', 'left_map2', 'right_map1', 'right_map2', 'Q']) - - camera = Camera(left_map1, left_map2, right_map1, right_map2, Q) - return camera - - -def stereo_match(imgleft, imgright): - stereo = cv2.StereoSGBM_create(minDisparity=0, - numDisparities=16 * 6, - blockSize=5, - P1=216, - P2=864, - disp12MaxDiff=1, - uniquenessRatio=10, - speckleWindowSize=0, - speckleRange=1, - preFilterCap=60, - mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY) - disparity = stereo.compute(imgleft, imgright) - return disparity - - -if __name__ == '__main__': - img1 = cv2.imread(LEFTIMG_PATH) - img2 = cv2.imread(RIGHTIMG_PATH) - - img_height, img_width = img1.shape[0:2] - - configs = get_rectify(img_height, img_width) - - # 根据更正map对图片进行重构 - img1_rectified = cv2.remap(img1, configs.left_map1, configs.left_map2, cv2.INTER_LINEAR) - img2_rectified = cv2.remap(img2, configs.right_map1, configs.right_map2, cv2.INTER_LINEAR) - cv2.imwrite("SGBM_left.jpg", img1_rectified) - - # 将图片置为灰度图,为StereoSGBM作准备 - imgL = cv2.cvtColor(img1_rectified, cv2.COLOR_BGR2GRAY) - imgR = cv2.cvtColor(img2_rectified, cv2.COLOR_BGR2GRAY) - - # 根据SGBM/Semi-Global Block Matching方法生成差异图 - left_match = stereo_match(imgL, imgR) - - # 将图片扩展至3d空间中,其z方向的值则为当前的距离 - threeD = cv2.reprojectImageTo3D(left_match.astype(np.float32) / 16., configs.Q) - - # 因为om模型读取要YUV格式,前面cv读取处理是BGR,我暂时没找到直接定义Image类的方法,所以重读一遍重构后的图片 - coordinate = yolo_infer("SGBM_left.jpg", YOLO_RESIZELEN) - - for coor in coordinate: - x = coor.x1 - y = coor.y1 - - x = int(x) - y = int(y) - - print('\n像素坐标 x = %d, y = %d' % (x, y)) - - x = x - 1 - y = y - 1 - print("世界坐标xyz 是:", threeD[y][x][0] / 1000.0, threeD[y][x][1] / 1000.0, threeD[y][x][2] / 1000.0, "m") - distance = math.sqrt(threeD[y][x][0] ** 2 + threeD[y][x][1] ** 2 + threeD[y][x][2] ** 2) - distance = distance / 1000.0 # mm -> m - print("距离是:", distance, "m") diff --git a/MobileStereoNet/yolov3_infer.py b/MobileStereoNet/yolov3_infer.py index 56e46c5..235eaf0 100644 --- a/MobileStereoNet/yolov3_infer.py +++ b/MobileStereoNet/yolov3_infer.py @@ -18,18 +18,17 @@ import cv2 from mindx.sdk import base from mindx.sdk.base import Tensor, Model, Size, log, ImageProcessor, post, BTensor -DEVICE_ID = 0 # 芯片ID -MODEL_PATH = "./model/yolov3_tf_aipp.om" # 模型的路径 -CONFIG_PATH = "./model/yolov3_tf_bs1_fp16.cfg" # 模型配置文件的路径 -LABEL_PATH = "./model/yolov3.names" # 分类标签文件的路径 -B_USEDVPP = False # 使用dvpp图像处理器启用,使用opencv时False +DEVICE_ID = 0 +MODEL_PATH = "./model/yolov3_tf_aipp.om" +CONFIG_PATH = "./model/yolov3_tf_bs1_fp16.cfg" +LABEL_PATH = "./model/yolov3.names" +B_USEDVPP = False # Enabled with dvpp image processor, false with opencv def yolo_infer(image_path, yolo_resize): - yolo = Model(MODEL_PATH, DEVICE_ID) # 创造模型对象 + yolo = Model(MODEL_PATH, DEVICE_ID) image_tensor = [] if B_USEDVPP: - # 创造图像处理器对象!!!!!使用该方法处理后数据已在device侧 image_processor0 = ImageProcessor(DEVICE_ID) decode_img = image_processor0.decode(image_path, base.nv12) @@ -39,7 +38,7 @@ def yolo_infer(image_path, yolo_resize): image_processor1 = ImageProcessor(DEVICE_ID) size_cof = Size(yolo_resize, yolo_resize) resize_img = image_processor1.resize(decode_img, size_cof) - image_tensor = [resize_img.to_tensor()] # 推理前需要转换为tensor的List,数据已在device侧无需转移 + image_tensor = [resize_img.to_tensor()] else: image = np.array(cv2.imread(image_path)) @@ -50,16 +49,15 @@ def yolo_infer(image_path, yolo_resize): resize_img = cv2.resize(image, size_cof, interpolation=cv2.INTER_LINEAR) - yuv_img = cv2.cvtColor(resize_img, cv2.COLOR_BGR2YUV) - yuv_img = yuv_img[np.newaxis, :, :] - image_tensor = Tensor(yuv_img) # 推理前需要转换为tensor的List,使用Tensor类来构建。 + yuv_img = resize_img[np.newaxis, :, :] + image_tensor = Tensor(yuv_img) - image_tensor.to_device(DEVICE_ID) # 重要,需要转移至device侧 + image_tensor.to_device(DEVICE_ID) image_tensor = [image_tensor] outputs = yolo.infer(image_tensor) - print("-----------YOLO Infer Success!----------------") + yolov3_post = post.Yolov3PostProcess( - config_path=CONFIG_PATH, label_path=LABEL_PATH) # 构造对应的后处理对象 + config_path=CONFIG_PATH, label_path=LABEL_PATH) resize_info = base.ResizedImageInfo() resize_info.heightResize = yolo_resize