光斑处理:python处理高斯光束的图像
光斑处理系统:
此前在图像裁切时,希望有一种点击模式,可以将鼠标点击的两个点框选起来。后来,在光斑分布时,也希望点击两个点,然后将两点连线所在区域的强度绘制出来。为了实现这个功能,需要实现点击交互。
在matplotlib的tkinter画布中,提供了mpl_connect可以注册鼠标动作,所以可在AnaFacula的初始化代码中,插入此函数
# 前面是self.canvas.get_tk_widget().pack(...
self.canvas.mpl_connect('button_press_event',
self.on_button_event)
# 后面是self.toolbar = NavigationToolbar2Tk(...
考虑到这种交互并非实时需要的,只有在进入click模式,其返回的数值才有意义,所以需要一个全局变量来标识点击是否有效。另一方面,这些返回的数值需要进行存储,为此需要新建一个全局变量。
故而先在init_param函数中添加两个全局变量。
self.xyLst = []
self.btnFlag = 'void'
并且,btnFlag至少有三种模式,void表示什么也不做,当处于裁切点击时,为’cut’;当处于分布点击时,状态是’dist’。
然后设计点击函数的功能,点击两次图像时,激活相关的功能,若模式为"cut",则进行切割,若模式为"dist",则调用线段绘制函数。调用之后,释放保存的点,并将btnFlag重置为"void"。
def on_button_event(self,evt):
if self.btnFlag == "void":
return
self.xyLst.append([evt.xdata,evt.ydata])
if len(self.xyLst) <2 :
return
arr = np.sort(self.xyLst,0).astype(int)
if self.btnFlag == "cut":
self.cutPara['xStart'], self.cutPara['yStart'] = arr[0]
self.cutPara['xEnd'], self.cutPara['yEnd'] = arr[1]
self.imgCut()
elif self.btnFlag == "dist":
self.drawLine(self.xyLst[0], self.xyLst[1])
self.btnFlag = "void"
self.xyLst = []
然后,回到img_cut函数,为click模式添加功能
elif cutPara['mode'] == 'click':
self.btnFlag = "cut"
return
img_distri函数亦然
elif distriPara['mode'] == "click":
self.btnFlag = "dist"
return
测试其裁切功能,效果如下
在交互函数中,引用了drawLine,用于绘制光斑图像中任意两点连线中的灰度值分布,下面就来实现这个函数。首先,模仿割线均分的函数,做一个已知起止点而计算线上灰度值的函数,代码如下,由于和disByOneDeg逻辑相似,故不再赘述。
def distByStartEnd(img,start,end):
r = np.arange(np.sqrt(np.sum((np.array(start)-end)**2)))
x = np.linspace(start[0],end[0],len(r))
y = np.linspace(start[1],end[1],len(r))
xL,yD = np.floor([x,y]).astype(int)
xR,yU = xL+1,yD+1
xDL,xDR = 1-(x-xL),1-(xR-x)
yDD,yDU = 1-(y-yD),1-(yU-y)
px = img[yU,xL]*xDL*yDU+img[yU,xR]*xDR*yDU+\
img[yD,xL]*xDL*yDD+img[yD,xR]*xDR*yDD
return [r,px]
最后,线段绘制函数如下
def drawLine(self, st, ed):
r, px = distByStartEnd(self.img, st, ed)
self.fig.clf()
ax = self.fig.add_subplot(121)
ax.imshow(self.img)
ax.plot([st[0],ed[0]], [st[1], ed[1]], lw=1, color='r')
ax = self.fig.add_subplot(122)
ax.plot(r, px)
self.fig.tight_layout()
self.canvas.draw()
运行结果如下,这个函数在一个图窗中绘制了两个子图,左图展现了刚刚点击的两点在图像上的连线,右侧表示这条红线上的灰度值。