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
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))
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)
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()
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)
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)
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)
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))
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])
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])
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)) )
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))
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()