在工作中有时会遇到一些需要从图像中提取数据点的情况。例如文献中展示了图像,却没有给出相应的数据。如果只是定性的比较,不一定需要联系作者索要数据。可以简单地通过一些软件来得到近似的数据。比如老牌的Origin,轻量级的 GetData Graph Digitizer,或者免费的 Graphixy 不过这三个都是Windows下的软件,在Linux/UNIX 和 Mac 下,可以考虑 WebPlotDigitizer ,或者直接使用它的在线版。
我是觉得这个功能不难,就用Python 写了一个脚本,使用pynput模块获取鼠标的屏幕位置,总共也就50行左右的代码。原理是用鼠标的屏幕坐标进行归算,所以图片越大,屏幕分辨率越高,获得的数据精度就会越好。做粗略的比较展示足够了,但要发表还是应该老老实实找原作者请求数据。
在调用时给定图像的xy轴边界,然后用鼠标依次点击图像四个顶点进行标定,接下来用鼠标左键单击需要提取的数据点即可,单击右键退出。就可以在终端和工作目录下看到提取的数据了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
from pynput.mouse import Listener,Button import numpy as np def grabdata(): points = [] def on_click(x, y, button, pressed): if pressed: print(x,y,button,pressed) points.append([x, y]) if button == Button.right: return False with Listener(on_click=on_click) as listener: listener.join() return points def main(boundary,flag=""): boundary = np.array(boundary) positions = grabdata() print(positions) data = np.array(positions) if flag == "loglog": boundary = np.log10(boundary) elif flag == "xlog": boundary[0] = np.log10(boundary[0]) elif flag == "ylog": boundary[1] = np.log10(boundary[1]) print(boundary) # convert zero point from left-top to left-bottom data[:,1] = np.max(data[:,1]) - data[:,1] resu = (data - np.min(data,axis=0))/(np.max(data,axis=0)-np.min(data,axis=0)) * (boundary[:,1]-boundary[:,0]) + boundary[:,0] if flag == "loglog": resu = 10**resu elif flag == "xlog": resu[0] = 10**resu[0] elif flag == "ylog": resu[1] = 10**resu[1] print("DATA:\n",resu) np.savetxt("data.txt",resu[4:]) if __name__ == "__main__": main(boundary=[[0,1],[0,1]]) |