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

Qt图像蒙版区域复制异常:仅左上角起始选择有效

蒙版区域复制异常问题:仅左上角起始绘制正常,其他角落出错

我实现了为图像添加蒙版并将蒙版内区域复制至另一图像的功能,但仅当从图像左上角开始绘制蒙版时功能正常,从其他角落起始绘制时,复制的区域会出现错误。我尝试通过判断蒙版选择的顺时针/逆时针方向来修正该问题,但并未奏效。

原实现代码

def add_mask(self):
    self.analysis_image_duplicate.mousePressEvent = self.start_mask
    self.analysis_image_duplicate.mouseMoveEvent = self.update_mask
    self.analysis_image_duplicate.mouseReleaseEvent = self.end_mask

    # Enable the select_roi_button once the add_mask_button has been clicked
    self.select_roi_button.setEnabled(True)

# Function to handle the start of the mask drawing process
def start_mask(self, event):
    rel_position = calc_relative_position(event.pos(), self.analysis_image.pixmap())
    self.mask_rect = QtCore.QRect(rel_position, rel_position)
    self.apply_mask()

# Function to update the mask during the drawing process
def update_mask(self, event):
    rel_position = calc_relative_position(event.pos(), self.analysis_image.pixmap())
    self.mask_rect.setBottomRight(QtCore.QPoint(rel_position.x(), rel_position.y()))
    self.apply_mask()

# Function to handle the end of the mask drawing process
def end_mask(self, event):
    self.update_mask(event)
    self.analysis_image_duplicate.mousePressEvent = self.start_mask
    self.analysis_image_duplicate.mouseMoveEvent = self.update_mask
    self.analysis_image_duplicate.mouseReleaseEvent = self.end_mask

    max_allowed_width = int(250 / self.scale_factor)
    if self.mask_rect.width() > max_allowed_width:
        self.mask_rect.setWidth(max_allowed_width)
        QMessageBox.warning(self, 'Warning', f'Mask area Width cannot exceed 250. Width reduced to 250.',
                            QMessageBox.Ok)

    max_allowed_height = int(1200 / self.scale_factor)
    if self.mask_rect.height() > max_allowed_height:
        self.mask_rect.setHeight(max_allowed_height)
        QMessageBox.warning(self, 'Warning', f'Mask area Height cannot exceed 1200. Height reduced to 1200.',
                            QMessageBox.Ok)

    self.roi_rect = QtCore.QRect(
        self.mask_rect.left(),
        self.mask_rect.top(),
        1,
        self.mask_rect.height()
    )

    self.roi_button = QPushButton(self.analysis_image_duplicate)
    self.roi_button.setGeometry(
        self.mask_rect.right() - 5,
        self.mask_rect.top(),
        5,
        self.mask_rect.height()
    )
    self.roi_button.setCursor(QtCore.Qt.SizeHorCursor)
    self.roi_button.installEventFilter(self)

    self.apply_mask()

# Function to apply the mask to the analysis image
def apply_mask(self):
    if self.analysis_image.pixmap():
        mask_pixmap = self.analysis_image.pixmap().copy()
        painter = QPainter(mask_pixmap)
        painter.setPen(QPen(Qt.red, 1))
        painter.drawRect(self.mask_rect)

        if self.roi_rect:
            painter.setPen(QPen(Qt.green, 1))
            painter.drawRect(self.roi_rect)

        painter.end()

        display_image(self.analysis_image_duplicate, mask_pixmap)

        self.apply_mask_to_template()

# Function to apply the mask to the template image and copy the ROI
def apply_mask_to_template(self):
    if self.template_image.pixmap():
        self.mask_pixmap = self.template_image.pixmap().copy()
        painter = QPainter(self.mask_pixmap)

        if self.analysis_image.pixmap():
            analysis_pixmap = self.analysis_image.pixmap().copy(self.mask_rect)

            # Shift analysis_pixmap to paste_point's coordinates, adjusting for height
            self.target_rect = QtCore.QRect(self.paste_point.x(), self.paste_point.y() - self.mask_rect.height(),
                                            self.mask_rect.width(), self.mask_rect.height())
            painter.drawPixmap(self.target_rect, analysis_pixmap)

        # Set the pen for drawing the blue lines
        painter.setPen(QPen(Qt.blue, 1, Qt.DashLine))

        # Draw blue lines that cross
        top_line_start = QtCore.QPoint(0, self.target_rect.top())
        top_line_end = QtCore.QPoint(self.mask_pixmap.width(), self.target_rect.top())
        bottom_line_start = QtCore.QPoint(0, self.target_rect.bottom())
        bottom_line_end = QtCore.QPoint(self.mask_pixmap.width(), self.target_rect.bottom())
        left_line_start = QtCore.QPoint(self.target_rect.left(), 0)
        left_line_end = QtCore.QPoint(self.target_rect.left(), self.mask_pixmap.height())
        right_line_start = QtCore.QPoint(self.target_rect.right(), 0)
        right_line_end = QtCore.QPoint(self.target_rect.right(), self.mask_pixmap.height())

        painter.drawLine(top_line_start, top_line_end)
        painter.drawLine(bottom_line_start, bottom_line_end)
        painter.drawLine(left_line_start, left_line_end)
        painter.drawLine(right_line_start, right_line_end)

        if self.roi_rect and self.paste_point:
            painter.setPen(QPen(Qt.green, 1))

            roi_top_left = QtCore.QPoint(max(self.roi_rect.left() - self.mask_rect.left(), 0),
                                         max(self.roi_rect.top() - self.mask_rect.top(), 0))
            roi_bottom_right = QtCore.QPoint(
                min(self.roi_rect.right() - self.mask_rect.left(), self.target_rect.width()),
                min(self.roi_rect.bottom() - self.mask_rect.top(), self.target_rect.height()))
            limited_roi_rect = QtCore.QRect(self.target_rect.topLeft() + roi_top_left,
                                            self.target_rect.topLeft() + roi_bottom_right)

            painter.drawRect(limited_roi_rect)

        # Create left and right part of the mask pixmap
        self.left_part = self.mask_pixmap.copy(0, 0, self.target_rect.left(), self.mask_pixmap.height())
        self.right_part = self.mask_pixmap.copy(self.target_rect.right(), 0,
                                                self.mask_pixmap.width() - self.target_rect.right(),
                                                self.mask_pixmap.height())

        painter.end()

        display_image(self.template_image_duplicate, self.mask_pixmap)
        self.copy_roi_to_template()

尝试修复的代码(未解决问题)

def add_mask(self):
    self.analysis_image_duplicate.mousePressEvent = self.start_mask
    self.analysis_image_duplicate.mouseMoveEvent = self.update_mask
    self.analysis_image_duplicate.mouseReleaseEvent = self.end_mask

    # Enable the select_roi_button once the add_mask_button has been clicked
    self.select_roi_button.setEnabled(True)

# Function to handle the start of the mask drawing process
def start_mask(self, event):
    rel_position = calc_relative_position(event.pos(), self.analysis_image.pixmap())
    self.mask_rect = QtCore.QRect(rel_position, rel_position)
    self.apply_mask()

# Function to update the mask during the drawing process
def update_mask(self, event):
    rel_position = calc_relative_position(event.pos(), self.analysis_image.pixmap())
    self.mask_rect.setBottomRight(QtCore.QPoint(rel_position.x(), rel_position.y()))
    self.apply_mask()

# Function to handle the end of the mask drawing process
def end_mask(self, event):
    self.update_mask(event)
    self.analysis_image_duplicate.mousePressEvent = self.start_mask
    self.analysis_image_duplicate.mouseMoveEvent = self.update_mask
    self.analysis_image_duplicate.mouseReleaseEvent = self.end_mask

    max_allowed_width = int(250 / self.scale_factor)
    if self.mask_rect.width() > max_allowed_width:
        self.mask_rect.setWidth(max_allowed_width)
        QMessageBox.warning(self, 'Warning', f'Mask area Width cannot exceed 250. Width reduced to 250.',
                            QMessageBox.Ok)

    max_allowed_height = int(1200 / self.scale_factor)
    if self.mask_rect.height() > max_allowed_height:
        self.mask_rect.setHeight(max_allowed_height)
        QMessageBox.warning(self, 'Warning', f'Mask area Height cannot exceed 1200. Height reduced to 1200.',
                            QMessageBox.Ok)

    self.roi_rect = QtCore.QRect(
        self.mask_rect.left(),
        self.mask_rect.top(),
        1,
        self.mask_rect.height()
    )

    self.roi_button = QPushButton(self.analysis_image_duplicate)
    self.roi_button.setGeometry(
        self.mask_rect.right() - 5,
        self.mask_rect.top(),
        5,
        self.mask_rect.height()
    )
    self.roi_button.setCursor(QtCore.Qt.SizeHorCursor)
    self.roi_button.installEventFilter(self)

    self.apply_mask()

# Function to apply the mask to the analysis image
def apply_mask(self):
    if self.analysis_image.pixmap():
        mask_pixmap = self.analysis_image.pixmap().copy()
        painter = QPainter(mask_pixmap)
        painter.setPen(QPen(Qt.red, 1))
        painter.drawRect(self.mask_rect)

        if self.roi_rect:
            painter.setPen(QPen(Qt.green, 1))
            painter.drawRect(self.roi_rect)

        painter.end()

        display_image(self.analysis_image_duplicate, mask_pixmap)

        self.apply_mask_to_template()

# Function to apply the mask to the template image and copy the ROI
def apply_mask_to_template(self):
    if self.template_image.pixmap():
        self.mask_pixmap = self.template_image.pixmap().copy()
        painter = QPainter(self.mask_pixmap)

        if self.analysis_image.pixmap():
            analysis_pixmap = self.analysis_image.pixmap().copy(self.mask_rect)

            # Shift analysis_pixmap to paste_point's coordinates, adjusting for height
            self.target_rect = QtCore.QRect(self.paste_point.x(), self.paste_point.y() - self.mask_rect.height(),
                                            self.mask_rect.width(), self.mask_rect.height())
            painter.drawPixmap(self.target_rect, analysis_pixmap)

        # Set the pen for drawing the blue lines
        painter.setPen(QPen(Qt.blue, 1, Qt.DashLine))

        # Draw blue lines that cross
        top_line_start = QtCore.QPoint(0, self.target_rect.top())
        top_line_end = QtCore.QPoint(self.mask_pixmap.width(), self.target_rect.top())
        bottom_line_start = QtCore.QPoint(0, self.target_rect.bottom())
        bottom_line_end = QtCore.QPoint(self.mask_pixmap.width(), self.target_rect.bottom())
        left_line_start = QtCore.QPoint(self.target_rect.left(), 0)
        left_line_end = QtCore.QPoint(self.target_rect.left(), self.mask_pixmap.height())
        right_line_start = QtCore.QPoint(self.target_rect.right(), 0)
        right_line_end = QtCore.QPoint(self.target_rect.right(), self.mask_pixmap.height())

        painter.drawLine(top_line_start, top_line_end)
        painter.drawLine(bottom_line_start, bottom_line_end)
        painter.drawLine(left_line_start, left_line_end)
        painter.drawLine(right_line_start, right_line_end)

        if self.roi_rect and self.paste_point:
            painter.setPen(QPen(Qt.green, 1))

            roi_top_left = QtCore.QPoint(max(self.roi_rect.left() - self.mask_rect.left(), 0),
                                         max(self.roi_rect.top() - self.mask_rect.top(), 0))
            roi_bottom_right = QtCore.QPoint(
                min(self.roi_rect.right() - self.mask_rect.left(), self.target_rect.width()),
                min(self.roi_rect.bottom() - self.mask_rect.top(), self.target_rect.height()))
            limited_roi_rect = QtCore.QRect(self.target_rect.topLeft() + roi_top_left,
                                            self.target_rect.topLeft() + roi_bottom_right)

            painter.drawRect(limited_roi_rect)

        # Create left and right part of the mask pixmap
        self.left_part = self.mask_pixmap.copy(0, 0, self.target_rect.left(), self.mask_pixmap.height())
        self.right_part = self.mask_pixmap.copy(self.target_rect.right(), 0,
                                                self.mask_pixmap.width() - self.target_rect.right(),
                                                self.mask_pixmap.height())

        painter.end()

        display_image(self.template_image_duplicate, self.mask_pixmap)
        self.copy_roi_to_template()

内容的提问来源于stack exchange,提问作者Kei Emile Daisy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 10:49:49