从推理 Pytorch 接收坐标

Receiving coordinates from inference Pytorch

我正在尝试获取由 Pytorches DefaultPredictor 生成的遮罩内像素的坐标,以便稍后获取多边形角并在我的应用程序中使用它。

但是,DefaultPredictor 生成了张量 pred_masks,格式如下:[False, False ... False], ... [False, False, .. False] 其中每个单独列表的长度是图像的长度,总列表的数量是图像的高度。

现在,因为我需要获取掩码内的像素坐标,简单的解决方案似乎是循环遍历 pred_masks,检查值,如果 == "True" 创建元组这些并将它们添加到列表中。然而,当我们讨论宽度 x 高度约为 3200 x 1600 的图像时,这是一个相对较慢的过程(循环一个 3200x1600 大约需要 4 秒,但由于有相当多的对象我需要进行推断最后 - 这最终会非常慢)。

使用 pytorch (detectron2) 模型获取检测到的对象的坐标(掩码)的更聪明的方法是什么?

请在下面找到我的代码以供参考:

from __future__ import print_function

from detectron2.engine import DefaultPredictor
from detectron2.config import get_cfg
from detectron2.data import MetadataCatalog
from detectron2.data.datasets import register_coco_instances


import cv2
import time


# get image
start = time.time()

im = cv2.imread("inputImage.jpg")

# Create config
cfg = get_cfg()
cfg.merge_from_file("detectron2_repo/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 # Set threshold for this model
cfg.MODEL.WEIGHTS = "model_final.pth" # Set path model .pth
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1
cfg.MODEL.DEVICE='cpu'

register_coco_instances("dataset_test",{},"testval.json","Images_path")
test_metadata = MetadataCatalog.get("dataset_test")


# Create predictor
predictor = DefaultPredictor(cfg)

# Make prediction
outputs = predictor(im)

 
#Loop through the pred_masks and check which ones are equal to TRUE, if equal, add the pixel values to the true_cords_list
outputnump = outputs["instances"].pred_masks.numpy()

true_cords_list = []
x_length = range(len(outputnump[0][0]))
#y kordinaat on range number
for y_cord in range(len(outputnump[0])):
    #x cord
    for x_cord in x_length:
        if str(outputnump[0][y_cord][x_cord]) == "True":
            inputcoords = (x_cord,y_cord)
            true_cords_list.append(inputcoords)

print(str(true_cords_list))

end = time.time()

print(f"Runtime of the program is {end - start}") # 14.29468035697937

//

编辑: 在将 for 循环部分更改为压缩后 - 我设法将 for 循环的运行时间减少了 ~3x - 但是,理想情况下,如果可能的话,我希望从预测器本身接收它。

y_length = len(outputnump[0])
x_length = len(outputnump[0][0])
true_cords_list = []
for y_cord in range(y_length):
    x_cords = list(compress(range(x_length), outputnump[0][y_cord]))
    if x_cords:
        for x_cord in x_cords:
            inputcoords = (x_cord,y_cord)
            true_cords_list.append(inputcoords)

如果对 NumPy 或 PyTorch 原生数组处理有足够的了解,这个问题很容易解决,与 Python 循环相比,它允许 100 倍的加速。你可以研究 NumPy library,PyTorch 张量在行为上与 NumPy 相似。

如何在 NumPy 中获取值的索引:

import numpy as np
arr = np.random.rand(3,4) > 0.5
ind = np.argwhere(arr)[:, ::-1]
print(arr)
print(ind)

在您的特定情况下,这将是

ind = np.argwhere(outputnump[0])[:, ::-1]

如何在 PyTorch 中获取值的索引:

import torch
arr = torch.rand(3, 4) > 0.5
ind = arr.nonzero()
ind = torch.flip(ind, [1])
print(arr)
print(ind)

[::-1].flip用于将坐标的顺序从(y,x)倒序到(x,y)。

NumPy 和 PyTorch 甚至允许检查简单条件并获取满足这些条件的值的索引,要进一步了解,请参阅相应的 NumPy docs article


询问时,您应该提供问题上下文的链接。这个问题实际上是关于 Facebook object detector,他们提供了一个很好的演示 Colab 笔记本。