def add_slider(self, label, description, minimum, maximum, value, slider_moved_func, parent, tick_interval=1, single_step=1, slider_scale_factor=1, int_values=False): # make layout to hold slider and textbox control_layout = QHBoxLayout() slider_label = label + "_slider" textbox_label = label + "_textbox" # make slider & add to layout slider = QSlider(Qt.Horizontal) slider.setObjectName(label) slider.setFocusPolicy(Qt.StrongFocus) slider.setTickPosition(QSlider.TicksBothSides) slider.setTickInterval(tick_interval) slider.setSingleStep(single_step) slider.setMinimum(minimum) slider.setMaximum(maximum) slider.setValue(value) control_layout.addWidget(slider) # make textbox & add to layout textbox = QLineEdit() textbox.setObjectName(label) textbox.setFixedWidth(40) textbox.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) textbox.returnPressed.connect( self.controller.update_crop_params_from_gui) self.update_textbox_from_slider(slider, textbox, slider_scale_factor, int_values) control_layout.addWidget(textbox) # connect slider to set textbox text & update params slider.sliderMoved.connect(lambda: self.update_textbox_from_slider( slider, textbox, slider_scale_factor, int_values)) slider.sliderMoved.connect(slider_moved_func) slider.sliderPressed.connect(lambda: self.slider_pressed(slider)) slider.sliderReleased.connect(lambda: self.slider_released(slider)) # connect textbox to textbox.editingFinished.connect( lambda: self.update_slider_from_textbox(slider, textbox, slider_scale_factor)) textbox.editingFinished.connect(slider_moved_func) # add row to form layout parent.addRow(description, control_layout) # add to list of controls self.crop_param_controls[-1][slider_label] = slider self.crop_param_controls[-1][textbox_label] = textbox
def _addSlider(self, v, cnt): control = QSlider(Qt.Horizontal) control.setMinimumWidth(172) control.setFocusPolicy(Qt.StrongFocus) control.setMaximum(v.max * 160) control.setMinimum(v.min * 160) control.setValue(v.value * 160) control.tag = cnt if self.styleName == "mac": control.setAttribute(Qt.WA_MacMiniSize, True) self.layout.addWidget(control, cnt, 1) self.connect(control, SIGNAL("valueChanged(int)"), self.numberChanged_)
def add_slider(foo, col): sld = QSlider(Qt.Vertical, sliders) sld.setFocusPolicy(Qt.NoFocus) sld.valueChanged[int].connect(foo) sld.valueChanged.connect(self.plot) sliders_grid.addWidget(sld, 0, col)
class PreviewWindow(QMainWindow): """ QMainWindow subclass used to show frames & tracking. """ def __init__(self, controller): QMainWindow.__init__(self) # set controller self.controller = controller # set title self.setWindowTitle("Preview") # get parameter window position & size param_window_x = self.controller.param_window.x() param_window_y = self.controller.param_window.y() param_window_width = self.controller.param_window.width() # set position & size to be next to the parameter window self.setGeometry(param_window_x + param_window_width, param_window_y, 10, 10) # create main widget self.main_widget = QWidget(self) self.main_widget.setMinimumSize(QSize(500, 500)) # create main layout self.main_layout = QGridLayout(self.main_widget) self.main_layout.setContentsMargins(0, 0, 0, 0) self.main_layout.setSpacing(0) # create label that shows frames self.image_widget = QWidget(self) self.image_layout = QVBoxLayout(self.image_widget) self.image_layout.setContentsMargins(0, 0, 0, 0) self.image_label = PreviewQLabel(self) self.image_label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.image_label.setAlignment(Qt.AlignTop | Qt.AlignLeft) self.image_label.hide() self.image_layout.addWidget(self.image_label) self.main_layout.addWidget(self.image_widget, 0, 0) # self.image_label.setStyleSheet("border: 1px solid rgba(122, 127, 130, 0.5)") self.bottom_widget = QWidget(self) self.bottom_layout = QVBoxLayout(self.bottom_widget) self.bottom_layout.setContentsMargins(8, 0, 8, 8) self.bottom_widget.setMaximumHeight(40) self.main_layout.addWidget(self.bottom_widget, 1, 0) # create label that shows crop instructions self.instructions_label = QLabel("") self.instructions_label.setStyleSheet("font-size: 11px;") self.instructions_label.setAlignment(Qt.AlignCenter) self.bottom_layout.addWidget(self.instructions_label) # create image slider self.image_slider = QSlider(Qt.Horizontal) self.image_slider.setFocusPolicy(Qt.StrongFocus) self.image_slider.setTickPosition(QSlider.NoTicks) self.image_slider.setTickInterval(1) self.image_slider.setSingleStep(1) self.image_slider.setValue(0) self.image_slider.valueChanged.connect(self.controller.show_frame) self.image_slider.hide() self.bottom_layout.addWidget(self.image_slider) self.zoom = 1 self.offset = [0, 0] self.center_y = 0 self.center_x = 0 # initialize variables self.image = None # image to show self.tracking_data = None # list of tracking data self.selecting_crop = False # whether user is selecting a crop self.changing_heading_angle = False # whether the user is changing the heading angle self.body_crop = None self.final_image = None # set main widget self.setCentralWidget(self.main_widget) # set window buttons if pyqt_version == 5: self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowFullscreenButtonHint) else: self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint) self.show() def wheelEvent(self, event): old_zoom = self.zoom self.zoom = max(1, self.zoom + event.pixelDelta().y() / 100) self.zoom = int(self.zoom * 100) / 100.0 self.update_image_label(self.final_image, zooming=True) def start_selecting_crop(self): # start selecting crop self.selecting_crop = True # add instruction text self.instructions_label.setText("Click & drag to select crop area.") def plot_image(self, image, params, crop_params, tracking_results, new_load=False, new_frame=False, show_slider=True, crop_around_body=False): if image is None: self.update_image_label(None) self.image_slider.hide() self.image_label.hide() else: if new_load: self.image_label.show() self.remove_tail_start() if show_slider: if not self.image_slider.isVisible(): self.image_slider.setValue(0) self.image_slider.setMaximum(self.controller.n_frames - 1) self.image_slider.show() else: self.image_slider.hide() max_inititial_size = 500 if image.shape[0] > max_inititial_size: min_height = max_inititial_size min_width = max_inititial_size * image.shape[ 1] / image.shape[0] elif image.shape[1] > max_inititial_size: min_width = max_inititial_size min_height = max_inititial_size * image.shape[ 0] / image.shape[1] else: min_height = image.shape[0] min_width = image.shape[1] self.main_widget.setMinimumSize( QSize(min_width, min_height + self.bottom_widget.height())) # convert to RGB if len(image.shape) == 2: image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB) # update image self.image = image.copy() try: body_crop = params['body_crop'] except: body_crop = None try: tail_start_coords = params['tail_start_coords'] # add tail start point to image cv2.circle(image, (int( round(tail_start_coords[1] - crop_params['offset'][1])), int( round(tail_start_coords[0] - crop_params['offset'][0]))), 1, (180, 180, 50), -1) except (KeyError, TypeError) as error: tail_start_coords = None if tracking_results is not None: body_position = tracking_results['body_position'] heading_angle = tracking_results['heading_angle'] # add tracking to image image = tracking.add_tracking_to_frame(image, tracking_results, cropped=True) if body_crop is not None and body_position is not None: if not crop_around_body: # copy image overlay = image.copy() # draw tail crop overlay cv2.rectangle(overlay, (int(body_position[1] - body_crop[1]), int(body_position[0] - body_crop[0])), (int(body_position[1] + body_crop[1]), int(body_position[0] + body_crop[0])), (242, 242, 65), -1) # overlay with the original image cv2.addWeighted(overlay, 0.2, image, 0.8, 0, image) self.body_crop = None else: self.body_crop = body_crop if crop_around_body: _, image = tracking.crop_frame_around_body( image, body_position, params['body_crop']) self.final_image = image # update image label self.update_image_label( self.final_image, zoom=(not (crop_around_body and body_position is not None)), new_load=new_load) def draw_crop_selection(self, start_crop_coords, end_crop_coords): if self.selecting_crop and self.image is not None: # convert image to rgb if len(self.image.shape) < 3: image = np.repeat(self.image[:, :, np.newaxis], 3, axis=2) else: image = self.image.copy() # copy image overlay = image.copy() # draw crop selection overlay cv2.rectangle(overlay, (start_crop_coords[1], start_crop_coords[0]), (end_crop_coords[1], end_crop_coords[0]), (255, 51, 0), -1) # overlay with the original image cv2.addWeighted(overlay, 0.5, image, 0.5, 0, image) # update image label self.update_image_label(image) def change_offset(self, prev_coords, new_coords): self.offset[0] -= new_coords[0] - prev_coords[0] self.offset[1] -= new_coords[1] - prev_coords[1] self.update_image_label(self.final_image) def draw_tail_start(self, rel_tail_start_coords): if self.controller.params['type'] == "headfixed": # send new tail start coordinates to controller self.controller.update_tail_start_coords(rel_tail_start_coords) # clear instructions text self.instructions_label.setText("") if self.image is not None: image = self.image.copy() cv2.circle(image, (int(round(rel_tail_start_coords[1])), int(round(rel_tail_start_coords[0]))), 1, (180, 180, 50), -1) # update image label self.update_image_label(image) def remove_tail_start(self): self.update_image_label(self.image) def add_angle_overlay(self, angle): image = self.image.copy() image_height = self.image.shape[0] image_width = self.image.shape[1] center_y = image_height / 2 center_x = image_width / 2 cv2.arrowedLine( image, (int(center_x - 0.3 * image_height * np.sin((angle + 90) * np.pi / 180)), int(center_y - 0.3 * image_width * np.cos((angle + 90) * np.pi / 180))), (int(center_x + 0.3 * image_height * np.sin((angle + 90) * np.pi / 180)), int(center_y + 0.3 * image_width * np.cos((angle + 90) * np.pi / 180))), (50, 255, 50), 2) self.update_image_label(image) def remove_angle_overlay(self): self.update_image_label(self.image) def update_image_label(self, image, zoom=True, new_load=False, zooming=False): if image is not None and self.zoom != 1 and zoom: if zooming: self.offset[0] = min( max( 0, self.offset[0] + int( (self.image_label.image.shape[0]) / 2.0) - int(round((image.shape[0] / self.zoom) / 2.0))), image.shape[0] - int(round(image.shape[0] / self.zoom))) self.offset[1] = min( max( 0, self.offset[1] + int( (self.image_label.image.shape[1]) / 2.0) - int(round((image.shape[1] / self.zoom) / 2.0))), image.shape[1] - int(round(image.shape[1] / self.zoom))) else: self.offset[0] = min( max(0, self.offset[0]), image.shape[0] - int(round(image.shape[0] / self.zoom))) self.offset[1] = min( max(0, self.offset[1]), image.shape[1] - int(round(image.shape[1] / self.zoom))) if self.center_y is None: self.center_y = int(round(image.shape[0] / 2.0)) if self.center_x is None: self.center_x = int(round(image.shape[1] / 2.0)) image = image[ self.offset[0]:int(round(image.shape[0] / self.zoom)) + self.offset[0], self.offset[1]:int(round(image.shape[1] / self.zoom)) + self.offset[1], :].copy() if image is not None: if zoom: self.setWindowTitle("Preview - Zoom: {:.1f}x".format( self.zoom)) else: self.setWindowTitle("Preview - Zoom: 1x") else: self.setWindowTitle("Preview") self.image_label.update_pixmap(image, new_load=new_load) def crop_selection(self, start_crop_coord, end_crop_coord): if self.selecting_crop: # stop selecting the crop self.selecting_crop = False # clear instruction text self.instructions_label.setText("") # update crop parameters from the selection self.controller.update_crop_from_selection(start_crop_coord, end_crop_coord) def closeEvent(self, ce): if not self.controller.closing: ce.ignore() else: ce.accept()
class OpencvCameraTestWidget(QWidget): available_resolutions = { "160x120": [160, 120], "176x144": [176, 144], "320x240": [320, 240], "352x288": [352, 288], "640x480": [640, 480], "960x720": [960, 720], "1280x960": [1280, 960] } def __init__(self, parent=None, capture=None, widget=None): super(OpencvCameraTestWidget, self).__init__(parent) self.main_layout = QVBoxLayout(self) self.main_layout.setSizeConstraint(QLayout.SetFixedSize) if capture is None: self.capture = cv2.VideoCapture(0) else: self.capture = capture if widget is None: self.camera_widget = QImageWidget() self.main_layout.addWidget(self.camera_widget) self.camera_ret = 0 self.raw_camera_image = None # cv2.namedWindow("image") self.camera_timer = QTimer() self.camera_timer.timeout.connect(self.grab_video) self.camera_timer.start(1000 / 24) self.brightness_layout = QHBoxLayout() self.brightness_label = QLabel("Brightness: ") self.brightness_layout.addWidget(self.brightness_label) self.brightness_value_label = QLabel("") self.brightness_value_label.setMinimumWidth(30) self.brightness_slider = QSlider(Qt.Horizontal) self.brightness_slider.setFocusPolicy(Qt.StrongFocus) self.brightness_slider.setTickPosition(QSlider.TicksBothSides) self.brightness_slider.setMinimum(-10) self.brightness_slider.setMaximum(110) self.brightness_slider.setValue(20) self.brightness_slider.setTickPosition(QSlider.TicksBelow) self.brightness_slider.setTickInterval(10) self.brightness_slider.valueChanged.connect(self.set_brightness) self.brightness_layout.addWidget(self.brightness_slider) self.brightness_layout.addWidget(self.brightness_value_label) self.main_layout.addLayout(self.brightness_layout) self.contrast_layout = QHBoxLayout() self.contrast_label = QLabel("Contrast: ") self.contrast_layout.addWidget(self.contrast_label) self.contrast_value_label = QLabel("") self.contrast_value_label.setMinimumWidth(30) self.contrast_slider = QSlider(Qt.Horizontal) self.contrast_slider.setFocusPolicy(Qt.StrongFocus) self.contrast_slider.setTickPosition(QSlider.TicksBothSides) self.contrast_slider.setMinimum(-10) self.contrast_slider.setMaximum(110) self.contrast_slider.setValue(20) self.contrast_slider.setTickPosition(QSlider.TicksBelow) self.contrast_slider.setTickInterval(10) self.contrast_slider.valueChanged.connect(self.set_contrast) self.contrast_layout.addWidget(self.contrast_slider) self.contrast_layout.addWidget(self.contrast_value_label) self.main_layout.addLayout(self.contrast_layout) self.exposure_layout = QHBoxLayout() self.exposure_label = QLabel("Exposure: ") self.exposure_layout.addWidget(self.exposure_label) self.exposure_value_label = QLabel("") self.exposure_value_label.setMinimumWidth(30) self.exposure_slider = QSlider(Qt.Horizontal) self.exposure_slider.setFocusPolicy(Qt.StrongFocus) self.exposure_slider.setTickPosition(QSlider.TicksBothSides) self.exposure_slider.setMinimum(-10) self.exposure_slider.setMaximum(110) self.exposure_slider.setValue(20) self.exposure_slider.setTickPosition(QSlider.TicksBelow) self.exposure_slider.setTickInterval(10) self.exposure_slider.valueChanged.connect(self.set_exposure) self.exposure_layout.addWidget(self.exposure_slider) self.exposure_layout.addWidget(self.exposure_value_label) self.main_layout.addLayout(self.exposure_layout) self.iso_layout = QHBoxLayout() self.iso_label = QLabel("ISO: ") self.iso_layout.addWidget(self.iso_label) self.iso_value_label = QLabel("") self.iso_value_label.setMinimumWidth(30) self.iso_slider = QSlider(Qt.Horizontal) self.iso_slider.setFocusPolicy(Qt.StrongFocus) self.iso_slider.setTickPosition(QSlider.TicksBothSides) self.iso_slider.setMinimum(-10) self.iso_slider.setMaximum(110) self.iso_slider.setValue(20) self.iso_slider.setTickPosition(QSlider.TicksBelow) self.iso_slider.setTickInterval(10) self.iso_slider.valueChanged.connect(self.set_iso) self.iso_layout.addWidget(self.iso_slider) self.iso_layout.addWidget(self.iso_value_label) self.main_layout.addLayout(self.iso_layout) self.auto_exposure_label = QLabel("AutoExposure: ") self.auto_exposure_checkbox = QCheckBox("AutoExposure: ") self.exposure_layout.addWidget(self.auto_exposure_checkbox) self.auto_exposure_checkbox.stateChanged.connect( self.set_auto_exposure) self.resolutions_combo = QComboBox() self.resolutions_combo.addItems(self.available_resolutions.keys()) self.main_layout.addWidget(self.resolutions_combo) self.resolutions_combo.currentIndexChanged[str].connect( self.set_resolution) def set_brightness(self, value): self.capture.set(cv2.CAP_PROP_BRIGHTNESS, value / 100.0) self.brightness_value_label.setText(str(value / 100.0)) def set_contrast(self, value): self.capture.set(cv2.CAP_PROP_CONTRAST, value / 100.0) self.contrast_value_label.setText(str(value / 100.0)) def set_exposure(self, value): self.capture.set(cv2.CAP_PROP_EXPOSURE, value / 100.0) self.exposure_value_label.setText(str(value / 100.0)) def set_iso(self, value): self.capture.set(cv2.CAP_PROP_ISO_SPEED, value / 100.0) self.exposure_value_label.setText(str(value / 100.0)) def set_auto_exposure(self, value): if value > 0: self.capture.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1) else: self.capture.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25) def set_resolution(self, string): if str(string) in self.available_resolutions: height = self.available_resolutions[str(string)][0] width = self.available_resolutions[str(string)][1] self.capture.set(cv2.CAP_PROP_FRAME_HEIGHT, height) self.capture.set(cv2.CAP_PROP_FRAME_WIDTH, width) def grab_video(self): # print "grab video" self.camera_ret, self.raw_camera_image = self.capture.read() if self.camera_ret: self.raw_camera_image = cv2.cvtColor(self.raw_camera_image, cv2.COLOR_BGR2RGB) self.camera_widget.set_opencv_image(self.raw_camera_image)