TypeError: индексы списка должны быть целыми или кусочками, а не cupy.core.core.ndarray
В алгоритмах обнаружения объекта используется Non-Maximum Suppression(NMS) для отбрасывания дополнительных результатов обнаружения для объекта, например транспортного средства.
Обычно горизонтальные ограничивающие рамки используются в алгоритмах обнаружения объектов, и реализация горизонтальной 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
Traceback (последний вызов был последним):
Файл "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 ответа
Короче говоря: используйте официальное подавление не максимума 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.###
[ОБНОВЛЕНИЕ 2019/2/13]
Пожалуйста, обратитесь к ответу @ yuki-hashimoto, который более подходит.
Как написано в сообщении об ошибке
TypeError: индексы списка должны быть целыми или кусочками, а не cupy.core.core.ndarray
Я думаю, order
такое массив чашечек? В таком случае polys[order[j + 1]]
использует индексы order[j+1]
как чашка, которая может вызвать проблему. Как насчет преобразования их в массив numy с помощью cuda.to_cpu(array)
метод?
from chainer import cuda
iou = polygon_iou_gpu(polys[i], polys[cuda.to_cpu(order[j + 1])])