python打造光斑处理系统8:点击交互裁切

文章目录

    • 动作注册
    • 鼠标响应函数
    • 线段绘制

光斑处理:python处理高斯光束的图像
光斑处理系统:

  • 程序框架打开图像参数对话框/伪彩映射裁切ROI
  • 光强分布高斯拟合沿割线的灰度分布

动作注册

此前在图像裁切时,希望有一种点击模式,可以将鼠标点击的两个点框选起来。后来,在光斑分布时,也希望点击两个点,然后将两点连线所在区域的强度绘制出来。为了实现这个功能,需要实现点击交互。

在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

测试其裁切功能,效果如下

python打造光斑处理系统8:点击交互裁切_第1张图片

线段绘制

在交互函数中,引用了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()

运行结果如下,这个函数在一个图窗中绘制了两个子图,左图展现了刚刚点击的两点在图像上的连线,右侧表示这条红线上的灰度值。

python打造光斑处理系统8:点击交互裁切_第2张图片

你可能感兴趣的:(本科生实验,python,交互,鼠标点击交互,matplotlib,tkinter)