将 FITS 图像绑定到 Python 中的 tkinter canvas
Bind FITS image to tkinter canvas in Python
请参阅代码块下方的要点以获取快速摘要
为了研究,我正在尝试在 python 中编写一个测光程序(我知道那里有软件,但我自己编写是有特定原因的)。我将 Anaconda 与 Python 3.6 一起使用,并且可以获得 FITS 文件图像进行渲染,但我希望能够单击一个点并执行光度测量。
基本上我想将图像绑定到 tkinter canvas 并在 return 位置有一个点击事件。
我一直在看几乎完全相同的问题 here,但主要区别在于我使用的是 FITS 文件和 python 3.6(它改变了很多功能在那个例子中)
到目前为止,我的代码(使用了该示例中的大部分内容)是:
import numpy as np
import matplotlib.pyplot as plt
from astropy.io import fits
import scipy as sp
import tkinter as tk
import PIL
hdulist = fits.open('00000039.sat_26624U.fit')
hdulist.info()
scidata = hdulist[0].data
histo = sp.histogram(scidata, 60, None, True)
display_min = histo[1][0]
display_max = histo[1][1]
pic = plt.imshow(scidata, cmap=plt.cm.gray, vmin=display_min, vmax=display_max, origin="lower")
#Try tk stuff
root = tk.Tk()
#setting up a tkinter canvas
frame = tk.Frame(root, bd=2, relief=tk.SUNKEN)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
canvas = tk.Canvas(frame, bd=0)
canvas.grid(row=0, column=0, sticky=tk.N+tk.S+tk.E+tk.W)
frame.pack(fill=tk.BOTH,expand=1)
#Add image
hold = tk.PhotoImage(pic)
canvas.create_image(0,0,image=hold,anchor="nw")
#function to be called when mouse is clicked
def printcoords(event):
#outputting x and y coords to console
print (event.x,event.y)
#mouseclick event
canvas.bind("<Button 1>",printcoords)
root.mainloop()
hdulist.close()
它显示了图像,但在以下位置给我一个错误:
#Add image
hold = tk.PhotoImage(pic)
canvas.create_image(0,0,image=hold,anchor="nw")
也就是说:
类型错误:__str__ returned 非字符串(类型 AxesImage)
要点:
我无法将 FITS 图像绑定到 tkinter canvas。我不知道如何单击该图像并获取鼠标单击的位置。我希望能够点击几个点,得到它们的位置,然后用这些位置画出几个圆环。
我还有很多其他问题,但这是我现在的主要问题。最终我将尝试跟踪它们(移动到下一张图片并搜索大致相同的区域,直到我再次找到该对象,放置环形空间)并计算里面的像素,但我可以稍后穿过那座桥(除非现在有人有想法).
您必须对代码进行一些更改。首先,我更愿意在 Tkinter 中使用 Place() 方法。你可以在这里查看地方方法
第二件事:通过使用 place 方法,它将适合您的应用程序。
提示:Place() 方法适用于 x 和 y 坐标。因此,这两个元素可以在 Tkinter 中使用 Place() 重叠,但在 Grid 中是不可能的。
现在使用 Place() 方法将图像放置在 Tkinter 的某个区域 window 假设图像大小为 100x100,然后使用函数调用制作一个按钮并将其放在图像后面,给出相同的坐标- Place() 方法中的坐标。因此,当用户单击图像时,它实际上会调用按钮后面的函数。
与一些人交谈后,我发现问题在于 tkinter canvas 需要 .gif 或 .png 等文件类型才能将图像绑定到 canvas。所以我改变了
pic = plt.imshow(scidata, cmap=plt.cm.gray, vmin=display_min, vmax=display_max, origin="lower")
到
plt.imsave("tempimgfile.gif", scidata, cmap=plt.cm.gray, vmin=display_min, vmax=display_max, origin="lower")
和
hold = tk.PhotoImage(pic)
到
hold = tk.PhotoImage(file="tempimgfile.gif")
将我的 numpy 数组保存为 gif 文件,长度刚好足以绑定,然后删除它。
底线:将 FITS 文件转换为 .gif 或其他兼容类型
它可能不是最优雅的修复方法,但它确实有效
请参阅代码块下方的要点以获取快速摘要
为了研究,我正在尝试在 python 中编写一个测光程序(我知道那里有软件,但我自己编写是有特定原因的)。我将 Anaconda 与 Python 3.6 一起使用,并且可以获得 FITS 文件图像进行渲染,但我希望能够单击一个点并执行光度测量。
基本上我想将图像绑定到 tkinter canvas 并在 return 位置有一个点击事件。
我一直在看几乎完全相同的问题 here,但主要区别在于我使用的是 FITS 文件和 python 3.6(它改变了很多功能在那个例子中)
到目前为止,我的代码(使用了该示例中的大部分内容)是:
import numpy as np
import matplotlib.pyplot as plt
from astropy.io import fits
import scipy as sp
import tkinter as tk
import PIL
hdulist = fits.open('00000039.sat_26624U.fit')
hdulist.info()
scidata = hdulist[0].data
histo = sp.histogram(scidata, 60, None, True)
display_min = histo[1][0]
display_max = histo[1][1]
pic = plt.imshow(scidata, cmap=plt.cm.gray, vmin=display_min, vmax=display_max, origin="lower")
#Try tk stuff
root = tk.Tk()
#setting up a tkinter canvas
frame = tk.Frame(root, bd=2, relief=tk.SUNKEN)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
canvas = tk.Canvas(frame, bd=0)
canvas.grid(row=0, column=0, sticky=tk.N+tk.S+tk.E+tk.W)
frame.pack(fill=tk.BOTH,expand=1)
#Add image
hold = tk.PhotoImage(pic)
canvas.create_image(0,0,image=hold,anchor="nw")
#function to be called when mouse is clicked
def printcoords(event):
#outputting x and y coords to console
print (event.x,event.y)
#mouseclick event
canvas.bind("<Button 1>",printcoords)
root.mainloop()
hdulist.close()
它显示了图像,但在以下位置给我一个错误:
#Add image
hold = tk.PhotoImage(pic)
canvas.create_image(0,0,image=hold,anchor="nw")
也就是说:
类型错误:__str__ returned 非字符串(类型 AxesImage)
要点:
我无法将 FITS 图像绑定到 tkinter canvas。我不知道如何单击该图像并获取鼠标单击的位置。我希望能够点击几个点,得到它们的位置,然后用这些位置画出几个圆环。
我还有很多其他问题,但这是我现在的主要问题。最终我将尝试跟踪它们(移动到下一张图片并搜索大致相同的区域,直到我再次找到该对象,放置环形空间)并计算里面的像素,但我可以稍后穿过那座桥(除非现在有人有想法).
您必须对代码进行一些更改。首先,我更愿意在 Tkinter 中使用 Place() 方法。你可以在这里查看地方方法
第二件事:通过使用 place 方法,它将适合您的应用程序。
提示:Place() 方法适用于 x 和 y 坐标。因此,这两个元素可以在 Tkinter 中使用 Place() 重叠,但在 Grid 中是不可能的。
现在使用 Place() 方法将图像放置在 Tkinter 的某个区域 window 假设图像大小为 100x100,然后使用函数调用制作一个按钮并将其放在图像后面,给出相同的坐标- Place() 方法中的坐标。因此,当用户单击图像时,它实际上会调用按钮后面的函数。
与一些人交谈后,我发现问题在于 tkinter canvas 需要 .gif 或 .png 等文件类型才能将图像绑定到 canvas。所以我改变了
pic = plt.imshow(scidata, cmap=plt.cm.gray, vmin=display_min, vmax=display_max, origin="lower")
到
plt.imsave("tempimgfile.gif", scidata, cmap=plt.cm.gray, vmin=display_min, vmax=display_max, origin="lower")
和
hold = tk.PhotoImage(pic)
到
hold = tk.PhotoImage(file="tempimgfile.gif")
将我的 numpy 数组保存为 gif 文件,长度刚好足以绑定,然后删除它。
底线:将 FITS 文件转换为 .gif 或其他兼容类型
它可能不是最优雅的修复方法,但它确实有效