- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我使用 matplotlib将数字矩阵显示为图像,沿轴附加标签,并将绘图保存为 PNG 文件。为了创建 HTML 图像映射,我需要知道 imshow 显示的图像中某个区域在 PNG 文件中的像素坐标。
我找到了 an example关于如何使用常规绘图执行此操作,但是当我尝试使用 imshow 执行相同操作时,映射不正确。这是我的代码,它保存了一张图像并尝试打印对角线上每个正方形中心的像素坐标:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
axim = ax.imshow(np.random.random((27,27)), interpolation='nearest')
for x, y in axim.get_transform().transform(zip(range(28), range(28))):
print int(x), int(fig.get_figheight() * fig.get_dpi() - y)
plt.savefig('foo.png', dpi=fig.get_dpi())
这是生成的 foo.png,显示为包含标尺的屏幕截图:
脚本的输出开始和结束如下:
73 55
92 69
111 83
130 97
149 112
…
509 382
528 396
547 410
566 424
585 439
如您所见,y 坐标是正确的,但 x 坐标被拉伸(stretch)了:它们的范围从 73 到 585,而不是预期的 135 到 506,并且它们的间距为 19 像素 o.c。而不是预期的 14。我做错了什么?
最佳答案
这是尝试从 matplotlib 获取精确像素值时比较令人困惑的部分之一。 Matplotlib 将处理精确像素值的渲染器与绘制图形和轴的 Canvas 分开。
基本上,最初创建图形(但尚未显示)时存在的渲染器不一定与显示图形或将其保存到文件时使用的渲染器相同。
您所做的是正确的,但它使用的是初始渲染器,而不是保存图形时使用的渲染器。
为了说明这一点,这里是您的代码的一个稍微简化的版本:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
im = ax.imshow(np.random.random((27,27)), interpolation='nearest')
for i in range(28):
x, y = ax.transData.transform_point([i,i])
print '%i, %i' % (x, fig.bbox.height - y)
fig.savefig('foo.png', dpi=fig.dpi)
这会产生与上面类似的结果:(差异是由于您的机器和我的机器之间的渲染后端不同)
89, 55
107, 69
125, 83
...
548, 410
566, 424
585, 439
但是,如果我们做完全相同的事情,但不是在显示坐标之前绘制图形,我们就会得到正确的答案!
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
im = ax.imshow(np.random.random((27,27)), interpolation='nearest')
fig.canvas.draw()
for i in range(28):
x, y = ax.transData.transform_point([i,i])
print '%i, %i' % (x, fig.bbox.height - y)
fig.savefig('foo.png', dpi=fig.dpi)
这会产生:(请记住,图形的边缘在数据坐标中为 <-0.5, -0.5>
,而不是 <0, 0>
。(即绘制图像的坐标以像素为中心)这就是 <0, 0>
产生的原因143, 55
,而不是 135, 48
)
143, 55
157, 69
171, 83
...
498, 410
512, 424
527, 439
当然,绘制图形只是为了在保存时再次绘制它是多余的并且计算量大。
为避免绘制两次,您可以将回调函数连接到绘制事件,并在该函数内输出您的 HTML 图像映射。举个简单的例子:
import numpy as np
import matplotlib.pyplot as plt
def print_pixel_coords(event):
fig = event.canvas.figure
ax = fig.axes[0] # I'm assuming there's only one subplot here...
for i in range(28):
x, y = ax.transData.transform_point([i,i])
print '%i, %i' % (x, fig.bbox.height - y)
fig = plt.figure()
ax = fig.add_subplot(111)
im = ax.imshow(np.random.random((27,27)), interpolation='nearest')
fig.canvas.mpl_connect('draw_event', print_pixel_coords)
fig.savefig('foo.png', dpi=fig.dpi)
这会产生正确的输出,同时在保存时只绘制一次图形:
143, 55
157, 69
171, 83
...
498, 410
512, 424
527, 439
另一个优点是您可以在调用 fig.savefig
时使用任何 dpi无需手动设置 fig
对象的 dpi 预先。因此,在使用回调函数的时候,直接做fig.savefig('foo.png')
即可。 , (或 fig.savefig('foo.png', dpi=whatever)
),您将获得与保存的 .png 文件匹配的输出。 (保存图形时默认的 dpi 是 100,而图形对象的默认 dpi 是 80,这就是为什么你必须首先指定 dpi 与 fig.dpi
相同)
希望这至少有点清楚!
关于python - 如何将 AxesImage 中的坐标映射到保存的图像文件中的坐标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4668432/
请看一下我的代码。 int main () { Program* allcommand = new Program; allcommand->addCommand("add", new
因此,当我遇到调试断言时,我正在编写代码。现在我很想知道为什么这段代码不起作用: for(Model::MeshMap::iterator it = obj1->GetMeshes().begin()
这是我上一个问题的延续 Group, Sum byType then get diff using Java streams . 按照建议,我应该作为单独的线程发布,而不是更新原始线程。 因此,通过我
我正在实现一些非常适合 map 的代码。但是,我要迭代的列表中有大量对象,所以我的问题是哪种方法是解决此问题的最佳方法: var stuff = $.map(listOfMyObjects, some
我正在尝试创建一个包含不同类的成员函数指针的映射。成员函数都具有相同的签名。为了做到这一点,我所有的类都继承了一个 Object 类,它只有默认构造函数、虚拟析构函数和一个虚拟 ToString()
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: how do you make a heterogeneous boost::map? 有可能在 C++ 中
我有一个 Mysql 查询,请检查以下内容: SELECT `tbl_classSubjects`.`classID` , `tbl_classSubjects`.`sectionID` , `tbl
抱歉,这可能是一个基本问题。 JNA直接映射和接口(interface)映射有什么区别? 我的解释是否正确: 直接映射 : 直接使用库对象(如 Java 中的静态 main) 接口(interface
在 Twitter's Scala school collections section ,它们显示了一个带有偏函数作为值的 Map: // timesTwo() was defined earlie
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。如需帮助澄清这个问题以便重新打开它,visit the help center .
据我了解,从 scala stdlib 声明一个映射并没有将其专门用于原始类型。我要的不是付出装箱/拆箱的代价,而是同时拥有scala map 的接口(interface)。一个明显的选择是使用 tr
如何为这样的 JSON 响应创建对象映射,它只是一个整数数组: [ 565195, 565309, 565261, 565515, 565292, 565281, 566346, 5
是否可以为 DTO 对象创建映射然后查询它们 而不是域?如果不解释为什么? 如果我需要几个 dtos 怎么办? DTos 是只读的 ID 由 NH 自动生成 将来这些 dtos 将设置映射到链接的 d
我有一个返回的函数(常规代码) [words: "one two", row: 23, col: 45] 在 Scala 中,我将上面更改为 Scala Map,但随后我被迫将其声明为 Map[Str
我有一组与 Vanilla 磅蛋糕烘焙相关的数据(200 行),具有 27 个特征,如下所示。标签caketaste是衡量烤蛋糕的好坏程度,由 bad(0) 定义, neutral(1) , good
我有试图映射到新代码的遗留代码。 OLD_PERSON pid sid name age NEW_PERSON pid sid fid age RESOLVE_PERSON pid fid statu
我有一个表,其中一个字段可以指向其他 3 个表之一中的外键,具体取决于鉴别器值是什么(Project、TimeKeep 或 CostCenter。通常这是用子类实现的,我想知道我有什么 注意子类名称与
我有一个类型 [ST s (Int, [Int])] 的绑定(bind)我正在尝试申请runST使用映射到每个元素,如下所示: name :: [ST s (Int, [Int])] --Of Cou
在我正在进行的项目中,我有以下实体:分析师、客户 和承包商。每个都继承自基类 User。 public abstract class User { public virtual int Id
我想知道是否可以在 Vim 中创建一个映射(对于普通模式),允许用户在映射执行之前输入。 我想为我最常用的 grep 命令创建一个快捷方式的映射。我希望命令允许输入我正在搜索的内容,然后在输入时执行。
我是一名优秀的程序员,十分优秀!