Как получить координаты логического 'True' из pd.dataframe? - PullRequest
1 голос
/ 20 октября 2019

У меня есть png, который я превратил в pd.DataFrame, который содержит логические значения. Для белого пикселя я получаю «False», а для черного пикселя «True». Я хотел бы создать диаграмму DXF. Для этого я пытаюсь получить координаты для каждого «True» на фрейме данных, чтобы потом я мог соединить их, чтобы нарисовать линию.

Это код, который у меня сейчас есть:

from PIL import Image
import numpy as np
import pandas as pd

img = Image.open('/home/sinushas/Downloads/Brezynio_Konvertavimas/test.png')
thresh = 200
fn = lambda x : 255 if x > thresh else 0
r = img.convert('L').point(fn, mode='1')
r.save('/home/sinushas/Downloads/Brezynio_Konvertavimas/test_converted.png')

im = Image.open('/home/sinushas/Downloads/Brezynio_Konvertavimas/test_converted.png')
im2arr = np.array(im) # im2arr.shape: height x width x channel

df = pd.DataFrame(im2arr)
df = (df == False) 

Это сгенерированный pd.Dataframe:

    0   1   2   3   4   5   6   7   8   9
0   False   False   False   False   False   False   False   False   False   False
1   False   False   False   False   False   False   False   False   False   False
2   False   False   True    True    True    True    True    True    False   False
3   False   False   False   False   True    True    False   False   False   False
4   False   False   False   False   True    True    False   False   False   False
5   False   False   False   False   True    True    False   False   False   False
6   False   False   False   False   True    True    False   False   False   False
7   False   False   False   False   False   False   False   False   False   False
8   False   False   False   False   False   False   False   False   False   False
9   False   False   False   False   False   False   False   False   False   False

Я ожидаю получить следующие координаты: (2: 3), (2: 4), (2: 5), (2: 6), (2: 7), (2: 8), (3: 5), (3: 6), (4: 5), (4: 6), (5: 5), (6: 6), (6: 5), (6: 6)

Я не нашел работающего фрагмента кода, который мог бы получить мне какие-либо координаты из кадра данных .. То, что я пробовал:

result = im2arr.where('True')

df.sort_index() 

res = [i for i, val in enumerate(df) if val]

Спасибо за любые советы.

Ответы [ 4 ]

0 голосов
/ 20 октября 2019

Вам не нужно pandas для этого. И вам не нужно читать это снова. Вы даже можете использовать L в .point(fn, mode='L')

r = img.convert('L').point(fn, mode='1')
r.save(...)

data = np.where(r)          # [[y1,y2,...], [x1,x2,...], ]
points = list(zip(*data))   # [[y1,x1], [y2,x2], ...]

print(points)

. Вы можете использовать where() на r напрямую, чтобы получить список с [[y1,y2,...], [x1,x2,...]].

И затем вы можете использовать zip() для создания пар [y1, x1], [y2,x2] и т. Д.

РЕДАКТИРОВАТЬ: Для других пикселей вы можете использовать ~для отрицания значений в r

data = np.where(~r)          # other pixels

Массив работает с координатами (row, columns), что означает (y, x) - как в ожидаемых вами данных (2,3), (2,4) - но если вам понадобится (x, y), тоиспользовать:

points = list(zip(data[1], data[0]))

в конечном итоге

points = [(x,y) for y,x in zip(*data)]

РЕДАКТИРОВАТЬ: Вам не нужно даже .point()

from PIL import Image
import numpy as np

img = Image.open('image.png').convert('L')

arr = np.array(img)

#data = np.where( arr > 200 )    # for white pixels
#data = np.where( ~(arr > 200) ) # for black pixels too
data = np.where(arr < 200) # for black pixels

points_y_x = list(zip(*data))
points_x_y = list(zip(data[1], data[0]))

print(points_y_x)
print(points_x_y)
0 голосов
/ 20 октября 2019

DataFrame.stack

для создания логического индексирования .

df2=df.stack()
coordinates=[*df2[df2].index]

#print(coordinates)
[(2, 2),
 (2, 3),
 (2, 4),
 (2, 5),
 (2, 6),
 (2, 7),
 (3, 4),
 (3, 5),
 (4, 4),
 (4, 5),
 (5, 4),
 (5, 5),
 (6, 4),
 (6, 5)]
0 голосов
/ 20 октября 2019

np.nonzero:

[(x,y) for x,y in zip(*np.nonzero(df.values))]

Вывод:

[(2, 2),
 (2, 3),
 (2, 4),
 (2, 5),
 (2, 6),
 (2, 7),
 (3, 4),
 (3, 5),
 (4, 4),
 (4, 5),
 (5, 4),
 (5, 5),
 (6, 4),
 (6, 5)]

​
0 голосов
/ 20 октября 2019

Использование np.where:

coord = np.where(df)

coordinates = [(x,y) for x, y in zip(coord[0], coord[1])]

Выход

[(2, 2),
 (2, 3),
 (2, 4),
 (2, 5),
 (2, 6),
 (2, 7),
 (3, 4),
 (3, 5),
 (4, 4),
 (4, 5),
 (5, 4),
 (5, 5),
 (6, 4),
 (6, 5)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...