Home > other >  How to know the exact position of a camera viewbox in Qt?
How to know the exact position of a camera viewbox in Qt?

Time:12-08

I am working with OpenGL in python and trying to attach 2d images to a canvas (the images will change according to a certain frequence).

I managed to achieve that but to continue my task i need two things:

  1. the major problem: I need to get the image position (or bounds), sorry if i don't have the correct term, i am new to this. basically i just need to have some kind of positions to know where my picture is in the canvas. i tried to look into the methods and attributes of self.view.camera I could not find anything to help.

  2. one minor problem: i can move the image with the mouse along the canvas and i zoom it. i wonder if it is possible to only allow the zoom but not allow the right/left move [this is resolved in the comments section]

here is my code:

import sys
from PySide2 import QtWidgets, QtCore
from vispy import scene
from PySide2.QtCore import QMetaObject
from PySide2.QtWidgets import *
import numpy as np
import dog
import time
import imageio as iio

class CameraThread(QtCore.QThread):
    new_image = QtCore.Signal(object)

    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)

    def run(self):
            try:
                while True:
                    frame = iio.imread(dog.getDog(filename='randog'))
                    self.new_image.emit(frame.data)
                    time.sleep(10.0)
            finally:
                print('end!')


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 400)

        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")

        self.groupBox = QGroupBox(self.centralwidget)
        self.groupBox.setObjectName("groupBox")

        self.gridLayout.addWidget(self.groupBox, 0, 0, 1, 1)

        MainWindow.setCentralWidget(self.centralwidget)

        QMetaObject.connectSlotsByName(MainWindow)



class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # OpenGL drawing surface
        self.canvas = scene.SceneCanvas(keys='interactive')
        self.canvas.create_native()
        self.canvas.native.setParent(self)


        self.setWindowTitle('MyApp')


        self.view = self.canvas.central_widget.add_view()

        self.view.bgcolor = '#ffffff'   # set the canvas to a white background

        self.image = scene.visuals.Image(np.zeros((1, 1)),
                                         interpolation='nearest',
                                         parent= self.view.scene,
                                         cmap='grays',
                                         clim=(0, 2 ** 8 - 1))


        self.view.camera = scene.PanZoomCamera(aspect=1)
        self.view.camera.flip = (0, 1, 0)
        self.view.camera.set_range()
        self.view.camera.zoom(1000, (0, 0))

        self._camera_runner = CameraThread(parent=self)
        self._camera_runner.new_image.connect(self.new_image, type=QtCore.Qt.BlockingQueuedConnection)
        self._camera_runner.start()


    @QtCore.Slot(object)
    def new_image(self, img):
        try:
            self.image.set_data(img)
            self.image.update()
        except Exception as e:
            print(f"problem sending image: {e}")


def main():
    import ctypes
    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('my_gui')

    app = QtWidgets.QApplication([])

    main_window = MainWindow()
    main_window.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

CodePudding user response:

Do you want to know the coordinates of the picture in the viewport (the window), or do you want the coordinates of the picture on the canvas? Vispy actually puts the image at (0,0) by default inside the Vispy canvas. When you move around the canvas you actually aren't moving the canvas around, you are just moving the camera which is looking at the canvas so the coordinates of the picture stay at (0,0) regardless if you move around the viewport or the camera or not. Also the coordinates of the Vispy canvas correspond one to one with the pixel length and width of your image. One pixel is one unit in Vispy. You can check this by adding this method to your MainWindow class:

def my_handler(self,event):
    

    transform = self.image.transforms.get_transform(map_to="canvas")
    img_x, img_y = transform.imap(event.pos)[:2]
    print(img_x, img_y)
    # optionally do the below to tell other handlers not to look at this event:
    event.handled = True

and adding this to your __init__ method:

self.canvas.events.mouse_move.connect(self.my_handler)

You can see that when you hover over the top left corner of your image, it should print roughly (0,0).

CodePudding user response:

def my_handler(self,event):

transform = self.image.transforms.get_transform(map_to="canvas")
img_x, img_y = transform.imap(event.pos)[:2]
print(img_x, img_y)
# optionally do the below to tell other handlers not to look at this event:
event.handled = True
  • Related