Пиксельное позиционирование линейной сетки поверх данных изображения с помощью matplotlib - PullRequest
1 голос
/ 09 мая 2019

Я пытаюсь точно наложить сетку из линий шириной в 1 пиксель поверх сетки изображения, как это показано в библиотеке python matplotlib.

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

Я пытался использовать функции imshow и pcolormesh, и столкнулся с проблемами в обоих подходах.

Подход imshow:

import matplotlib.pyplot as plt
import numpy as np

size = 60
border = 5

#create test data for image and ticks location
im = np.zeros(shape=(size,size),dtype=np.float32)
ticks = np.arange(size)+0.5

#create test checkerboard pattern outside of border area
for index in range(size-2*border):
    im[border+index,border:-border] += index % 2
for index in range(size-2*border):
    im[border:-border,index+border] -= index % 2
im = np.abs(im)

#display image with imshow
plt.imshow(im, interpolation='nearest', cmap='binary', vmin=0, vmax=1)
ax = plt.gca()
ax.set_xticks(ticks)
ax.set_xticklabels([])
ax.set_yticks(ticks)
ax.set_yticklabels([])
ax.grid(color='r', linestyle='-', linewidth=1)
#sometimes line is off by 1 pixel
plt.show()

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

На этом увеличенном изображении показаны результаты исмещение легко видно:

red_mesh_offset_by_one_pixel

Я также пытался использовать pcolormesh и edgecolor (используя те же данные, что и выше):

plt.pcolormesh(im, cmap='binary', vmin=0, vmax=1, edgecolors='r', linewidth=0.005)
plt.show()

Здесь сетка красной линиивыравнивается лучше, но ширина линии не согласована, иногда имеет ширину 1 пиксель, иногда ширину 2 пикселя, как показано на этом рисунке: red_mesh_inconsistent_line_width

Здесь, в идеале, я хотел бы всегда получать1-пиксельная широкая линия.Можно поэкспериментировать с параметром ширины линии, но если я сделаю его слишком маленьким, тогда линии начнут иметь ширину 0 пикселей, и они вообще исчезнут, а также я не совсем понимаю, что является единицей ширины линии.

В заключение, я был бы признателен за любые предложения о том, как добиться согласованности как в позиционировании (красная линия сетки без смещения от черно-белой шахматной доски), так и в ширине линии (всегда на экране ровно 1 пиксель).

1 Ответ

0 голосов
/ 27 мая 2019

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

Мне удалось последовательно построить сетку pcolormesh с ширинойровно 1 пиксель с использованием приведенного ниже кода, где my_dpi необходимо точно установить разрешение экрана на дюйм на экране, а imsize_pixel_x и imsize_pixel_y - требуемый размер окна графика.

my_dpi = 96.0
imsize_pixel_x = 800
imsize_pixel_y = 600

plt.figure(figsize=(imsize_pixel_x/my_dpi, imsize_pixel_y/my_dpi), dpi=my_dpi)
plt.pcolormesh(im, cmap='binary', vmin=0, vmax=1, edgecolors='r', linewidth=my_dpi/(1024*32))

plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...