Пример #1
0
    def get_render_to_mat(self, rect: Rect) -> 'npt.NDArray[numpy.float64]':
        actual_scale = self.get_actual_scale(rect)

        cx: Vec2 = self.__rect.center
        cx *= actual_scale

        return translate(rect.center.x - cx.x, rect.center.y - cx.y).dot(
            scale(actual_scale))  # type:ignore
Пример #2
0
    def get_render_to_mat(self, rect):
        hscale = rect.width / self.__rect.width
        vscale = rect.height / self.__rect.height

        actual_scale = min(hscale, vscale)

        cx = self.__rect.center
        cx *= actual_scale

        return translate(rect.center.x - cx.x, rect.center.y - cx.y).dot(scale(actual_scale))
Пример #3
0
    def wheelEvent(self, event):
        """
        :param event:
        :type event: QtGui.MouseWheelEvent
        :return:
        """
        if not event.modifiers():
            step = event.delta()/120.0

            sf = 1.1 ** step
            fixed_center_dot(self.viewState, M.scale(sf), QPoint_to_pair(event.pos()))
        else:
            if self.interactionDelegate:
                self.interactionDelegate.mouseWheelEvent(event)
Пример #4
0
    def wheelEvent(self, event):
        """
        :param event:
        :type event: QtGui.MouseWheelEvent
        :return:
        """
        if not event.modifiers():
            step = event.delta()/120.0

            sf = 1.1 ** step
            fixed_center_dot(self.viewState, M.scale(sf), QPoint_to_pair(event.pos()))
        else:
            if self.interactionDelegate:
                self.interactionDelegate.mouseWheelEvent(event)
Пример #5
0
    def __update(self, suppress=False) -> None:
        # Elements of the world transform
        scale = M.scale(self.__scale)
        translate = M.translate(-self.__center_point.x, -self.__center_point.y)

        # Calculate the world transform

        self.__transform = scale @ self.__rotate_flip @ translate

        self.__w2v = self.__n2v @ self.transform
        self.__v2w = numpy.linalg.inv(self.__w2v) # type:ignore

        if not suppress:
            self.changed.emit()
Пример #6
0
    def __init__(self, vis_model, il, model):
        BaseViewWidget.__init__(self)

        self.il = il
        self.iv = ImageView(il)
        self.model = model
        self.vis_model = vis_model

        self.overlays = set()
        self.active_overlays = set()

        self.setFocusPolicy(QtCore.Qt.StrongFocus)

        self.viewState.transform = scale(0.80)

        self.originView = OriginView()

        self.text_batch = TextBatcher(self.gls.text)
Пример #7
0
    def render(self, vs: 'ViewPort') -> None:
        self.vs = vs

        # Standard alpha-blending. We emit alpha=1 or alpha=0 (no real blending),
        # but the text rendering needs transparency for font rendering
        GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)

        # transform from center of keypoint to edge-of-text
        tmove = translate(-self.d1 + 2, -self.d1 - 3).dot(scale(14, -14))

        count = len(self.model.kp.keypoints)
        for n, kp in enumerate(self.model.kp.keypoints):

            # In unaligned view mode we don't need to show any keypoints that aren't in use
            if not self.model.view_mode.is_aligned() and not kp.use:
                continue

            # Generate a number of colors, separated by as far in hue-space as possible
            color = colorsys.hsv_to_rgb(float(n) / count, 1, 0.8) + (1, )

            # use colors based on current selection
            selected = n == self.model.kp.selected_idx
            frame_color = [1, 1, 1, 1] if selected else color
            text_color = [0, 0, 0, 1] if selected else [1, 1, 1, 1]

            p = self.get_keypoint_viewport_center(kp)

            # Coordinates in view-space
            center_point = vs.glWMatrix.dot(translate(p.x, p.y))
            text_point = center_point.dot(tmove)

            with self.prog.program, self.handle_vao:
                GL.glUniformMatrix3fv(self.prog.uniforms.mat, 1, True,
                                      center_point.astype(numpy.float32))
                GL.glUniform4f(self.prog.uniforms.color, *frame_color)
                # Render the frame
                GL.glDrawArrays(GL.GL_LINES, 0, 12)

                # and the text flag background
                GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 12, 4)

            # Render the text for the flag
            s = self._parent.view.text_batch.get_string("%d" % (n + 1))
            self._parent.view.text_batch.submit(s, text_point, text_color)
Пример #8
0
    def render(self, vs):
        self.vs = vs

        # Standard alpha-blending. We emit alpha=1 or alpha=0 (no real blending),
        # but the text rendering needs transparency for font rendering
        GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)

        # transform from center of keypoint to edge-of-text
        tmove = translate(-self.d1 + 2, -self.d1 - 3).dot(scale(14, -14))

        count = len(self.model.kp.keypoints)
        for n, kp in enumerate(self.model.kp.keypoints):

            # In unaligned view mode we don't need to show any keypoints that aren't in use
            if self.model.view_mode == 0 and not kp.use:
                continue

            # Generate a number of colors, separated by as far in hue-space as possible
            color = colorsys.hsv_to_rgb(float(n) / count, 1,0.8) + (1,)

            # use colors based on current selection
            selected = n == self.model.kp.selected_idx
            frame_color = [1,1,1,1] if selected else color
            text_color = [0,0,0,1] if selected else [1,1,1,1]

            p = self.get_keypoint_viewport_center(kp)

            # Coordinates in view-space
            center_point = vs.glWMatrix.dot(translate(p.x, p.y))
            text_point = center_point.dot(tmove)

            with self.prog, self.handle_vao:
                GL.glUniformMatrix3fv(self.prog.uniforms.mat, 1, True, center_point.astype(numpy.float32))
                GL.glUniform4f(self.prog.uniforms.color, *frame_color)
                # Render the frame
                GL.glDrawArrays(GL.GL_LINES, 0, 12)

                # and the text flag background
                GL.glDrawArrays(GL.GL_TRIANGLE_STRIP, 12, 4)

            # Render the text for the flag
            s = self._parent.view.text_batch.get_string("%d" % (n+1))
            self._parent.view.text_batch.submit(s, text_point, text_color)
Пример #9
0
    def __init__(self, project):
        BaseViewWidget.__init__(self)
        self.project = project

        self.image_view_cache = { }

        self.pad_renderer = PadRender(self)
        self.dip_renderer = DIPRender(self)
        self.smd_renderer = SMDRender(self)
        self.trace_renderer = TraceRender(self)
        self.via_renderer = THRenderer(self)
        self.text_batch = TextBatcher(self.gls.text)
        self.poly_renderer = CachedPolygonRenderer(self)
        self.hairline_renderer = HairlineRenderer(self)
        self.passive_renderer = PassiveRender(self)

        # Initial view is a normalized 1-1-1 area.
        # Shift to be 10cm max
        self.viewState.transform = translate(-0.9, -0.9).dot(scale(1./100000))
Пример #10
0
    def __init__(self, project):
        BaseViewWidget.__init__(self)
        self.project = project

        self.image_view_cache = { }

        self.pad_renderer = PadRender(self)
        self.dip_renderer = DIPRender(self)
        self.smd_renderer = SMDRender(self)
        self.trace_renderer = TraceRender(self)
        self.via_renderer = THRenderer(self)
        self.text_batch = TextBatcher(self.gls.text)
        self.poly_renderer = CachedPolygonRenderer(self)
        self.hairline_renderer = HairlineRenderer(self)
        self.passive_renderer = PassiveRender(self)

        # Initial view is a normalized 1-1-1 area.
        # Shift to be 10cm max
        self.viewState.transform = translate(-0.9, -0.9).dot(scale(1./100000))
Пример #11
0
    def update_matricies(self):
        # Build compatible arrays for cv2.getPerspectiveTransform
        src = numpy.ones((4,2), dtype=numpy.float32)
        dst = numpy.ones((4,2), dtype=numpy.float32)
        src[:, :2] = self.align_handles[:4]
        dst[:, :2] = corners

        # And update the perspective transform
        self.persp_matrix = cv2.getPerspectiveTransform(src, dst)

        # Now, calculate the scale factor
        da = self.dim_handles[1] - self.dim_handles[0]
        db = self.dim_handles[3] - self.dim_handles[2]

        ma = da.mag()
        mb = db.mag()

        sf = 100.0/max(ma, mb)

        self.placeholder_dim_values[0] = sf * ma
        self.placeholder_dim_values[1] = sf * mb

        dims = self.dim_values
        if None in self.dim_values:
            dims = self.placeholder_dim_values

        # Perspective transform handles - convert to
        handles_pp = []
        for handle in self.dim_handles:
            p1 = self.persp_matrix.dot(handle.homol())
            p1 /= p1[2]
            handles_pp.append(p1[:2])

        da = handles_pp[1] - handles_pp[0]
        db = handles_pp[3] - handles_pp[2]
        A = numpy.vstack([da**2, db**2])
        B = numpy.array(dims) ** 2
        res = numpy.abs(numpy.linalg.solve(A, B)) ** .5

        self.scale_matrix = scale(res[0], res[1])
Пример #12
0
    def update_matricies(self) -> None:
        # Build compatible arrays for cv2.getPerspectiveTransform
        src = numpy.ones((4, 2), dtype=numpy.float32)
        dst = numpy.ones((4, 2), dtype=numpy.float32)
        src[:, :2] = self.align_handles[:4]
        dst[:, :2] = corners

        # And update the perspective transform
        self.persp_matrix = cv2.getPerspectiveTransform(src, dst)

        # Now, calculate the scale factor
        da = self.dim_handles[1] - self.dim_handles[0]
        db = self.dim_handles[3] - self.dim_handles[2]

        ma = da.mag()
        mb = db.mag()

        sf = 100.0 / max(ma, mb)

        self.__placeholder_dim_values[0] = sf * ma * MM
        self.__placeholder_dim_values[1] = sf * mb * MM

        dims = self.__active_dims()

        # Perspective transform handles - convert to
        handles_pp = []
        for handle in self.dim_handles:
            p1 = self.persp_matrix.dot(handle.homol())
            p1 /= p1[2]
            handles_pp.append(p1[:2])

        da = handles_pp[1] - handles_pp[0]
        db = handles_pp[3] - handles_pp[2]
        A = numpy.vstack([da ** 2, db ** 2])
        B = numpy.array(dims) ** 2
        res = numpy.abs(numpy.linalg.solve(A, B)) ** .5

        self.scale_matrix = scale(res[0], res[1])
Пример #13
0
 def flip_rotate_matrix(self) -> 'npt.NDArray[numpy.float64]':
     return cast('npt.NDArray[numpy.float64]',
                 rotate(self.rotate_theta).dot(scale(-1 if self.flip_x else 1, -1 if self.flip_y else 1))
                 )
Пример #14
0
 def flip_rotate_matrix(self):
     return rotate(self.rotate_theta).dot(scale(-1 if self.flip_x else 1, -1 if self.flip_y else 1))
Пример #15
0
    def __init__(self, parent, project, il):
        QtGui.QDialog.__init__(self, parent)
        self.resize(800,600)
        self.setSizeGripEnabled(True)

        self.project = project
        self.il = il

        self.model = AlignmentViewModel(self.il)

        # Build the treeView model for layer visibility
        self.buildVisibilityModel()

        # Always align keypoint-based load. Works with unaligned images
        self.model.kp.load(self.project)

        # Keypoint-align, initialize from existing align project and align data
        if isinstance(il.alignment, KeyPointAlignment):
            self.model.align_by = ALIGN_BY_KEYPOINTS
        elif isinstance(il.alignment, RectAlignment):
            self.model.ra.load(self.project)
            self.model.align_by = ALIGN_BY_DIMENSIONS

        # Dialog is two areas, the view, and the controls for the view
        hlayout = QtGui.QHBoxLayout()
        self.setLayout(hlayout)

        view_layout = QtGui.QVBoxLayout()

        self.view_tabs = QtGui.QTabBar()
        self.view_tabs.currentChanged.connect(self.set_view_type)

        self.update_tabs()

        view_layout.addWidget(self.view_tabs)

        self.view = AlignmentViewWidget(self.vis_model, self.il, self.model)


        self.ra_id = RectAlignmentControllerView(self, self.model)
        self.kp_id = KeypointAlignmentControllerView(self, self.model)

        self.view.overlays.add(self.ra_id)
        self.view.overlays.add(self.kp_id)


        view_layout.addWidget(self.view, 1)
        self.directions_label = QtGui.QLabel("")
        view_layout.addWidget(self.directions_label, 0)
        hlayout.addLayout(view_layout, 1)

        # Align Controls
        control_layout = QtGui.QFormLayout()

        rect_align_controls = RectAlignSettingsWidget(self, self.model.ra)
        keypoint_align_controls = KeypointAlignmentWidget(self, self.model.kp)

        # Alignment selection
        self.align_selection = QtGui.QComboBox()
        self.align_selection.addItem("Perimeter + Dimensions")
        self.align_selection.addItem("Keypoints")
        self.align_selection.activated.connect(self.align_selection_cb_changed)
        control_layout.addRow("Align By:", self.align_selection)

        # And the widget stack to drive that
        self.stacked_layout = QtGui.QStackedLayout()
        self.stacked_layout.addWidget(rect_align_controls)
        self.stacked_layout.addWidget(keypoint_align_controls)



        # right pane layout
        control_buttons_layout = QtGui.QVBoxLayout()
        control_buttons_layout.addLayout(control_layout)
        control_buttons_layout.addLayout(self.stacked_layout)

        # Visbox
        vis_gb = QtGui.QGroupBox("Visible Layers")

        self.vis_widget = VisibilityTree(self.vis_model)
        vis_gb_layout = QtGui.QVBoxLayout()
        vis_gb.setLayout(vis_gb_layout)
        vis_gb_layout.addWidget(self.vis_widget)
        control_buttons_layout.addWidget(vis_gb)

        bbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Cancel)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        control_buttons_layout.addWidget(bbox)
        hlayout.addLayout(control_buttons_layout, 0)


        # Explicitly disconnect child-events for the rect-align model
        # We (mostly) don't care about changes to the perimeter
        self.model.ra.changed.disconnect(self.model.change)

        self.model.changed.connect(self.view.update)
        self.vis_model.changed.connect(self.view.update)
        self.model.changed.connect(self.update_controls)


        self._selected_view = None

        self._saved_transforms = [
            scale(0.8), scale(0.8)
        ]


        # Undo stack
        self.undoStack = UndoStack()
        self.undoStack.setup_actions(self)

        self.update_controls()
Пример #16
0
 def flip_rotate_matrix(self):
     return rotate(self.rotate_theta).dot(scale(-1 if self.flip_x else 1, -1 if self.flip_y else 1))