Как выделить части изображения между двумя щелчками правой кнопкой мыши?Python

Программы на Python
Anonymous
Как выделить части изображения между двумя щелчками правой кнопкой мыши?

Сообщение Anonymous »

Пока у меня есть общий визуализатор, но я застрял в том, как реализовать охватывающий несколько столбцов маркер, если это имеет смысл (я приложу пример того, что я имею в виду).
Моя цель — отобразить несколько фотографических изображений, расположенных вертикально (Фото 1.jpg, Фото 2.jpg), с нанесенным поверх них прозрачным наложением (Overlay 1.png, Overlay 2.png).
Результирующая подсветка должна быть такой (как здесь фиолетовая подсветка между двумя зелеными точками, обозначающими последовательные щелчки правой кнопкой мыши), хотя и не обязательно фиолетовая (я бы предпочел просто увеличить яркость этого раздела). вообще-то).
from PyQt6.QtCore import QPointF, Qt, pyqtSignal
from PyQt6.QtGui import QImage, QMouseEvent, QPixmap, QTransform, QWheelEvent
from PyQt6.QtOpenGLWidgets import QOpenGLWidget
from PyQt6.QtWidgets import QApplication, QGraphicsPixmapItem, QGraphicsScene, QGraphicsView, QLabel, QPushButton, QSlider, QVBoxLayout, QWidget

class ImageOverlayApp(QWidget):
def __init__(self, corebox_images: list[str], overlay_images: list[str]) -> None:
super().__init__()
self.setWindowTitle("Viewer")

# Initial opacity
self.alpha = 0.5

# Prepare the scene
self.scene = QGraphicsScene()

# Lists to hold pixmap items and images
self.pixmap_items_core: list[QGraphicsPixmapItem] = []
self.pixmap_items_overlay: list[QGraphicsPixmapItem] = []
self.overlay_images: list[QImage] = []

# Transformation for rotation
transform = QTransform()
transform.rotate(-90) # Rotate 90 degrees counterclockwise

y_offset = 0 # Vertical position offset
for core_img_path, overlay_img_path in zip(corebox_images, overlay_images, strict=True):
# Load images as QImage
core_photo = QImage(core_img_path)
false_color = QImage(overlay_img_path)

# Rotate images
core_photo = core_photo.transformed(transform, Qt.TransformationMode.FastTransformation)
false_color = false_color.transformed(transform, Qt.TransformationMode.FastTransformation)

# Resize overlay image to match core photo
false_color = false_color.scaled(core_photo.size(), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.FastTransformation)

# Create pixmap items
pixmap_item_core = QGraphicsPixmapItem(QPixmap.fromImage(core_photo))
pixmap_item_overlay = QGraphicsPixmapItem(QPixmap.fromImage(false_color))
pixmap_item_overlay.setOpacity(self.alpha)

# Position pixmap items vertically
pixmap_item_core.setPos(0, y_offset)
pixmap_item_overlay.setPos(0, y_offset)

# Add items to scene
self.scene.addItem(pixmap_item_core)
self.scene.addItem(pixmap_item_overlay)

# Store pixmap items and images
self.pixmap_items_core.append(pixmap_item_core)
self.pixmap_items_overlay.append(pixmap_item_overlay)
self.overlay_images.append(false_color)

# Update y_offset for the next image
y_offset += core_photo.height()

# Set up QGraphicsView with OpenGL for performance
self.view = GraphicsView(self.scene)
self.view.setViewport(QOpenGLWidget())
self.view.setBackgroundBrush(Qt.GlobalColor.transparent)
self.view.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)
self.view.setOptimizationFlags(QGraphicsView.OptimizationFlag.DontSavePainterState)
self.view.setViewportUpdateMode(QGraphicsView.ViewportUpdateMode.SmartViewportUpdate)

# Connect signals
self.view.clicked.connect(self.on_image_clicked)

# Slider for adjusting transparency
self.slider = QSlider(Qt.Orientation.Horizontal)
self.slider.setRange(0, 100)
self.slider.setValue(int(self.alpha * 100))
self.slider.valueChanged.connect(self.slider_changed)

# Label for transparency slider
self.slider_label = QLabel("Transparency")

# Button to reset zoom
self.reset_button = QPushButton("Reset Zoom")
self.reset_button.clicked.connect(self.reset_zoom)

# Layout
layout = QVBoxLayout()
layout.addWidget(self.view)
layout.addWidget(self.slider_label)
layout.addWidget(self.slider)
layout.addWidget(self.reset_button)
self.setLayout(layout)

def reset_zoom(self) -> None:
"""Reset the zoom to the original state."""
self.view.resetTransform()
self.view.zoom = 0

def slider_changed(self, value: float) -> None:
"""Adjust the opacity of the overlay images."""
self.alpha = value / 100
for pixmap_item_overlay in self.pixmap_items_overlay:
pixmap_item_overlay.setOpacity(self.alpha)

def on_image_clicked(self, scene_pos: QPointF) -> None:
"""Handle clicks on the image."""
# Now check which image was clicked
for index, pixmap_item_overlay in enumerate(self.pixmap_items_overlay):
# Get the bounding rectangle of the item in scene coordinates
item_rect = pixmap_item_overlay.mapRectToScene(pixmap_item_overlay.boundingRect())
if item_rect.contains(scene_pos):
# Map the scene position to the item's local coordinates
item_pos = pixmap_item_overlay.mapFromScene(scene_pos)
x = item_pos.x()
y = item_pos.y()

# Optionally, get the pixel value from the original image
pixel_value = self.overlay_images[index].pixelColor(int(x), int(y))
print(f"Clicked on image {index} at coordinates: ({int(x)}, {int(y)})")
print(f"Pixel color: {pixel_value}")
# Process the coordinates as needed
break

class GraphicsView(QGraphicsView):
clicked = pyqtSignal(QPointF)

def __init__(self, scene: QGraphicsScene) -> None:
super().__init__(scene)
self.zoom = 0
self.setMouseTracking(True)
self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
self.setResizeAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)

def wheelEvent(self, event: QWheelEvent) -> None:
"""Handle mouse wheel events for panning and zooming."""
if event.modifiers() & Qt.KeyboardModifier.ControlModifier:
# Handle zooming
zoom_in_factor = 1.25
zoom_out_factor = 1.0 / zoom_in_factor

# Save the scene pos
old_pos = self.mapToScene(event.position().toPoint())

# Zoom
if event.angleDelta().y() > 0:
zoom_factor = zoom_in_factor
self.zoom += 1
else:
zoom_factor = zoom_out_factor
self.zoom -= 1

# Scale the viewer
self.scale(zoom_factor, zoom_factor)

# Get the new position
new_pos = self.mapToScene(event.position().toPoint())

# Move scene to old position to achieve zoom at cursor
delta = new_pos - old_pos
self.translate(delta.x(), delta.y())
else:
# Handle panning with the scroll wheel
delta = event.pixelDelta() if not event.pixelDelta().isNull() else event.angleDelta() / 8

# Invert delta to match the scroll direction
self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - delta.x())
self.verticalScrollBar().setValue(self.verticalScrollBar().value() - delta.y())

def mousePressEvent(self, event: QMouseEvent) -> None:
"""Handle mouse press events."""
if event.button() == Qt.MouseButton.LeftButton:
scene_pos = self.mapToScene(event.position().toPoint())
self.clicked.emit(scene_pos)
super().mousePressEvent(event)

def mouseReleaseEvent(self, event: QMouseEvent) -> None:
"""Disable dragging when mouse is released."""
if event.button() == Qt.MouseButton.LeftButton:
self.setDragMode(QGraphicsView.DragMode.NoDrag)
super().mouseReleaseEvent(event)

# Run the application
if __name__ == "__main__":
app = QApplication([])
window = ImageOverlayApp(
[
r"Photo 1.jpg",
r"Photo 2.jpg",
],
[
r"Overlay 1.png",
r"Overlay 2.png",
],
)

window.show()
app.exec()


Подробнее здесь: https://stackoverflow.com/questions/790 ... ght-clicks

Вернуться в «Python»