pyqt5 分割瓦片显示超大图像

在使用pyqt5显示超大遥感影像时,程序卡顿特别严重,遂实现了一种思路,将影像分割成较小的瓦片,然后循环显示到QGraphicsItem中,同时在分片的基础上实现了影像的缩放、平移、范围选取和点选取。

完整代码下载连接:https://download.youkuaiyun.com/download/ZH_CS/85527400icon-default.png?t=M4ADhttps://download.youkuaiyun.com/download/ZH_CS/85527400

mport pyqtgraph as pg
from PyQt5.QtCore import Qt, QRectF, pyqtSignal
from PyQt5.QtGui import QColor, QPalette, QPixmap
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene

from view.image.ImageItem import ImageItem


class ImageView(QGraphicsView):
    # 鼠标悬停像素的信号
    signal_pixel_selected = pyqtSignal(str, int)
    signal_progress = pyqtSignal(object, object)

    item: ImageItem = None
    pixmap: QPixmap = None
    # 影像名称和item的对应关系
    item_dict = {}

    def __init__(self):
        super(ImageView, self).__init__()
        pg.ImageView()
        pg.ImageItem()
        self.QImg = None
        self.image = None
        self.image_array = None
        self.background_color = QColor()
        self.background_color.setNamedColor('#ffffff')
        self.palette = QPalette()
        self.palette.setColor(QPalette.Window, self.background_color)
        self.__init_view()

    def __init_view(self):
        self.setAutoFillBackground(True)
        self.setPalette(self.palette)
        self.setAlignment(Qt.AlignCenter)
        # 创建场景
        self.scene = QGraphicsScene()

    # 显示整幅图像
    def showImage(self):
        self.setSceneRect(QRectF(-(self.width() / 2), -(self.height() / 2), self.width() - 10, self.height() - 10))
        self.setScene(self.scene)
        self.item = ImageItem(self.image, self.signal_pixel_selected, self.signal_progress)
        self.item.setQGraphicsViewWH(self.width(), self.height())
        self.scene.clear()
        self.scene.addItem(self.item)

    def showLayer(self, image):
        self.image = image
        if image is None:
            return
        self.image = image
        self.showImage()

    # 清理显示的图层
    def cleanLayer(self, image):
        self.scene.clear()

    # 设置图像的显示状态
    def setItemStatus(self, status, tool):
        if self.item is not None:
            self.item.setStatus(status)
            self.item.setCurrentTool(tool)

 影像显示控件继承了QGraphicsItem,在这里实现缩放和平移

from PyQt5.QtCore import Qt, QPoint, QRectF
from PyQt5.QtGui import QPainter, QPixmap, QColor, QPen, QImage
from PyQt5.QtWidgets import QStyleOptionGraphicsItem, QWidget, QGraphicsItem, QApplication

from image import OpticalImage
from system.System import System


class ImageItem(QGraphicsItem):

    def __init__(self, image: OpticalImage, signal_pixel_selected, signal_progress):
        super(ImageItem, self).__init__()
        # 影像在横轴偏移量
        self.w_offset = 0
        # 影像在纵轴的偏移量
        self.h_offset = 0
        # 鼠标当前所在的像素位置
        self.w_cur_pos = 0
        self.h_cur_pos = 0
        # 当前正在显示的影像
        self.image = None
        # 信号
        self.signal_pixel_selected = None
        # 选择状态
        self.image_view_status = System.v_image_show
        # 当前的矩形几何
        self.show_rect = []
        # 当前选择的点
        self.show_point = []
        # 当前正在画的点
        self.current_paint_point = None
        # 当前正在画的矩形
        self.current_paint_rect = None
        # 当前鼠标按下的键
        self.mouse_click_button = None
        # pixmap瓦片
        self.pixmap_tiles = {}

        self.image = image
        self.setAcceptDrops(True)
        self.m_scaleValue = 1
        self.m_scaleDafault = 1
        self.m_isMove = False
        self.m_isRect = False
        self.m_startPos = None
        self.setAcceptHoverEvents(True)
        self.signal_pixel_selected = signal_pixel_selected
        self.signal_progress = signal_progress

        self.currentTool = System.v_image_show
        self.setStatus(System.v_image_show)
        self.create_pixmap_tiles()

    def boundingRect(self):
        """
        重写原有方法
        :return:
        """
        self.w_offset = int(self.image.width / 2)
        self.h_offset = int(self.image.height / 2)
        return QRectF(-self.w_offset, -self.h_offset, self.image.width, self.image.height)

    def paint(self, painter, const, widget=None):
        """
        重写方法
        :param painter:
        :param const:
        :param widget:
        :return:
        """
        self.painter_tiles(painter)
        self.paintShowChecked(painter, const, widget)

    def painter_tiles(self, painter):
        """
        将影像瓦片展示到控件
        :param painter:
        :return:
        """
        tiles_size = self.image.tiles.size
        length = len(self.pixmap_tiles)
        cur = 0
        for key, value in self.pixmap_tiles.items():
            h_index, w_index = key
            h_offset = h_index * tiles_size - self.h_offset
            w_offset = w_index * tiles_size - self.w_offset
            if value is None:
                continue
            painter.drawPixmap(w_offset, h_offset, value)
            cur = cur + 1

    def create_pixmap_tiles(self):
        """
        根据显示的图层创建pixmap的瓦片
        :return:
        """
        length = len(self.image.get_show_layer())
        cur = 0
        for key, value in self.image.get_show_layer().items():
            pixmap = self.create_pixmap(value)
            self.pixmap_tiles[key] = pixmap
            cur = cur + 1
            System.signal.signal_progress.emit("正在创建瓦片:", cur * 100 / length)
            QApplication.processEvents()
        print("pixmap瓦片创建完成")
        # self.image.start_image_static()

    def create_pixmap(self, image_array):
        """
        根据给定的数组生成pixmap
        :param image_array:
        :return:
        """
        shape = image_array.shape
        height = 0
        width = 0
        bytesPerComponent = 1
        if len(shape) == 2:
            height, width = shape
        elif len(shape) == 3:
            height, width, bytesPerComponent = shape
        bytesPerLine = bytesPerComponent * width
        if bytesPerComponent == 1:
            # 显示灰度图像
            QImg = QImage(image_array.tobytes(), width, height, bytesPerLine, QImage.Format_Grayscale8)
        elif bytesPerComponent == 3:
            # 显示GGB图像
            QImg = QImage(image_array.tobytes(), width, height, bytesPerLine, QImage.Format_RGB888)
        else:
            # 如果不符合就不显示
            return
        return QPixmap.fromImage(QImg)

    def paintEvent(self):
        pass

    # 将主界面的控件QGraphicsView的width和height传进本类中,并根据图像的长宽和控件的长宽的比例来使图片缩放到适合控件的大小
    def setQGraphicsViewWH(self, nwidth: int, nheight: int):
        nImgWidth = self.image.width
        nImgHeight = self.image.height
        t_width = nwidth / nImgWidth
        t_height = nheight / nImgHeight
        if t_width > t_height:
            self.m_scaleDafault = t_height
        else:
            self.m_scaleDafault = t_width
        self.setSca
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZH_CS

随缘吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值