You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在silx viewer Plot2D中实现滑块切换时图像修改持久化?

问题描述

使用自定义silx viewer可视化单个HDF5文件中的系列图像时,默认Plot2D组件的滑块可切换图像:
滑块浏览图像

已实现一个自定义SumAction,功能是给图像每个像素加100,但切换滑块时之前的修改会消失。希望实现:当SumAction按钮处于勾选状态时,切换图像自动执行修改,让效果看起来持久化。

现有核心代码片段:

class SumAction(PlotAction):
    def __init__(self, plot, parent=None):
    
        sum_icon = qt.QIcon("./matrix.png")
        
        super(SumAction, self).__init__(
            plot, icon=sum_icon, text='Sum',
            tooltip='Sum 100 to each image pixel.',
            triggered=self.__sum,
            checkable=True, parent=parent)

    def __sum(self, checked):
        activeImage = self.plot.getActiveImage()
        if activeImage is None:
            qt.QMessageBox.information(
                self.plot,
                "Plot data is None. Open a valid 2D image to use this function."
            )
            
        data = activeImage.getData()
        self.originalData = activeImage.getData()
        data+=100
        activeImage.setData(data)
解决方案

不需要重写滑块函数,通过监听Plot2D的图像切换信号,结合SumAction的勾选状态,自动对新切换的图像应用修改即可。关键是要保存每个图像的原始数据,避免重复叠加修改,同时在图像切换时触发处理逻辑。

修改后的完整代码如下:

#!/usr/bin/env python

import sys
import numpy

from silx.gui import qt

def createWindow(parent, settings):
    # Local import to avoid early import (like h5py)
    # Some libraries have to be configured first properly
    from silx.gui.plot.actions import PlotAction
    from silx.app.view.Viewer import Viewer
    from silx.app.view.ApplicationContext import ApplicationContext
        
    class SumAction(PlotAction):
        def __init__(self, plot, parent=None):
            sum_icon = qt.QIcon("./matrix.png")
            super(SumAction, self).__init__(
                plot, icon=sum_icon, text='Sum',
                tooltip='Sum 100 to each image pixel.',
                triggered=self.__sum,
                checkable=True, parent=parent)
            
            # 存储每个图像的原始数据,以图像对象为键
            self.original_data_map = {}
            # 监听活动图像变化信号
            self.plot.activeImageChanged.connect(self.__onImageChanged)

        def __sum(self, checked):
            active_image = self.plot.getActiveImage()
            if active_image is None:
                qt.QMessageBox.information(
                    self.plot,
                    "Plot data is None. Open a valid 2D image to use this function."
                )
                return
            
            if checked:
                # 保存原始数据(仅第一次勾选时保存)
                if active_image not in self.original_data_map:
                    self.original_data_map[active_image] = active_image.getData().copy()
                # 应用修改
                modified_data = self.original_data_map[active_image] + 100
                active_image.setData(modified_data)
            else:
                # 取消勾选时恢复原始数据
                if active_image in self.original_data_map:
                    active_image.setData(self.original_data_map[active_image])

        def __onImageChanged(self, new_image, old_image):
            # 切换图像时,如果按钮处于勾选状态,自动应用修改
            if self.isChecked() and new_image is not None:
                if new_image not in self.original_data_map:
                    self.original_data_map[new_image] = new_image.getData().copy()
                modified_data = self.original_data_map[new_image] + 100
                new_image.setData(modified_data)
                            
    class MyApplicationContext(ApplicationContext):
        """This class is shared to all the silx view application."""
    
        def findPrintToolBar(self, plot):
            # FIXME: It would be better to use the Qt API
            return plot._outputToolBar

        def viewWidgetCreated(self, view, widget):
            """Called when the widget of the view was created.

            So we can custom it.
            """
            from silx.gui.plot import Plot2D
            if isinstance(widget, Plot2D):
                toolBar = self.findPrintToolBar(widget)
                action = SumAction(widget, widget)
                toolBar.addAction(action)

    class MyViewer(Viewer):
        def createApplicationContext(self, settings):
            return MyApplicationContext(self, settings)

    window = MyViewer(parent=parent, settings=settings)
    window.setWindowTitle(window.windowTitle() + " [custom]")
    return window


def main(args):
    from silx.app.view import main as silx_view_main
    # Monkey patch the main window creation
    silx_view_main.createWindow = createWindow
    # Use the default launcher
    silx_view_main.main(args)


if __name__ == '__main__':
    main(sys.argv)

关键修改说明:

  • 添加original_data_map字典,存储每个图像对象对应的原始数据,避免重复叠加修改(防止多次切换后像素值持续增加)。
  • 连接plot.activeImageChanged信号到__onImageChanged槽函数,当切换图像时自动触发修改逻辑。
  • 在__sum函数中,勾选时保存原始数据并应用修改;取消勾选时恢复原始数据。
  • 在__onImageChanged函数中,检测到按钮勾选且有新图像时,自动对新图像应用修改。

内容的提问来源于stack exchange,提问作者Marco Montevechi Filho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 07:35:58