сортировать Numpy ndarray классов и координат по минимальному значению слева направо - PullRequest
0 голосов
/ 01 марта 2020

Я хочу отсортировать массив numpy, который содержит классы объектов, найденных на изображении с соответствующими координатами. Начало должно быть в левом верхнем углу изображения и проходить по строкам до нижнего правого угла.

Мой numpy массив:

import numpy as np


columns=['classses','ymin','xmin','ymax','xmax']

arr=np.array([[10.,  0.50835305,  0.47248545,  0.59892374,  0.51885366],
   [11.,  0.36795592,  0.52040386,  0.46757331,  0.56760514],
   [ 4.,  0.24611123,  0.29460225,  0.34236759,  0.34000006],
   [ 2.        ,  0.37274304,  0.38200337,  0.46354109,  0.4273783 ],
   [ 2.        ,  0.510912  ,  0.37931672,  0.59918219,  0.42638448],
   [11.        ,  0.10971789,  0.51647586,  0.20377752,  0.562015  ],
   [ 7.        ,  0.51268667,  0.24481608,  0.59831458,  0.29086089],
   [10.        ,  0.24716213,  0.47549573,  0.33929491,  0.52023494],
   [ 1.        ,  0.37433949,  0.61748177,  0.46359614,  0.65206224],
   [ 7.        ,  0.24870941,  0.24960253,  0.33646214,  0.29458734],
   [11.        ,  0.24345258,  0.51865327,  0.33831981,  0.565395  ],
   [ 8.        ,  0.11206201,  0.33702213,  0.19984987,  0.38336146],
   [10.        ,  0.24955718,  0.6559478 ,  0.34239537,  0.70276546],
   [ 2.        ,  0.24712075,  0.38360605,  0.33835301,  0.42949697],
   [ 4.        ,  0.51084387,  0.29126126,  0.59996665,  0.33353919],
   [ 8.        ,  0.51466578,  0.33362284,  0.60250646,  0.37810257],
   [ 6.        ,  0.510656  ,  0.56336159,  0.59472215,  0.61143786],
   [ 2.        ,  0.1192565 ,  0.69437939,  0.2057956 ,  0.73883325],
   [ 7.        ,  0.11934   ,  0.25181183,  0.20320818,  0.29591617],
   [ 9.        ,  0.51130402,  0.65646565,  0.59214538,  0.70244706],
   [ 3.        ,  0.11690334,  0.56094837,  0.20533638,  0.60812557],
   [11.        ,  0.50439239,  0.51784241,  0.59443074,  0.56629324],
   [ 7.        ,  0.37829998,  0.24856552,  0.46135774,  0.29153487],
   [ 4.        ,  0.37588719,  0.29197016,  0.46272004,  0.33599868],
   [ 1.        ,  0.37316957,  0.57077163,  0.46224919,  0.60553724],
   [10.        ,  0.1145431 ,  0.47239822,  0.20014074,  0.5183605 ],
   [10.        ,  0.37647596,  0.65606439,  0.46242031,  0.70245349],
   [ 1.        ,  0.24754623,  0.61552459,  0.34198812,  0.65568751],
   [10.        ,  0.37339926,  0.47152713,  0.461395  ,  0.52023202],
   [10.        ,  0.37436292,  0.69828469,  0.46418577,  0.74559146],
   [ 6.        ,  0.37082726,  0.42555344,  0.4643003 ,  0.47343689],
   [ 9.        ,  0.5126825 ,  0.69970727,  0.59857124,  0.74693108],
   [ 2.        ,  0.1202545 ,  0.3842268 ,  0.19877489,  0.42925853],
   [ 5.        ,  0.24687886,  0.5643267 ,  0.33911708,  0.61170775],
   [10.        ,  0.12104956,  0.65108246,  0.21425578,  0.69579262],
   [ 6.        ,  0.24587491,  0.42739749,  0.33760101,  0.47690719],
   [ 8.        ,  0.24526763,  0.33704251,  0.33957234,  0.38356996],
   [ 4.        ,  0.1150065 ,  0.29550964,  0.20008969,  0.3379634 ],
   [ 6.        ,  0.514301  ,  0.42620456,  0.59742886,  0.47339022],
   [ 1.        ,  0.24682792,  0.7001856 ,  0.34188086,  0.74008971],
   [ 8.        ,  0.11335434,  0.42906916,  0.19882832,  0.47424948],
   [ 1.        ,  0.11596378,  0.61286598,  0.20856762,  0.64871949],
   [ 8.        ,  0.37103209,  0.33494309,  0.46368858,  0.38201007],
   [ 6.        ,  0.37533277,  0.33500299,  0.46548373,  0.38105384]])

Форма массива (44,5)

Я преобразовал массив в pandas Dataframe, умножил значения на фактическую высоту и ширину изображения и нашел среднее значение для X и Y из их минимальных и максимальных значений.

import pandas as pd


df=pd.DataFrame(arr.copy(),index=None,columns=['classses','ymin','xmin','ymax','xmax'])
df['ymin']=(df['ymin']+df['ymax'])*1080/2
df['xmin']=(df['xmin']+df['xmax'])*1920/2
df=df.drop(columns=['xmax','ymax'])

## now it's rather y and x actually 
df.sort_values(by=['ymin','xmin'])

Вывод:

    classses    ymin    xmin
11  8.0 168.432415  691.568246
40  8.0 168.578636  867.185894
5   11.0    169.287521  1035.351226
25  10.0    169.929274  951.128371
37  4.0 170.151943  608.134118
32  2.0 172.275871  780.945917
20  3.0 174.009449  1122.310982
18  7.0 174.176017  525.818880
41  1.0 175.246956  1211.122051

...

Хотя класс 8 расположен довольно далеко в левом верхнем углу, это не самое низкое значение для X и Y.

Я также пробовал argsort () и lexsort (), а также преобразование в список и использование sorted () с operator.itemgetter (), но это принесло одинаковые результаты при сортировке для обоих столбцов.

Я также думал об использовании pop () и argmin () для получения минимального значения каждого столбца, а затем с помощью индекса pandas для получения соответствующего класса. Но я думаю, что это будет проблемой, как только я доберусь до конца каждой строки.

Заранее спасибо!

Здесь вы можете увидеть (не очень точный) график объектов на изображении

1 Ответ

0 голосов
/ 02 марта 2020

Одна ошибка в том, что если вы хотите, чтобы он начинался сверху вниз, справа внизу, то для оси y вам нужно отсортировать по ascending=False, а для оси x вам нужно отсортировать по ascending=True.

Попробуйте pd.sort_values(by=['ymin','xmin'],ascending=[False,True])

Это, по крайней мере, даст вам что-то в первом ряду. Однако, если вы хотите строго левый верхний класс, вам нужно сначала установить некоторые правила для классификации того, какие объекты находятся в одной строке. Это другой вопрос.

...