TypeError: индексы списка должны быть целыми или кусочками, а не cupy.core.core.ndarray - PullRequest
0 голосов
/ 11 февраля 2019

В алгоритмах обнаружения объектов, Non-Maximum Suppression (NMS) используется для отбрасывания дополнительных результатов обнаружения для объекта, например транспортного средства.

Обычно, горизонтальные ограничивающие рамки используются в алгоритмах обнаружения объектов и реализации GPUгоризонтальной NMS уже существует, но я хотел, чтобы реализация GPU повернула ограничивающие рамки.

Реализация CPU уже выполнена, но я изо всех сил пытаюсь преобразовать версию CPU в версию GPU, используя пакет CuPy.Вот код, который я написал.После раздела кода вы можете увидеть ошибку.

Мой вопрос заключается в том, что является причиной TypeError: индексы списка должны быть целыми числами или кусочками, а не cupy.core.core.ndarray?

    from shapely.geometry import Polygon as shpoly
    import time

    #### CPU implementation
    import numpy as np   

    def polygon_iou(poly1, poly2):
      """
      Intersection over union between two shapely polygons.
      """
      if not poly1.intersects(poly2): # this test is fast and can accelerate calculation
        iou = 0
      else:
        try:
          inter_area = poly1.intersection(poly2).area
          union_area = poly1.area + poly2.area - inter_area
          iou = float(inter_area) / float(union_area)
        except shapely.geos.TopologicalError:
          warnings.warn("'shapely.geos.TopologicalError occured, iou set to 0'", UserWarning)
          iou = 0
        except ZeroDivisionError:
          iou = 0
      return iou

    def polygon_from_array(poly_):
      """
      Create a shapely polygon object from gt or dt line.
      """
      polygon_points = np.array(poly_).reshape(4, 2)
      polygon = shpoly(polygon_points).convex_hull
      return polygon

    def nms(dets, thresh):
        scores = dets[:, 8]
        order = scores.argsort()[::-1]
        polys = []
        areas = []
        for i in range(len(dets)):
            tm_polygon = polygon_from_array(dets[i,:8])
            polys.append(tm_polygon)
        keep = []
        while order.size > 0:
            ovr = []
            i = order[0]
            keep.append(i)
            for j in range(order.size - 1):
                iou = polygon_iou(polys[i], polys[order[j + 1]])
                ovr.append(iou)
            ovr = np.array(ovr)
            inds = np.where(ovr <= thresh)[0]
            order = order[inds + 1]
        return keep


    #### GPU implementation
    import cupy as cp  

    def polygon_iou_gpu(poly1, poly2):
      """
      Intersection over union between two shapely polygons.
      """
      if not poly1.intersects(poly2): # this test is fast and can accelerate calculation
        iou = 0
      else:
        try:
          inter_area = poly1.intersection(poly2).area
          union_area = poly1.area + poly2.area - inter_area
          iou = float(inter_area) / float(union_area)
        except shapely.geos.TopologicalError:
          warnings.warn("'shapely.geos.TopologicalError occured, iou set to 0'", UserWarning)
          iou = 0
        except ZeroDivisionError:
          iou = 0
      return iou

    def polygon_from_array_gpu(poly_):
      """
      Create a shapely polygon object from gt or dt line.
      """
      polygon_points = cp.array(poly_).reshape(4, 2)
      polygon = shpoly(polygon_points).convex_hull
      return polygon

    def nms_gpu(dets, thresh):
        scores = dets[:, 8]
        order = scores.argsort()[::-1]
        polys = []
        areas = []
        for i in range(len(dets)):
            tm_polygon = polygon_from_array_gpu(dets[i,:8])
            polys.append(tm_polygon)
        keep = []
        while order.size > 0:
            ovr = []
            i = order[0]
            keep.append(i)
            for j in range(order.size - 1):   
                iou = polygon_iou_gpu(polys[i], polys[order[j + 1]])
                ovr.append(iou)
            ovr = np.array(ovr)
            inds = np.where(ovr <= thresh)[0]
            order = order[inds + 1]
        return keep


    if __name__ == '__main__':
        import random
        boxes = np.random.randint(0,100,(1000,8))
        scores = np.random.rand(1000, 1)
        dets = np.hstack((boxes, scores[:])).astype(np.float32)


        thresh = 0.1
        start = time.time()
        keep = nms(dets, thresh)
        print("CPU implementation took: {}".format(time.time() - start))

        cp.cuda.Device(1)
        dets_gpu = cp.array(dets)
        start = time.time()
        keep = nms_gpu(dets_gpu, thresh)
        print("GPU implementation took: {}".format(time.time() - start))

Ошибка:

Реализация ЦП заняла: 0,3672311305999756

Трассировка (последний последний вызов):

Файл "nms_rotated.py", строка 117,в

keep = nms_gpu(dets_gpu, thresh)

Файл "nms_rotated.py", строка 97, в nms_gpu

iou = polygon_iou_gpu(polys[i], polys[order[j + 1]])

TypeError: индексы списка должны быть целыми или слайсами, а не cupy.core.core.ndarray

Обновление: 13.02.2019 Я попытался ответить @Yuki Hashimoto

, заменив iou = polygon_iou_gpu(polys[i], polys[order[j + 1]]) на iou = polygon_iou_gpu(polys[i.get()], polys[order[j + 1].get()]).Он не выдает никаких ошибок, но версия GPU в несколько раз медленнее, чем версия CPU.

при использовании 100000 случайных обнаружений:

      CPU implementation took: 47.125494956970215
      GPU implementation took: 142.08464860916138

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Короче говоря: используйте официальное подавление PFN не максимальное подавление .

Подробности: Используйте cp.where, который возвращает объект list, который соответствует некоторому условию.


Ответ corochann не рекомендуется, поскольку polys является списком, и list также не должен быть разрезан на np.ndarray.(и вводить другую зависимость не рекомендуется ...)

>>> polys[order.get()]  # get method returns np.ndarray
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: only integer scalar arrays can be converted to a scalar index
>>> polys[order[j + 1].get()]
### some result in some case, but this may fails depending on your env.###
0 голосов
/ 11 февраля 2019

[ОБНОВЛЕНИЕ 2019/2/13]

Пожалуйста, обратитесь к ответу @ yuki-hashimoto, который более подходит.


Как написано в сообщении об ошибке

TypeError: индексы списка должны быть целыми или кусочками, а не cupy.core.core.ndarray

Я думаю, order является массивом cupy?В этом случае polys[order[j + 1]] использует индексы order[j+1] в качестве массива кубов, что может вызвать проблему.Как насчет того, чтобы попытаться преобразовать их в массив numpy методом cuda.to_cpu(array)?

from chainer import cuda
iou = polygon_iou_gpu(polys[i], polys[cuda.to_cpu(order[j + 1])])
...