Как обвести некоторые пиксели на тепловой карте непрерывной, не разветвленной линией, используя Python? - PullRequest
0 голосов
/ 13 декабря 2018

Я использую plt.imshow() для отображения значений на сетке (в моем случае данные CCD).Пример графика:

enter image description here

Мне нужно указать на нем барьер, чтобы показать, какие пиксели меня интересуют.Это похоже на то, что мне нужно:

enter image description here

Я знаю, как добавить квадратов к изображению , линий сетки кизображение , но это знание не решает проблему и не добавляет одиночные квадраты к картинке, что также в моих силах.Мне нужна линия, которая окружает область на сетке (и эта линия всегда должна идти между пикселями, а не поперек их, так что это может немного упростить ее).

Как я могу это сделать?


Юрий Соуза предоставил хороший обходной путь к вышеуказанному вопросу.Тем не менее, он не строго обводит область линией (скорее наносит маску на изображение, а затем снова покрывает большую часть изображения), и не удается, когда я пытаюсь окружить перекрывающуюся группу пикселей. ImportanceOfBeingErnest предложил в комментариях, что я должен просто использовать образец plt.plot.Используя пример Iury Sousa в качестве отправной точки, давайте получим:

X,Y = np.meshgrid(range(30),range(30))
Z = np.sin(X)+np.sin(Y)
selected1 = Z>1.5

Теперь selected1 - это массив логических массивов , и мы хотели быобведите только те пиксели, которые имеют соответствующее значение Z выше 1,5.Мы также хотели бы обвести selected2, который содержит True значения для пикселей со значением выше 0,2 и ниже 1,8:

upperlim_selected2 = Z<1.8
selected2 = upperlim_selected2>0.2

Большой обходной путь Iury Sousa не работает для этого случая.plt.plot будет, по моему мнению.Как эффективно обойти кружки selected1 и selected2, используя plt.plot или другой метод?

Ответы [ 3 ]

0 голосов
/ 23 декабря 2018

Аналогично ответу в Могут ли контуры matplotlib соответствовать краям пикселей? Вы можете создать сетку с более высоким разрешением и нарисовать график contour.

import numpy as np
import matplotlib.pyplot as plt

X,Y = np.meshgrid(range(30),range(30))
Z = np.sin(X)+np.sin(Y)

resolution = 25

f = lambda x,y: Z[int(y),int(x) ]
g = np.vectorize(f)

x = np.linspace(0,Z.shape[1], Z.shape[1]*resolution)
y = np.linspace(0,Z.shape[0], Z.shape[0]*resolution)
X2, Y2= np.meshgrid(x[:-1],y[:-1])
Z2 = g(X2,Y2)


plt.pcolormesh(X,Y, Z)
plt.contour(X2,Y2,Z2, [1.5], colors='r', linewidths=[1])

plt.show()

enter image description here

0 голосов
/ 03 января 2019

Другое решение, которое работает для меня:

Позволяет иметь сетку, например:

grid=[[0, 6, 8, 2, 2, 5, 25, 24, 11],
      [4, 15, 3, 22, 225, 1326, 2814, 1115, 18],
      [6, 10, 9, 201, 3226, 3549, 3550, 3456, 181],
      [42, 24, 46, 1104, 3551, 3551, 3551, 3382, 27],
      [9, 7, 73, 2183, 3551, 3551, 3551, 3294, 83],
      [9, 7, 5, 669, 3544, 3551, 3074, 1962, 18],
      [10, 3545, 9, 10, 514, 625, 16, 14, 5],
      [5, 6, 128, 10, 8, 6, 7, 40, 4]]

Мы строим ее:

plt.pcolormesh(grid)

enter image description here

Предположим, что мы хотим окружить каждый пиксель значением больше 1420. Мы создаем логический массив:

threshold=1420
booleangrid=np.asarray(grid)>threshold
intgrid=booleangrid*1

Затем мы создаем отрезок линии вокруг каждого пикселя:

down=[];up=[];left=[];right=[]
for i, eachline in enumerate(intgrid):
    for j, each in enumerate(eachline):
        if each==1:
            down.append([[j,j+1],[i,i]])
            up.append([[j,j+1],[i+1,i+1]])
            left.append([[j,j],[i,i+1]])
            right.append([[j+1,j+1],[i,i+1]])

и соедините их вместе:

together=[]
for each in down: together.append(each)
for each in up: together.append(each)
for each in left: together.append(each)
for each in right: together.append(each)

(Создано отдельно для ясности.)

Мы проходим эти отдельные отрезки линии, оставляя только те, которые появляются только один разт. е. те, которые находятся на краю объекта, определенного логическим массивом (booleangrid), который мы определили выше:

filtered=[]
for each in together:
    c=0
    for EACH in together:
        if each==EACH:
            c+=1
    if c==1:
        filtered.append(each)

Затем мы строим сетку и отдельные сегменты линии с помощью цикла for:

plt.pcolormesh(grid)
for x in range(len(filtered)):
    plt.plot(filtered[x][0],filtered[x][1],c='red', linewidth=8)

дает нам результат:

enter image description here

С которым мы можем быть счастливы.

0 голосов
/ 14 декабря 2018

Я попробовал что-то, что должно соответствовать вашим потребностям.

Прежде всего, я определил произвольные данные:

X,Y = np.meshgrid(range(30),range(30))

Z = np.sin(X)+np.sin(Y)

Здесь вы можете определить условие, которое вписывается в шаблон, который вы хотитевыделить:

selected = Z>1.5

Для построения графика вы будете использовать scatter вместо imshow.Вы нанесете на график все данные, затем выбранные данные еще два раза, один с большими квадратами с цветом подсветки, а другой обычно с использованием того же эталона цвета и ограничений.

info = dict(marker='s',vmin=-2,vmax=2)
fig,ax = plt.subplots()
plt.scatter(X.ravel(),Y.ravel(),100,c=Z.ravel(),**info)
plt.scatter(X[selected].ravel(),Y[selected].ravel(),150,c='r',marker='s')
plt.scatter(X[selected].ravel(),Y[selected].ravel(),100,c=Z[selected].ravel(),**info)
ax.axis('equal')

enter image description here

...