使用matplotlib在图像数据之上对线网格进行像素精确定位 [英] pixel-precise positioning of line mesh on top of image data with matplotlib

查看:38
本文介绍了使用matplotlib在图像数据之上对线网格进行像素精确定位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在python库matplotlib显示的图像网格顶部上精确覆盖1像素宽的线的网格.

不幸的是,我似乎无法对结果进行足够的精细控制,以实现线网格与数据网格的正确对齐,如下面的代码所示.结果似乎总是很接近,但并不完全正确.

我曾尝试同时使用 imshowpcolormesh 函数,但两种方法都遇到了问题.

imshow方法:

 将matplotlib.pyplot导入为plt将numpy导入为np大小 = 60边框= 5#为图像和刻度位置创建测试数据im = np.zeros(shape=(size,size),dtype=np.float32)刻度= np.arange(size)+0.5#在边界区域之外创建测试棋盘图案对于范围(size-2 * border)中的索引:im [border + index,border:-border] + =索引%2对于范围内的索引(size-2*border):im [border:-border,index + border]-=索引%2im = np.abs(im)#用imshow显示图片plt.imshow(im,插值='最近',cmap ='二进制',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)#有时线会偏离 1 个像素plt.show()

我希望红线的线网格精确覆盖数据网格的棋盘图案,但它们相差一个像素.

此缩放图像显示了结果,并且偏移很容易看到:

我也尝试使用pcolormesh和edgecolor(使用与上述相同的数据):

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

此处红线网格的对齐方式更好,但是线宽不一致,有时为1像素宽,有时为2像素宽,如下图所示:

在这里,理想情况下,我希望始终得到一条1像素宽的线.可以使用 linewidth 参数,但是如果我把它设置得太小,那么线条开始具有 0 像素宽度并且它们完全消失,而且我不太明白 linewidth 的单位是什么.

最后,对于在定位(红线网格,不偏离黑白棋盘格)和线宽(在屏幕上始终正好为1像素)方面实现一致性的任何建议,我将不胜感激.

解决方案

好吧,我想我会回答我自己的问题.这是基于反复试验,所以我不确定它是否普遍有效,但我希望这些信息对某人有用.

我能够使用下面的代码一致地绘制宽度为 1 个像素的 pcolormesh 网格,其中 my_dpi 需要精确设置为显示屏和 imsize_pixel_ximsize_pixel_y 是所需的绘图窗口大小.

my_dpi = 96.0imsize_pixel_x = 800imsize_pixel_y = 600plt.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',线宽= my_dpi/(1024 * 32))plt.show()

I am trying to precisely overlay a mesh of 1-pixel wide lines on top of an image grid as displayed by the python library matplotlib.

Unfortunately, I seem to be unable to have enough fine control over the result to achieve proper alignment of the line mesh with the data grid, as the code below shows. The results seems to always be close but not quite exactly right.

I have tried using both the imshow and pcolormesh functions, and encountered problems with both approaches.

imshow approach:

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()

I would expect the line mesh of red lines to overlay precisely the checkerboard pattern of the data grid, but they are off by one pixel.

This zoomed image show the results and the offset is easily visible:

I also tried using pcolormesh and edgecolor (using same data as above):

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

Here the red line mesh aligns better, but the line width is not consistent, sometimes is 1-pixel wide, sometimes 2-pixel wide, as shown in this image:

Here, ideally, I would like to always get a 1-pixel wide line. It is possible to play around with the linewidth parameter, but if I make it too small, then the lines start to have 0-pixel width and they disappear altogether, and also I am not quite understanding what is the unit of linewidth.

In conclusion, I would appreciate any suggestions on how to achieve consistency in both positioning (red line mesh without offset from black and white checkerboard) and line width (always exactly 1-pixel wide on screen).

解决方案

Oh well, I guess I'll answer my own question. This is based on trial and error, so I am not sure if it is universally valid, but I hope the information may be useful for someone.

I was able to consistently plot the pcolormesh grid with width of exactly 1 pixels using the code below, where my_dpi needs to be set exactly to the dpi resolution of the display screen and imsize_pixel_x and imsize_pixel_y are the desired size of the plot window.

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()

这篇关于使用matplotlib在图像数据之上对线网格进行像素精确定位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆