ImagePy经过一次大的重构后,软件架构有了很大改变,将前端UI和后端数据结构进行了解耦:
- sciapp是一套数据接口,包含图像Image、网格Mesh、表格Table、几何矢量Shape等基础数据结构;
- sciwx是符合sciapp接口标准的可视化组件库;
- ImagePy是后端基于sciapp、前端基于sciwx的一个插件集,包含了大量常用的图像处理算法等。
因此可以很容易地基于分离后的sciapp和sciwx构建自定义的独立图像处理软件。
Sciapp版Hello World
1 | import wx |
结果如图:
可以看出,自定义的app需要继承sciwx库的CanvasNoteFrame以及sciapp的App类,并对其初始化。
添加图像
上例是张空白的画布,这里对其添加一张图像,供后面进行操作。
1 | import wx |
如上,添加两行代码即可完全对图像的添加和显示。
结果如图:

首先,获取notebook并对其添加画布:
1 | canvas = hello.notebook.add_canvas() |
然后,在画布上添加图像:
1 | canvas.set_img(astronaut()) |
如果是展示图像序列,则:
1 | canvas.set_imgs([astronaut(), 255-astronaut()]) |
结果如图:

注意,这里展示的是图像序列,因此两张图像都显示在同一个标签页下,通过下方的滑动条进行切换。
如果是想多标签页显示,那么:
1 | canvas2 = hello.notebook.add_canvas() |
即新添加一个画布,再设置图像,结果如图:

添加工具
为自己的app添加一个画笔工具:
1 | import wx |
效果如图:

解析如下:
在app中添加自定义的工具时,需要继承sciapp中提供的ImageTool基类:
1 | from sciapp.action import ImageTool |
然后再根据自己的需求重载四个鼠标事件:
1 | def mouse_down(self, ips, x, y, btn, **key): pass |
这四个函数的参数意义为:
从中也可以看出自定义工具中可以调用的接口:
(1)ips:即画布承载的Image对象,该对象即sciapp中定义的统一的图像数据结构
(2)x和y:当前鼠标所在的图像像素坐标,水平方向是x方向,垂直方向是y方向。btn是鼠标按键,1为左键按下,2为中键按下,3为右键按下,key是字典,里面有多个字段,key[‘alt’]代表是否按下alt键,key[‘ctrl’]代表是否按下ctrl键,key[‘shift’]代表是否按下shift键,key[‘px’]返回鼠标当前的画布x坐标,key[‘py’]返回画布y坐标,key[‘canvas’]返回该画布自身。
然后在app中添加工具条:
1 | tool = hello.add_toolbar() |
如果想添加多个工具,多次调用add_tool即可。
添加菜单
为自己的app添加菜单(即插件),这里以添加高斯模糊插件为例:
1 | import wx |
效果如图:

解析如下:
首先自定义插件需要继承sciapp提供的ImgAction基类,即:
1 | from sciapp.action import ImgAction |
然后在自己的插件类中重载run()方法:
1 | def run(self, ips, img, snap, para): |
这里的四个参数的意义分别是:
(1)ips即sciapp中定义的Image图像封装;
(2)img即ips中的当前实际的图像;
(3)snap是当前图像在处理之前的拷贝,这样就可以做回退操作;
(4)para是参数对话框,用于与用户进行参数设置的交互。上面代码中没有提供该对话框,稍后添加代码实现这一功能。
编写完自己的插件后,需要添加到app中:
1 | hello.add_img(canvas.image) |
上面两行是将当前画布的图像及其窗口添加到总控全局的App管理器中,这样插件才能识别到当前图像。
下面两行是添加菜单栏,Filter是一级菜单,Gaussian是二级菜单,如果想添加多个菜单项,可以在相应位置以字典的形式加入,比如:
1 | menu.load(('menu',[('Filter',[('Gaussian', Gaussian), |
前面说了,上述代码中的滤波器的标准差sigma的值是“写死”的,即固定为2,下面添加代码使得显示出参数对话框方便用户交互:
1 | from sciwx.widgets import ParaDialog |
这里应用了sciwx提供的ParaDialog组件,关于ParaDialog的详细解析可以参见之前的一篇文章:
ImagePy解析:18 — 参数对话框ParaDialog详解
效果如下:
添加“打开文件”插件
“打开文件”是一个非常重要的功能,因为它赋予用户通过图形界面打开图像的权利(前面的例子都是在程序中将图像“硬读入”)。
之所以将“打开文件”插件单独拿出来,是因为它涉及的操作比高斯模糊插件更多:获取文件路径并添加图像等,所重载的函数也稍稍不同。见下方源码:
1 | import wx |
主要增添了如下代码块:
(1)在app中增加路径读取模块,即:
1 | def getpath(self, title, filt, io, name=''): |
(2)在插件OpenFile中重载start()方法,而不是run()方法,因为它不涉及图像操作:
1 | def start(self, app, para = None): |
(3)在app中增加添加和显示图像的模块,即:
1 | def show_img(self, img, title): |
原理就是之前的添加canvas和向App管理器中添加图像。
一个完整demo
下面给出一个完整demo,包括“打开文件”和“高斯滤波”这两个菜单插件,及“画笔”和“矩形ROI”这两个工具。
1 | import wx |
效果如图:

更多
管理器、表格、网格等。