예제 #1
0
파일: test.py 프로젝트: quanqhow/tx2
    def __init__(self, context):
        """
        TestPlugin class to evaluate the image_recognition_msgs interfaces
        :param context: QT context, aka parent
        """
        super(TestPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Test Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)
        
        # Layout and attach to widget
        layout = QVBoxLayout()  
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget, self.image_roi_callback, clear_on_click=True)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._info = QLineEdit()
        self._info.setDisabled(True)
        self._info.setText("Draw a rectangle on the screen to perform recognition of that ROI")
        layout.addWidget(self._info)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set subscriber and service to None
        self._sub = None
        self._srv = None
예제 #2
0
    def setup_ui(self):
        """Initialize widgets.
        """
        self.file_name = QLabel()
        self.f_widget = self.setup_func_widget()
        self.f_2widget = self.setup_second_func_widget()
        self.label_w = LabelWidget(self)
        self.image_w = ImageWidget(self.label_w, self)
        self.filelist_w = FilelistWidget(self)

        self.l_layout = QVBoxLayout()
        self.l_layout.addWidget(self.file_name)
        self.l_layout.addWidget(self.image_w)
        self.l_layout.addWidget(self.f_widget)
        self.l_layout.addWidget(self.f_2widget)
        self.l_widget = QWidget()
        self.l_widget.setLayout(self.l_layout)

        self.r_layout = QVBoxLayout()
        self.r_layout.addWidget(self.label_w)
        self.r_layout.addWidget(self.filelist_w)
        self.r_widget = QWidget()
        self.r_widget.setLayout(self.r_layout)

        self.h_layout = QHBoxLayout()
        self.h_layout.addWidget(self.l_widget)
        self.h_layout.addWidget(self.r_widget)

        self.setLayout(self.h_layout)
    def __init__(self, context):
        super(TestPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Test Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)

        # Layout and attach to widget
        layout = QVBoxLayout()
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget, self.image_roi_callback)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._info = QLineEdit()
        self._info.setDisabled(True)
        self._info.setText(
            "Draw a rectangle on the screen to perform object recognition of that ROI"
        )
        layout.addWidget(self._info)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set subscriber and service to None
        self._sub = None
        self._srv = None
    def __init__(self, context):
        """
        Annotation plugin to create data sets or test the Annotate.srv service
        :param context: Parent QT widget
        """
        super(AnnotationPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Label Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)

        # Layout and attach to widget
        layout = QVBoxLayout()
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget,
                                         self.image_roi_callback,
                                         clear_on_click=True)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._edit_path_button = QPushButton("Edit path")
        self._edit_path_button.clicked.connect(self._get_output_directory)
        grid_layout.addWidget(self._edit_path_button, 1, 1)

        self._output_path_edit = QLineEdit()
        self._output_path_edit.setDisabled(True)
        grid_layout.addWidget(self._output_path_edit, 1, 2)

        self._labels_edit = QLineEdit()
        self._labels_edit.setDisabled(True)
        grid_layout.addWidget(self._labels_edit, 2, 2)

        self._edit_labels_button = QPushButton("Edit labels")
        self._edit_labels_button.clicked.connect(self._get_labels)
        grid_layout.addWidget(self._edit_labels_button, 2, 1)

        self._save_button = QPushButton("Annotate again!")
        self._save_button.clicked.connect(self.annotate_again_clicked)
        grid_layout.addWidget(self._save_button, 2, 3)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set subscriber to None
        self._sub = None
        self._srv = None

        self.labels = []
        self.label = ""
        self.output_directory = ""
예제 #5
0
    def __init__(self, context):
        super(LabelPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Label Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)

        # Layout and attach to widget
        layout = QVBoxLayout()
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget, self.image_roi_callback)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._edit_path_button = QPushButton("Edit path")
        self._edit_path_button.clicked.connect(self._get_output_directory)
        grid_layout.addWidget(self._edit_path_button, 1, 1)

        self._output_path_edit = QLineEdit()
        self._output_path_edit.setDisabled(True)
        grid_layout.addWidget(self._output_path_edit, 1, 2)

        self._labels_edit = QLineEdit()
        self._labels_edit.setDisabled(True)
        grid_layout.addWidget(self._labels_edit, 2, 2)

        self._edit_labels_button = QPushButton("Edit labels")
        self._edit_labels_button.clicked.connect(self._get_labels)
        grid_layout.addWidget(self._edit_labels_button, 2, 1)

        self._save_button = QPushButton("Save another one")
        self._save_button.clicked.connect(self.store_image)
        grid_layout.addWidget(self._save_button, 2, 3)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set subscriber to None
        self._sub = None

        self.labels = []
        self.roi_image = None
        self.label = ""
        self.output_directory = ""
예제 #6
0
    def __init__(self):
        super().__init__()

        self.title = "Glorified Rectangle Creator"
        self.setWindowTitle(self.title)

        self.data_dir = ""

        self.left = 0
        self.top = 0
        self.width = 1024
        self.height = 768
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.tab_panel = TableWidget(self)

        file_list = FileListWidget()
        self.tab_panel.tab1.layout.addWidget(file_list)

        class_list = ClassListWidget()
        self.tab_panel.tab1.layout.addWidget(class_list)

        self.image_panel = ImageWidget(self)
        self.image_panel_controls = ImageControlsWidget()
        self.tab_panel.tab2.layout.addWidget(self.image_panel)
        self.tab_panel.tab2.layout.addWidget(self.image_panel_controls)

        self.setCentralWidget(self.tab_panel)

        self.center()

        self.show()
예제 #7
0
    def __init__(self, context):
        """
        ManualPlugin class that performs a manual recognition based on a request
        :param context: QT context, aka parent
        """
        super(ManualPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Manual Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)
        
        # Layout and attach to widget
        layout = QVBoxLayout()  
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget, self.image_roi_callback)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._labels_edit = QLineEdit()
        self._labels_edit.setDisabled(True)
        grid_layout.addWidget(self._labels_edit, 2, 2)

        self._edit_labels_button = QPushButton("Edit labels")
        self._edit_labels_button.clicked.connect(self._get_labels)
        grid_layout.addWidget(self._edit_labels_button, 2, 1)

        self._done_recognizing_button = QPushButton("Done recognizing..")
        self._done_recognizing_button.clicked.connect(self._done_recognizing)
        self._done_recognizing_button.setDisabled(True)
        grid_layout.addWidget(self._done_recognizing_button, 3, 2)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set service to None
        self._srv = None
        self._srv_name = None

        self._response = RecognizeResponse()
        self._recognizing = False
예제 #8
0
    def setupUi(self, FormImageBboxEditor):
        FormImageBboxEditor.setObjectName("FormImageBboxEditor")
        FormImageBboxEditor.resize(684, 471)
        self.verticalLayout = QtWidgets.QVBoxLayout(FormImageBboxEditor)
        self.verticalLayout.setObjectName("verticalLayout")
        self.image = ImageWidget(FormImageBboxEditor)
        self.image.setObjectName("image")
        self.verticalLayout.addWidget(self.image)
        self.labelInfoPath = QtWidgets.QLabel(FormImageBboxEditor)
        self.labelInfoPath.setObjectName("labelInfoPath")
        self.verticalLayout.addWidget(self.labelInfoPath)
        self.labelInfoScale = QtWidgets.QLabel(FormImageBboxEditor)
        self.labelInfoScale.setObjectName("labelInfoScale")
        self.verticalLayout.addWidget(self.labelInfoScale)
        self.listView = QtWidgets.QListView(FormImageBboxEditor)
        self.listView.setObjectName("listView")
        self.verticalLayout.addWidget(self.listView)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.checkboxStayInside = QtWidgets.QCheckBox(FormImageBboxEditor)
        self.checkboxStayInside.setChecked(True)
        self.checkboxStayInside.setObjectName("checkboxStayInside")
        self.horizontalLayout.addWidget(self.checkboxStayInside)
        self.buttonSwitchInOutEditor = QtWidgets.QPushButton(
            FormImageBboxEditor)
        self.buttonSwitchInOutEditor.setObjectName("buttonSwitchInOutEditor")
        self.horizontalLayout.addWidget(self.buttonSwitchInOutEditor)
        self.buttonSwapInOutEditor = QtWidgets.QPushButton(FormImageBboxEditor)
        self.buttonSwapInOutEditor.setObjectName("buttonSwapInOutEditor")
        self.horizontalLayout.addWidget(self.buttonSwapInOutEditor)
        self.buttonImageNext = QtWidgets.QPushButton(FormImageBboxEditor)
        self.buttonImageNext.setObjectName("buttonImageNext")
        self.horizontalLayout.addWidget(self.buttonImageNext)
        self.buttonImagePrev = QtWidgets.QPushButton(FormImageBboxEditor)
        self.buttonImagePrev.setObjectName("buttonImagePrev")
        self.horizontalLayout.addWidget(self.buttonImagePrev)
        self.buttonDone = QtWidgets.QPushButton(FormImageBboxEditor)
        self.buttonDone.setObjectName("buttonDone")
        self.horizontalLayout.addWidget(self.buttonDone)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.verticalLayout.setStretch(0, 3)
        self.verticalLayout.setStretch(3, 1)

        self.retranslateUi(FormImageBboxEditor)
        QtCore.QMetaObject.connectSlotsByName(FormImageBboxEditor)
예제 #9
0
    def initUI(self):
        vbox = QtGui.QVBoxLayout()

        # Create the widget that displays the video frame
        self.pic = ImageWidget()

        # A horizontal slider to scroll through the video
        self.sld = QtGui.QSlider(QtCore.Qt.Horizontal)
        # self.sld.setFocusPolicy(QtCore.Qt.NoFocus)
        self.sld.setRange(0, self.num_positions)
        self.sld.setValue(100)
        self.sld.valueChanged[int].connect(self.change_slider_value)

        # A special widget that displays the marked ranges and average frame colors
        # (Is also called slider, because it should later take over the role of the conventional slider)
        self.sld2 = SliderWidget()

        # The ranges class manages the marked video ranges and sends them to the widget when changed
        self.ranges = Ranges(update_function=self.sld2.setRanges)
        self.load_or_save_ranges(save=False)

        # A label with a quick introduction
        man_label = QtGui.QLabel()
        man_label.setText(
            "Use the slider to navigate (Mouse + keyboard).\n" +
            "Q = Start preview range, A = Start ad range, Z = Start ignore range\n"
            +
            "D = End current range, Bksp = remove last element.\n Auto-saves on close."
        )
        man_label.setSizePolicy(QtGui.QSizePolicy.Minimum,
                                QtGui.QSizePolicy.Fixed)

        # Put everything together and show it
        vbox.addWidget(self.pic)
        vbox.addWidget(self.sld)
        vbox.addWidget(self.sld2)
        vbox.addWidget(man_label)

        self.setLayout(vbox)
        self.setWindowTitle('Video Annotator')
        self.setAcceptDrops(True)
        self.show()
예제 #10
0
파일: app.py 프로젝트: ccidevs/robovision
    def __init__(self):
        QWidget.__init__(self)

        # loaind ui from xml
        uic.loadUi(os.path.join(DIRPATH, 'app.ui'), self)

        # button event handlers
        self.btnStartCaptureForVideoAnalysis.clicked.connect(
            self.start_capture_for_video_analysis)
        self.btnStopCaptureForVideoAnalysis.clicked.connect(
            self.stop_capture_for_video_analysis)

        self.btnChooseClassifierXML.clicked.connect(
            self.choose_classifier_file)

        self.btnChooseImage.clicked.connect(self.choose_image_for_analysis)

        self.setup_tray_menu()

        # add camera ids
        for i in range(0, 11):
            self.cboxCameraIds.addItem(str(i))
            self.cboxCameraIds1.addItem(str(i))

        # setting up handlers for menubar actions
        self.actionAbout.triggered.connect(self.about)
        self.actionExit.triggered.connect(qApp.quit)
        self.actionPreferences.triggered.connect(self.show_preferences)

        self.img_widget_vid_analysis = ImageWidget()
        self.hlayoutVideoAnalysis.addWidget(self.img_widget_vid_analysis)

        self.img_widget_img_analysis = ImageWidget()
        self.hlayoutImageAnalysis.addWidget(self.img_widget_img_analysis)

        self.vid_capture = VideoCapture()
        self.vid_capture.got_image_data_from_camera.connect(
            self.process_image_data_from_camera)

        self.highlight_faces = self.chkHighlightFaces.isChecked()
        self.chkHighlightFaces.stateChanged.connect(
            self.highlight_faces_checkbox_changed)
예제 #11
0
    def add_log_row(self, log_content_array):
        # add row to the QTableWidget for logs
        row_count = self.logs_ui.logs_table.rowCount()
        self.logs_ui.logs_table.setRowCount(row_count + 1)
        event_sign_image_path = None
        # log levels:
        # debug
        # info
        # notice
        # warning
        # error
        if log_content_array["log_event_type"] == "info":
            info_png_path = os.path.join(os.path.dirname(__file__),
                                         'resources/img/info.png')
            event_sign_image_path = str(info_png_path)
        elif log_content_array["log_event_type"] == "warning":
            warning_png_path = os.path.join(os.path.dirname(__file__),
                                            'resources/img/warning.png')
            event_sign_image_path = str(warning_png_path)
        elif log_content_array["log_event_type"] == "notice":
            notice_png_path = os.path.join(os.path.dirname(__file__),
                                           'resources/img/notice.png')
            event_sign_image_path = str(notice_png_path)
        elif log_content_array["log_event_type"] == "debug":
            debug_png_path = os.path.join(os.path.dirname(__file__),
                                          'resources/img/debug.png')
            event_sign_image_path = str(debug_png_path)
        elif log_content_array["log_event_type"] == "success":
            debug_png_path = os.path.join(os.path.dirname(__file__),
                                          'resources/img/success.png')
            event_sign_image_path = str(debug_png_path)
        elif log_content_array["log_event_type"] == "error":
            error_png_path = os.path.join(os.path.dirname(__file__),
                                          'resources/img/error.png')
            event_sign_image_path = str(error_png_path)

        image = ImageWidget(event_sign_image_path, self)
        widget = QWidget()
        hbl = QHBoxLayout()
        hbl.setMargin(0)
        hbl.setSpacing(0)
        hbl.addWidget(image)
        widget.setLayout(hbl)
        self.logs_ui.logs_table.setCellWidget(row_count, 0, widget)
        self.logs_ui.logs_table.setItem(
            row_count, 1,
            QTableWidgetItem(log_content_array["log_event_type"]))
        titleitem = QTableWidgetItem(log_content_array["title"])
        titleitem.setTextAlignment(QtCore.Qt.AlignCenter)
        self.logs_ui.logs_table.setItem(row_count, 2, titleitem)
        self.logs_ui.logs_table.setItem(
            row_count, 3, QTableWidgetItem(log_content_array["description"]))

        return 1
예제 #12
0
    def show_start_screen(self, time_ms: int) -> None:
        """Show start-splashscreen for the given time. The regular UI is shown
        afterwards.

        Args:
            time_ms:
                Number of miliseconds to actually show the splash-screen
        """
        image_widget = ImageWidget("images/splash_screen.png")
        v_layout = QVBoxLayout()
        h_layout = QHBoxLayout()
        h_layout.addWidget(image_widget)
        v_layout.addLayout(h_layout)
        widget = QWidget()
        widget.setLayout(v_layout)
        self.setCentralWidget(widget)

        timer = QTimer(self)
        timer.singleShot(time_ms, self.on_start_screen_end)
예제 #13
0
    def __init__(self):

        #   call super class
        super(MainWidget, self).__init__()

        #   get widget
        self.imageWidget = ImageWidget()
        self.otherWidget = Profile()

        #   create box layout
        self.boxLayout = QtGui.QVBoxLayout()

        #   add widget to box
        self.boxLayout.addWidget(self.imageWidget)
        self.boxLayout.addStretch()
        self.boxLayout.addWidget(self.otherWidget)

        #   set layout
        self.setLayout(self.boxLayout)
예제 #14
0
    def add_log_row(self, log_content_array):
        # add row to the QTableWidget for logs
        row_count = self.logs_ui.logs_table.rowCount()
        self.logs_ui.logs_table.setRowCount(row_count + 1)
        event_sign_image_path = None

        if log_content_array['log_event_type'] == 'info':
            info_png_path = os.path.join(os.path.dirname(__file__), 'resources/img/info.png')
            event_sign_image_path = str(info_png_path)
        elif log_content_array['log_event_type'] == 'warning':
            warning_png_path = os.path.join(os.path.dirname(__file__), 'resources/img/warning.png')
            event_sign_image_path = str(warning_png_path)
        elif log_content_array['log_event_type'] == 'notice':
            notice_png_path = os.path.join(os.path.dirname(__file__), 'resources/img/notice.png')
            event_sign_image_path = str(notice_png_path)
        elif log_content_array['log_event_type'] == 'debug':
            debug_png_path = os.path.join(os.path.dirname(__file__), 'resources/img/debug.png')
            event_sign_image_path = str(debug_png_path)
        elif log_content_array['log_event_type'] == 'success':
            debug_png_path = os.path.join(os.path.dirname(__file__), 'resources/img/success.png')
            event_sign_image_path = str(debug_png_path)
        elif log_content_array['log_event_type'] == 'error':
            error_png_path = os.path.join(os.path.dirname(__file__), 'resources/img/error.png')
            event_sign_image_path = str(error_png_path)

        image = ImageWidget(event_sign_image_path, self)
        widget = QWidget()
        hbl = QHBoxLayout()
        hbl.setMargin(0)
        hbl.setSpacing(0)
        hbl.addWidget(image)
        widget.setLayout(hbl)

        self.logs_ui.logs_table.setCellWidget(row_count, 0, widget)
        self.logs_ui.logs_table.setItem(row_count, 1, QTableWidgetItem(log_content_array['log_event_type']))

        titleitem = QTableWidgetItem(log_content_array['title'])
        titleitem.setTextAlignment(QtCore.Qt.AlignCenter)

        self.logs_ui.logs_table.setItem(row_count, 2, titleitem)
        self.logs_ui.logs_table.setItem(row_count, 3, QTableWidgetItem(log_content_array['description']))

        return 1
예제 #15
0
class AppWindow(QMainWindow):
    """
    Main GUI class for application
    """
    def __init__(self):
        QWidget.__init__(self)

        # loaind ui from xml
        uic.loadUi(os.path.join(DIRPATH, 'app.ui'), self)

        # FIXME - libpng warning: iCCP: known incorrect sRGB profile
        self.setWindowIcon(QIcon("./images/robot_icon.png"))

        # keep the window fixed sized
        self.setFixedSize(self.size())

        # button event handlers
        self.btnStartCaptureForVideoAnalysis.clicked.connect(
            self.start_capture_for_video_analysis)
        self.btnStopCaptureForVideoAnalysis.clicked.connect(
            self.stop_capture_for_video_analysis)

        self.btnChooseClassifierXML.clicked.connect(
            self.choose_classifier_file)

        self.btnChooseImage.clicked.connect(self.choose_image_for_analysis)

        self.setup_tray_menu()

        # add camera ids
        for i in range(0, 11):
            self.cboxCameraIds.addItem(str(i))
            self.cboxCameraIds1.addItem(str(i))

        # setting up handlers for menubar actions
        self.actionAbout.triggered.connect(self.about)
        self.actionExit.triggered.connect(qApp.quit)
        self.actionPreferences.triggered.connect(self.show_preferences)

        # video analysis image widget
        self.img_widget_vid_analysis = ImageWidget()
        self.hlayoutVideoAnalysis.addWidget(self.img_widget_vid_analysis)

        # face training image widget
        self.img_widget_face_training = ImageWidget()
        self.hlayoutFaceTrainingImg.addWidget(self.img_widget_face_training)

        # face identification image widget
        self.img_widget_identify_face = ImageWidget()
        self.hlayoutIdentifyFace.addWidget(self.img_widget_identify_face)

        # image analysis image widget
        self.img_widget_img_analysis = ImageWidget()
        self.hlayoutImageAnalysis.addWidget(self.img_widget_img_analysis)
        img = cv2.imread("images/human.png")
        self.img_widget_img_analysis.handle_image_data(img)

        self.vid_capture = VideoCapture()
        self.vid_capture.got_image_data_from_camera.connect(
            self.process_image_data_from_camera)

        self.highlight_faces = self.chkHighlightFaces.isChecked()
        self.chkHighlightFaces.stateChanged.connect(
            self.highlight_faces_checkbox_changed)
        self.chckGrayscale.stateChanged.connect(
            self.grayscale_checkbox_changed)

        # face trainer dataset browser btn handler
        self.btnBrowseDatasetForFaceTrainer.clicked.connect(
            self.browse_dataset_for_face_trainer)
        self.btnBrowseClassifierForFaceTrainer.clicked.connect(
            self.browse_classifier_file_for_face_trainer)
        self.btnStartFaceTrainer.clicked.connect(self.start_face_trainer)

        self.btnBrowseIdentifyFace.clicked.connect(self.browse_identify_face)

        self.btnTalk.clicked.connect(self.lets_talk)

        # create and start robot
        self.robot = Robot(self.lblRobot)

        self.mouth = Mouth()

        # connect global signals to slots
        g_emitter().feed_mouth.connect(self.mouth.feed_text)
        g_emitter().set_speaking_state.connect(self.robot.set_speaking_state)
        g_emitter().set_idle_state.connect(self.robot.set_idle_state)

        self.robot.start()
        self.mouth.start()

    def lets_talk(self):
        text = self.teTalk.toPlainText()
        self.teTalk.setText("")
        g_emitter().emit_signal_to_feed_mouth(text)

    def browse_identify_face(self):
        fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
        self.teIdentifyFace.setText(fname[0])

        img = cv2.imread(fname[0])
        self.img_widget_identify_face.handle_image_data(img)

    def start_face_trainer(self):
        dataset_dir = self.teFaceTrainerDataset.toPlainText()
        classifier_xml = self.teFaceTrainerClassifier.toPlainText()
        log.info(
            "starting face trainer with classifier '%s' and dataset '%s'" %
            (classifier_xml, dataset_dir))

        ft = FaceTrainer(classifier_xml, dataset_dir)
        ft.processing_image.connect(self.processing_image_for_training)
        ft.face_training_finished.connect(self.face_training_finished)
        ft.start()
        self.lblFaceTrainingStatus.setText("FACE TRAINING UNDER PROGRESS")

    def face_training_finished(self):
        self.lblFaceTrainingStatus.setText("FACE TRAINING FINISHED")
        g_emitter().emit_signal_to_feed_mouth("face training finished")

    def processing_image_for_training(self, label, fname):
        log.info("processing image for training: '%s'" % label)
        self.lblFaceTrainerCurImg.setText("Learning face of: '%s' " % label)

        try:
            img = cv2.imread(fname)
            self.img_widget_face_training.handle_image_data(img)
        except Exception as exp:
            log.warning("failed while processing image '%s' while training" %
                        fname)
            log.warning("Exception: %s" % str(exp))

    def browse_dataset_for_face_trainer(self):
        dataset_dir = str(
            QFileDialog.getExistingDirectory(self,
                                             'Select directory for dataset',
                                             '/home'))
        log.info("dataset dir file: %s" % dataset_dir)
        self.teFaceTrainerDataset.setText(dataset_dir)

    def browse_classifier_file_for_face_trainer(self):
        classifier_xml = QFileDialog.getOpenFileName(self, 'Open file',
                                                     '/home')
        log.info("classifier xml file: %s" % classifier_xml[0])
        self.teFaceTrainerClassifier.setText(classifier_xml[0])

    def grayscale_checkbox_changed(self):
        fname = self.teImage.toPlainText()
        print(fname)
        img = cv2.imread(fname)
        if self.chckGrayscale.isChecked():
            # convert image to grayscale
            pil_image = Image.open(fname).convert("L")

            # convery grayscale image to numpy array
            image_array = np.array(pil_image, "uint8")

            # FIXME - code crashes here !!!
            self.img_widget_img_analysis.handle_image_data(image_array)
        else:
            self.img_widget_img_analysis.handle_image_data(img)

    def highlight_faces_checkbox_changed(self):
        if self.chkHighlightFaces.isChecked():
            print("yes")
        else:
            print("no")

    def choose_classifier_file(self):
        fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
        log.info("chose classfier xml file: %s" % fname[0])
        self.teClassifierXML.setText(fname[0])

    def choose_image_for_analysis(self):
        fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
        log.info("chose imagefile: %s, for analysis" % fname[0])
        self.teImage.setText(fname[0])

        img = cv2.imread(fname[0])
        self.img_widget_img_analysis.handle_image_data(img)

    def start_capture_for_video_analysis(self):
        log.debug("start video capture")
        self.vid_capture.start()

    def stop_capture_for_video_analysis(self):
        log.debug("start video capture")
        self.vid_capture.stop()
        self.img_widget_vid_analysis.reset()

    def detect_face_in_image_data(self, image_data):
        """
        function detects faces in image data,
        draws rectangle for faces in image data,
        and returns this updated image data with highlighted face/s
        """
        self._red = (0, 0, 255)
        self._width = 2
        self._min_size = (30, 30)

        # haarclassifiers work better in black and white
        gray_image = cv2.cvtColor(image_data, cv2.COLOR_BGR2GRAY)
        gray_image = cv2.equalizeHist(gray_image)

        # path to Haar face classfier's xml file
        face_cascade_xml = './cascades/haarcascades_cuda/haarcascade_frontalface_default.xml'
        self.classifier = cv2.CascadeClassifier(face_cascade_xml)
        faces = self.classifier.detectMultiScale(gray_image,
                                                 scaleFactor=1.3,
                                                 minNeighbors=4,
                                                 flags=cv2.CASCADE_SCALE_IMAGE,
                                                 minSize=self._min_size)

        for (x, y, w, h) in faces:
            cv2.rectangle(image_data, (x, y), (x + w, y + h), self._red,
                          self._width)

        return image_data

    def process_image_data_from_camera(self, image_data):
        if self.chkHighlightFaces.isChecked():
            image_data = self.detect_face_in_image_data(image_data)
        self.img_widget_vid_analysis.handle_image_data(image_data)

    def about(self):
        ad = AboutDialog()
        ad.display()

    def show_preferences(self):
        print("preferences")
        pd = PrefsDialog()
        pd.display()

    def setup_tray_menu(self):

        # setting up QSystemTrayIcon
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(QIcon("./images/robot_icon.png"))

        # tray actions
        show_action = QAction("Show", self)
        quit_action = QAction("Exit", self)
        hide_action = QAction("Hide", self)

        # action handlers
        show_action.triggered.connect(self.show)
        hide_action.triggered.connect(self.hide)
        quit_action.triggered.connect(qApp.quit)

        # tray menu
        tray_menu = QMenu()
        tray_menu.addAction(show_action)
        tray_menu.addAction(hide_action)
        tray_menu.addAction(quit_action)
        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()

    def closeEvent(self, event):
        try:
            event.ignore()
            self.hide()
            self.tray_icon.showMessage("RoboVision",
                                       "RoboVision was minimized to Tray",
                                       QSystemTrayIcon.Information, 2000)
            self.robot.stop()
            self.robot.join()
        except Exception as exp:
            log.warning("app close exp: %s" % str(exp))

    def ok_pressed(self):
        log.debug("[AppWindow] :: ok")
        self.show_msgbox("AppWindow", "Its ok")

    def show_msgbox(self, title, text):
        """
        Function for showing error/info message box
        """
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText(text)
        msg.setWindowTitle(title)
        msg.setStandardButtons(QMessageBox.Ok)

        retval = msg.exec_()
        print("[INFO] Value of pressed message box button:", retval)
예제 #16
0
#!./venv/bin/python3
import os

from PySide2.QtWidgets import (QMainWindow, QApplication, QSizePolicy, QWidget)
from PySide2.QtGui import QResizeEvent, QKeyEvent, QDesktopServices
from PySide2.QtCore import QSize, Slot, QUrl
import bad_practise_global as bpg
import custom_log as l
from PySide2.QtCore import Qt
# from main_level_widget import MainWidget
from image_widget import ImageWidget

if __name__ == '__main__':
    # l.disable()
    import sys

    app = QApplication(sys.argv)
    image_widget = ImageWidget()
    image_widget.show()
    image_widget.resize(500, 500)
    # window.resize(bpg.screen_width, bpg.screen_height)
    sys.exit(app.exec_())
예제 #17
0
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.buttonLoadKdenlive = QtWidgets.QPushButton(self.centralwidget)
        self.buttonLoadKdenlive.setObjectName("buttonLoadKdenlive")
        self.horizontalLayout_2.addWidget(self.buttonLoadKdenlive)
        self.buttonLoadImages = QtWidgets.QPushButton(self.centralwidget)
        self.buttonLoadImages.setObjectName("buttonLoadImages")
        self.horizontalLayout_2.addWidget(self.buttonLoadImages)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem)
        self.buttonSaveKdenlive = QtWidgets.QPushButton(self.centralwidget)
        self.buttonSaveKdenlive.setObjectName("buttonSaveKdenlive")
        self.horizontalLayout_2.addWidget(self.buttonSaveKdenlive)
        self.buttonSaveBboxesJson = QtWidgets.QPushButton(self.centralwidget)
        self.buttonSaveBboxesJson.setObjectName("buttonSaveBboxesJson")
        self.horizontalLayout_2.addWidget(self.buttonSaveBboxesJson)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.lineeditTargetVideoResolution = QtWidgets.QLineEdit(self.centralwidget)
        self.lineeditTargetVideoResolution.setText("")
        self.lineeditTargetVideoResolution.setObjectName("lineeditTargetVideoResolution")
        self.gridLayout.addWidget(self.lineeditTargetVideoResolution, 0, 2, 1, 1)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem1, 0, 3, 1, 1)
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 1, 1, 1)
        self.verticalLayout.addLayout(self.gridLayout)
        self.image = ImageWidget(self.centralwidget)
        self.image.setObjectName("image")
        self.verticalLayout.addWidget(self.image)
        self.labelInfoPath = QtWidgets.QLabel(self.centralwidget)
        self.labelInfoPath.setObjectName("labelInfoPath")
        self.verticalLayout.addWidget(self.labelInfoPath)
        self.labelInfoScale = QtWidgets.QLabel(self.centralwidget)
        self.labelInfoScale.setObjectName("labelInfoScale")
        self.verticalLayout.addWidget(self.labelInfoScale)
        self.listView = QtWidgets.QListView(self.centralwidget)
        self.listView.setObjectName("listView")
        self.verticalLayout.addWidget(self.listView)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.checkboxStayInside = QtWidgets.QCheckBox(self.centralwidget)
        self.checkboxStayInside.setChecked(True)
        self.checkboxStayInside.setObjectName("checkboxStayInside")
        self.horizontalLayout.addWidget(self.checkboxStayInside)
        self.buttonSwitchInOutEditor = QtWidgets.QPushButton(self.centralwidget)
        self.buttonSwitchInOutEditor.setObjectName("buttonSwitchInOutEditor")
        self.horizontalLayout.addWidget(self.buttonSwitchInOutEditor)
        self.buttonSwapInOutEditor = QtWidgets.QPushButton(self.centralwidget)
        self.buttonSwapInOutEditor.setObjectName("buttonSwapInOutEditor")
        self.horizontalLayout.addWidget(self.buttonSwapInOutEditor)
        self.buttonImageNext = QtWidgets.QPushButton(self.centralwidget)
        self.buttonImageNext.setObjectName("buttonImageNext")
        self.horizontalLayout.addWidget(self.buttonImageNext)
        self.buttonImagePrev = QtWidgets.QPushButton(self.centralwidget)
        self.buttonImagePrev.setObjectName("buttonImagePrev")
        self.horizontalLayout.addWidget(self.buttonImagePrev)
        self.buttonDone = QtWidgets.QPushButton(self.centralwidget)
        self.buttonDone.setObjectName("buttonDone")
        self.horizontalLayout.addWidget(self.buttonDone)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout_3.addWidget(self.label_2)
        self.spinboxBboxRatioMultiplier = QtWidgets.QDoubleSpinBox(self.centralwidget)
        self.spinboxBboxRatioMultiplier.setObjectName("spinboxBboxRatioMultiplier")
        self.horizontalLayout_3.addWidget(self.spinboxBboxRatioMultiplier)
        self.buttonApplyBboxRatioMultiplier = QtWidgets.QPushButton(self.centralwidget)
        self.buttonApplyBboxRatioMultiplier.setObjectName("buttonApplyBboxRatioMultiplier")
        self.horizontalLayout_3.addWidget(self.buttonApplyBboxRatioMultiplier)
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem2)
        self.verticalLayout.addLayout(self.horizontalLayout_3)
        self.verticalLayout.setStretch(2, 3)
        self.verticalLayout.setStretch(5, 1)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
예제 #18
0
class ControlWidget(QWidget):
    def __init__(self, parent=None):
        super(ControlWidget, self).__init__(parent)
        self.set_init_settings()
        self.setup_ui()
        self.setup_labeling_func()
        self.setup_file_func()
        self.set_check()
        self.set_check_func()
        self.set_size()
        self.setFocusPolicy(QtCore.Qt.StrongFocus)

    def set_size(self):
        self.l_layout.setAlignment(QtCore.Qt.AlignTop)

        self.select_button.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Minimum)
        self.save_button.setSizePolicy(QSizePolicy.Minimum,
                                       QSizePolicy.Minimum)
        self.delete_button.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Minimum)
        self.image_w.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.label_w.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.filelist_w.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Minimum)

        self.f_widget.setFixedHeight(40)
        self.f_2widget.setFixedHeight(40)
        self.file_name.setFixedHeight(40)

        self.l_widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.r_widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)

    def set_init_settings(self):
        self.auto_load_next_data = False
        self.auto_save = True

    def setup_ui(self):
        """Initialize widgets.
        """
        self.file_name = QLabel()
        self.f_widget = self.setup_func_widget()
        self.f_2widget = self.setup_second_func_widget()
        self.label_w = LabelWidget(self)
        self.image_w = ImageWidget(self.label_w, self)
        self.filelist_w = FilelistWidget(self)

        self.l_layout = QVBoxLayout()
        self.l_layout.addWidget(self.file_name)
        self.l_layout.addWidget(self.image_w)
        self.l_layout.addWidget(self.f_widget)
        self.l_layout.addWidget(self.f_2widget)
        self.l_widget = QWidget()
        self.l_widget.setLayout(self.l_layout)

        self.r_layout = QVBoxLayout()
        self.r_layout.addWidget(self.label_w)
        self.r_layout.addWidget(self.filelist_w)
        self.r_widget = QWidget()
        self.r_widget.setLayout(self.r_layout)

        self.h_layout = QHBoxLayout()
        self.h_layout.addWidget(self.l_widget)
        self.h_layout.addWidget(self.r_widget)

        self.setLayout(self.h_layout)

    def setup_func_widget(self):
        f_widget = QWidget()
        f_layout = QHBoxLayout()
        self.select_button = QPushButton("Open Dir")
        self.select_button.clicked.connect(self.select_dir)
        self.save_button = QPushButton("Save")
        self.save_button.clicked.connect(self.save_data)
        self.delete_button = QPushButton("Delete")
        self.delete_button.clicked.connect(self.delete_data)
        self.auto_load_next_data_box = QCheckBox("Auto Load Next")
        self.auto_save_box = QCheckBox("Auto Save")
        self.auto_take_over_last_data_box = QCheckBox("Auto Use Last label")

        f_layout.addWidget(self.select_button)
        f_layout.addWidget(self.save_button)
        f_layout.addWidget(self.delete_button)
        f_layout.addWidget(self.auto_load_next_data_box)
        f_layout.addWidget(self.auto_save_box)
        f_layout.addWidget(self.auto_take_over_last_data_box)
        f_widget.setLayout(f_layout)
        return f_widget

    def setup_second_func_widget(self):
        f_widget = QWidget()
        f_layout = QHBoxLayout()
        self.left_button = QPushButton("←")
        self.left_button.clicked.connect(
            lambda: self.open_data(self.filelist_w.select_filepath_back()))
        self.right_button = QPushButton("→")
        self.right_button.clicked.connect(
            lambda: self.open_data(self.filelist_w.select_filepath()))

        f_layout.addWidget(self.left_button)
        f_layout.addWidget(self.right_button)
        f_widget.setLayout(f_layout)
        return f_widget

    def set_check(self):
        self.auto_load_next_data_box.setChecked(self.auto_load_next_data)
        self.auto_save_box.setChecked(self.auto_save)
        self.auto_take_over_last_data_box.setChecked(
            self.image_w.auto_take_over_last_data)

    def set_check_func(self):
        self.auto_load_next_data_box.stateChanged.connect(self.change_check)
        self.auto_save_box.stateChanged.connect(self.change_check)
        self.auto_take_over_last_data_box.stateChanged.connect(
            self.change_check)

    def change_check(self):
        self.auto_load_next_data = self.auto_load_next_data_box.isChecked()
        self.auto_save = self.auto_save_box.isChecked()
        self.image_w.auto_take_over_last_data = self.auto_take_over_last_data_box.isChecked(
        )

    def setup_labeling_func(self):
        for w in self.label_w.level_buttons:
            w.clicked.connect(self.labeling)

    def setup_file_func(self):
        for w in self.filelist_w.filelabel_list:
            w.clicked.connect(self.clicked_file)

    def labeling(self):
        lbutton = self.sender()
        return self.__f_labeling(int(lbutton.text()) - 1)

    def __f_labeling(self, level):
        self.image_w.update_labeling_data(level)
        if self.auto_load_next_data:
            if self.image_w.is_last_idx():
                self.save_data()
                self.open_data(self.filelist_w.select_filepath())
                return
        # self.image_w.update_selected_idx()
        img, level = self.image_w.get_selected_area_image()
        self.label_w.update_limage(img, level)

    def save_data(self):
        self.image_w.save_labeling_data(self.auto_save)

    def delete_data(self):
        self.image_w.delete_labeling_data()

    def select_dir(self):
        self.filelist_w.select_dir()
        self.setup_file_func()
        self.open_data(self.filelist_w.get_selected_path())

    def open_data(self, file_path):
        if file_path:
            self.save_data()
            self.file_name.setText(file_path)
            self.image_w.load_image(file_path, self.filelist_w.selected_idx)
            img, level = self.image_w.get_selected_area_image()
            self.label_w.update_limage(img, level)

    def clicked_file(self):
        filelabel = self.sender()
        id = filelabel.id
        self.save_data()
        self.open_data(self.filelist_w.select_filepath(id))

    def closeEvent(self, event):
        self.save_data()

    def keyPressEvent(self, event):
        if event.modifiers() == QtCore.Qt.ControlModifier:
            if event.key() == QtCore.Qt.Key_Up:
                self.image_w.move_selected_idx(v=-1, h=0)
            if event.key() == QtCore.Qt.Key_Down:
                self.image_w.move_selected_idx(v=1, h=0)
            if event.key() == QtCore.Qt.Key_Left:
                self.image_w.move_selected_idx(v=0, h=-1)
            if event.key() == QtCore.Qt.Key_Right:
                self.image_w.move_selected_idx(v=0, h=1)
        else:
            if event.key() == QtCore.Qt.Key_Up:
                self.open_data(self.filelist_w.select_filepath_back())
            if event.key() == QtCore.Qt.Key_Down:
                self.open_data(self.filelist_w.select_filepath())
            if event.key() == QtCore.Qt.Key_Left:
                self.open_data(self.filelist_w.select_filepath_back())
            if event.key() == QtCore.Qt.Key_Right:
                self.open_data(self.filelist_w.select_filepath())
            if event.key() == QtCore.Qt.Key_1:
                self.__f_labeling(0)
            if event.key() == QtCore.Qt.Key_2:
                self.__f_labeling(1)
            if event.key() == QtCore.Qt.Key_3:
                self.__f_labeling(2)
예제 #19
0
파일: app.py 프로젝트: ccidevs/robovision
class AppWindow(QMainWindow):
    """
    Main GUI class for application
    """
    def __init__(self):
        QWidget.__init__(self)

        # loaind ui from xml
        uic.loadUi(os.path.join(DIRPATH, 'app.ui'), self)

        # button event handlers
        self.btnStartCaptureForVideoAnalysis.clicked.connect(
            self.start_capture_for_video_analysis)
        self.btnStopCaptureForVideoAnalysis.clicked.connect(
            self.stop_capture_for_video_analysis)

        self.btnChooseClassifierXML.clicked.connect(
            self.choose_classifier_file)

        self.btnChooseImage.clicked.connect(self.choose_image_for_analysis)

        self.setup_tray_menu()

        # add camera ids
        for i in range(0, 11):
            self.cboxCameraIds.addItem(str(i))
            self.cboxCameraIds1.addItem(str(i))

        # setting up handlers for menubar actions
        self.actionAbout.triggered.connect(self.about)
        self.actionExit.triggered.connect(qApp.quit)
        self.actionPreferences.triggered.connect(self.show_preferences)

        self.img_widget_vid_analysis = ImageWidget()
        self.hlayoutVideoAnalysis.addWidget(self.img_widget_vid_analysis)

        self.img_widget_img_analysis = ImageWidget()
        self.hlayoutImageAnalysis.addWidget(self.img_widget_img_analysis)

        self.vid_capture = VideoCapture()
        self.vid_capture.got_image_data_from_camera.connect(
            self.process_image_data_from_camera)

        self.highlight_faces = self.chkHighlightFaces.isChecked()
        self.chkHighlightFaces.stateChanged.connect(
            self.highlight_faces_checkbox_changed)

    def highlight_faces_checkbox_changed(self):
        if self.chkHighlightFaces.isChecked():
            print("yes")
        else:
            print("no")

    def choose_classifier_file(self):
        fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
        log.info("chose classfier xml file: %s" % fname[0])
        self.teClassifierXML.setText(fname[0])

    def choose_image_for_analysis(self):
        fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
        log.info("chose imagefile: %s, for analysis" % fname[0])
        self.teImage.setText(fname[0])

        img = cv2.imread(fname[0])
        print("type:", type(img))
        #gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        #self.img_widget_img_analysis.handle_image_data(image_data)
        self.img_widget_img_analysis.handle_image_data(img)

    def start_capture_for_video_analysis(self):
        log.debug("start video capture")
        self.vid_capture.start()

    def stop_capture_for_video_analysis(self):
        log.debug("start video capture")
        self.vid_capture.stop()
        self.img_widget_vid_analysis.reset()

    def detect_face_in_image_data(self, image_data):
        """
        function detects faces in image data,
        draws rectangle for faces in image data,
        and returns this updated image data with highlighted face/s
        """
        self._red = (0, 0, 255)
        self._width = 2
        self._min_size = (30, 30)

        # haarclassifiers work better in black and white
        gray_image = cv2.cvtColor(image_data, cv2.COLOR_BGR2GRAY)
        gray_image = cv2.equalizeHist(gray_image)

        # path to Haar face classfier's xml file
        face_cascade_xml = './cascades/haarcascades_cuda/haarcascade_frontalface_default.xml'
        self.classifier = cv2.CascadeClassifier(face_cascade_xml)
        faces = self.classifier.detectMultiScale(gray_image,
                                                 scaleFactor=1.3,
                                                 minNeighbors=4,
                                                 flags=cv2.CASCADE_SCALE_IMAGE,
                                                 minSize=self._min_size)

        for (x, y, w, h) in faces:
            cv2.rectangle(image_data, (x, y), (x + w, y + h), self._red,
                          self._width)

        return image_data

    def process_image_data_from_camera(self, image_data):
        if self.chkHighlightFaces.isChecked():
            image_data = self.detect_face_in_image_data(image_data)
        self.img_widget_vid_analysis.handle_image_data(image_data)

    def about(self):
        ad = AboutDialog()
        ad.display()

    def show_preferences(self):
        print("preferences")
        pd = PrefsDialog()
        pd.display()

    def setup_tray_menu(self):

        # setting up QSystemTrayIcon
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(self.style().standardIcon(
            QStyle.SP_ComputerIcon))

        # tray actions
        show_action = QAction("Show", self)
        quit_action = QAction("Exit", self)
        hide_action = QAction("Hide", self)

        # action handlers
        show_action.triggered.connect(self.show)
        hide_action.triggered.connect(self.hide)
        quit_action.triggered.connect(qApp.quit)

        # tray menu
        tray_menu = QMenu()
        tray_menu.addAction(show_action)
        tray_menu.addAction(hide_action)
        tray_menu.addAction(quit_action)
        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()

    def closeEvent(self, event):
        event.ignore()
        self.hide()
        self.tray_icon.showMessage("RoboVision",
                                   "RoboVision was minimized to Tray",
                                   QSystemTrayIcon.Information, 2000)

    def ok_pressed(self):
        log.debug("[AppWindow] :: ok")
        self.show_msgbox("AppWindow", "Its ok")

    def show_msgbox(self, title, text):
        """
        Function for showing error/info message box
        """
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText(text)
        msg.setWindowTitle(title)
        msg.setStandardButtons(QMessageBox.Ok)

        retval = msg.exec_()
        print("[INFO] Value of pressed message box button:", retval)
예제 #20
0
class AnnotationPlugin(Plugin):
    def __init__(self, context):
        """
        Annotation plugin to create and edit data sets either by manual annotation or automatically, e.g. using
        a tracker, and generating larger data sets with data augmentation.
        :param context: Parent QT widget
        """
        super(AnnotationPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Label Plugin')

        self.widget = QWidget()
        context.add_widget(self.widget)
        self.widget.resize(1800, 1000)
        """left side (current image, grab img button, ...)"""

        self.cur_im_widget = ImageWidget(self.widget,
                                         self.roi_callback,
                                         clear_on_click=False)
        self.cur_im_widget.setGeometry(QRect(20, 20, 640, 480))

        self.grab_img_button = QPushButton(self.widget)
        self.grab_img_button.setText("Grab frame")
        self.grab_img_button.clicked.connect(self.grab_frame)
        self.grab_img_button.setGeometry(QRect(20, 600, 100, 50))
        """right side (selected image, workspace...)"""

        self.sel_im_widget = ImageWidget(self.widget,
                                         self.roi_callback,
                                         clear_on_click=True)
        self.sel_im_widget.setGeometry(QRect(720, 20, 640, 480))
        """list widgets for images and annotations"""

        self.annotation_list_widget = QListWidget(self.widget)
        self.annotation_list_widget.setGeometry(QRect(1400, 50, 150, 200))
        self.annotation_list_widget.setObjectName("annotation_list_widget")
        self.annotation_list_widget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.annotation_list_widget.currentItemChanged.connect(
            self.select_annotation)

        self.image_list_widget = QListWidget(self.widget)
        self.image_list_widget.setGeometry(QRect(1550, 50, 250, 500))
        self.image_list_widget.setObjectName("image_list_widget")
        self.image_list_widget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.image_list_widget.currentItemChanged.connect(self.select_image)

        self.output_path_edit = QLineEdit(self.widget)
        self.output_path_edit.setGeometry(QRect(1400, 20, 300, 30))
        self.output_path_edit.setDisabled(True)

        self.edit_path_button = QPushButton(self.widget)
        self.edit_path_button.setText("set ws")
        self.edit_path_button.setGeometry(QRect(1700, 20, 100, 30))
        self.edit_path_button.clicked.connect(self.get_workspace)
        """ buttons for adding or deleting annotations"""
        self.add_annotation_button = QPushButton(self.widget)
        self.add_annotation_button.setText("add")
        self.add_annotation_button.setGeometry(QRect(1400, 250, 75, 30))
        self.add_annotation_button.clicked.connect(self.add_annotation)

        self.remove_annotation_button = QPushButton(self.widget)
        self.remove_annotation_button.setText("del")
        self.remove_annotation_button.setGeometry(QRect(1475, 250, 75, 30))
        self.remove_annotation_button.clicked.connect(
            self.remove_current_annotation)
        """label combo box, line edit and button for adding labels"""
        self.option_selector = QComboBox(self.widget)
        self.option_selector.currentIndexChanged.connect(self.class_change)
        self.option_selector.setGeometry(1400, 280, 150, 30)

        self.label_edit = QLineEdit(self.widget)
        self.label_edit.setGeometry(QRect(1400, 310, 100, 30))
        self.label_edit.setDisabled(False)

        self.edit_label_button = QPushButton(self.widget)
        self.edit_label_button.setText("add")
        self.edit_label_button.setGeometry(QRect(1500, 310, 50, 30))
        self.edit_label_button.clicked.connect(self.add_label)
        """ button for image deletion"""
        self.remove_image_button = QPushButton(self.widget)
        self.remove_image_button.setText("delete image")
        self.remove_image_button.setGeometry(QRect(1550, 550, 150, 30))
        self.remove_image_button.clicked.connect(self.remove_current_image)
        """ export data """
        self.gen_data_label = QLabel(self.widget)
        self.gen_data_label.setText("Export workspace: ")
        self.gen_data_label.setGeometry(QRect(1550, 650, 250, 50))

        self.export_ws_button = QPushButton(self.widget)
        self.export_ws_button.setText("Export")
        self.export_ws_button.setGeometry(QRect(1550, 700, 125, 50))
        self.export_ws_button.clicked.connect(self.export_workspace_to_tf)

        self.conf_export_button = QPushButton(self.widget)
        self.conf_export_button.setText("Configure")
        self.conf_export_button.setGeometry(QRect(1675, 700, 125, 50))
        self.conf_export_button.clicked.connect(self.set_export_parameters)
        """ generate augmented data """

        self.gen_data_label = QLabel(self.widget)
        self.gen_data_label.setText("Generate augmented dataset:")
        self.gen_data_label.setGeometry(QRect(1550, 800, 250, 50))

        self.gen_data_button = QPushButton(self.widget)
        self.gen_data_button.setText("Generate")
        self.gen_data_button.setGeometry(QRect(1550, 850, 125, 50))
        self.gen_data_button.clicked.connect(self.generate_augmented_data)

        self.gen_data_button = QPushButton(self.widget)
        self.gen_data_button.setText("Configure")
        self.gen_data_button.setGeometry(QRect(1675, 850, 125, 50))
        self.gen_data_button.clicked.connect(
            self.set_data_augmentation_parameters)
        """ functional stuff"""
        self.bridge = CvBridge()

        self.sub = None

        self.class_id = -1
        self.label = ""
        self.changes_done = False

        self.workspace = None
        self.labels = []
        self.images_with_annotations = []
        self.cur_annotated_image = None
        self.cur_annotation_index = -1

        self.class_change()

        # export parameters
        self.default_config_path = None
        self.pretrained_graph = None
        self.p_test = 0.2
        self.batch_size = 12

        # data augmentation parameters
        self.gen_dir = None
        self.num_illuminate = 1
        self.num_scale = 1
        self.num_blur = 1

    def set_data_augmentation_parameters(self):
        self.gen_dir = QFileDialog.getExistingDirectory(
            self.widget, "Select output directory")

        num_illum, ok = QInputDialog.getText(self.widget,
                                             "Illumination changes per image",
                                             "1")
        if ok:
            try:
                self.num_illuminate = int(num_illum)
            except ValueError:
                pass
        num_scale, ok = QInputDialog.getText(self.widget,
                                             "Scaling changes per image", "1")
        if ok:
            try:
                self.num_scale = int(num_scale)
            except ValueError:
                pass
        num_blur, ok = QInputDialog.getText(self.widget,
                                            "Blurring changes per image", "1")
        if ok:
            try:
                self.num_blur = int(num_blur)
            except ValueError:
                pass

    def generate_augmented_data(self):
        if self.gen_dir is None:
            warning_dialog("Warning", "Set parameters first")
            return
        data_augmentation.multiply_dataset(self.workspace, self.gen_dir, None,
                                           0, self.num_illuminate,
                                           self.num_scale, self.num_blur, 0)
        print("data augmentation done")

    def set_export_parameters(self):
        """ Set variables for export via QInputDialog and QFileDialog. """
        # default config path
        config_path = QFileDialog.getOpenFileName(self.widget,
                                                  "Select default config")
        config_path = str(config_path[0])
        file, ext = os.path.splitext(config_path)
        if not ext == ".config":
            self.default_config_path = None
            warning_dialog("warning", "invalid file extension")
            return
        else:
            self.default_config_path = config_path

        # pretrained graph
        pretrained_graph_dir = QFileDialog.getExistingDirectory(
            self.widget, "Select pretrained graph directory")
        self.pretrained_graph = pretrained_graph_dir + "/model.ckpt"

        # batch size
        batch_size, ok = QInputDialog.getText(self.widget, "Set batch size",
                                              "12")
        if ok:
            try:
                self.batch_size = int(batch_size)
            except ValueError:
                pass

        # test percentage
        p_test, ok = QInputDialog.getText(self.widget, "Set test percentage",
                                          "0.2")
        if ok:
            try:
                self.p_test = float(p_test)
            except ValueError:
                pass

    def export_workspace_to_tf(self):
        """ Export workspace to training formats. """
        if self.default_config_path is None or self.pretrained_graph is None:
            warning_dialog("Warning",
                           "define default config and pretrained graph first")
            return

        tf_utils.export_data_to_tf(self.workspace,
                                   self.images_with_annotations, self.labels,
                                   self.p_test, self.default_config_path,
                                   self.batch_size, self.pretrained_graph,
                                   True)
        tf_utils.create_roi_images(self.workspace,
                                   self.images_with_annotations, self.labels)
        print("Export done")

    def add_label(self):
        """ If label doesn't exist yet, add to the list and combo box. """
        new_label = str(self.label_edit.text())
        if new_label is None or new_label == "":
            return

        for label in self.labels:
            if label[0] == new_label:
                warning_dialog("warning",
                               "label\"" + label[0] + "\" already exists")
                return
        new_label = list((new_label, 0))
        self.labels.append(new_label)
        self.option_selector.addItem(new_label[0])

        label_file = self.workspace + "/labels.txt"
        utils.write_labels(label_file, self.labels)

    def add_annotation(self):
        """ Add annotation to current image. Bounding box is just a dummy. Use current label. """
        if self.class_id == -1 or self.label == "":
            warning_dialog("Warning", "select label first")
            return
        if self.cur_annotated_image is None:
            warning_dialog("Warning", "select image first")
            return
        label = self.option_selector.currentText()
        annotation = utils.AnnotationWithBbox(self.class_id, 1.0, 0.5, 0.5, 1,
                                              1)
        self.cur_annotated_image.annotation_list.append(annotation)
        index = len(self.cur_annotated_image.annotation_list) - 1
        self.add_annotation_to_list_widget(index, label, True)

        self.changes_done = True

    def class_change(self):
        """ Called another label is selected in the combo box. Set current label and class id. """
        self.label = self.option_selector.currentText()
        if self.labels is None or len(self.labels) == 0:
            return
        self.class_id = [i[0] for i in self.labels].index(self.label)
        # num_annotations = self.labels[self.class_id][1]

    def select_annotation(self):
        """
            Called when an annotation is selected. The corresponding bounding box is drawn thicker,
            enables drawing on the image widget.
        """
        item = self.annotation_list_widget.currentItem()
        if item is None:
            self.sel_im_widget.set_active(False)
            self.sel_im_widget.clear()
            return
        text = str(item.text())
        index = text.split(":")[0]
        self.cur_annotation_index = int(index)
        self.show_image_from_workspace()
        self.sel_im_widget.set_active(True)

    def select_image(self):
        """
            Called when an image from the list is selected.
            Save annotations, if changes were made. Then show selected image and its annotation list.
        """
        if self.changes_done:
            utils.save_annotations(self.cur_annotated_image.image_file,
                                   self.cur_annotated_image.annotation_list)
            self.changes_done = False

        item = self.image_list_widget.currentItem()
        if item is None:
            return
        image_file = self.workspace + str(item.text())
        self.cur_annotated_image = None
        for img in self.images_with_annotations:
            if img.image_file == image_file:
                self.cur_annotated_image = img
        if self.cur_annotated_image is not None:
            self.show_image_from_workspace()
            self.set_annotation_list()

    def set_annotation_list(self):
        """ Set list of annotations for the current image. """
        self.annotation_list_widget.clear()
        self.cur_annotation_index = -1
        for i in range(len(self.cur_annotated_image.annotation_list)):

            index = int(self.cur_annotated_image.annotation_list[i].label)
            num_labels = len(self.labels)
            if index < num_labels:
                self.add_annotation_to_list_widget(i, self.labels[index][0])
            else:
                self.add_annotation_to_list_widget(i, "unknown")
        self.show_image_from_workspace()

    def add_annotation_to_list_widget(self, index, label, select=False):
        """
            Add a QListWidgetItem to the annotation QListWidget
            :param index: index in annotation list
            :param label: label of annotation
            :param select: select new item or not
        """
        item = QListWidgetItem()
        item.setText(str(index) + ":" + label)
        self.annotation_list_widget.addItem(item)
        if select:
            self.annotation_list_widget.setCurrentItem(item)
            self.select_annotation()

    def add_image_to_list_widget(self, file_name, select=False):
        """
            Add a QListWidgetItem to the image QListWidget
            :param file_name: image file name
            :param select: select new item or not
        """
        item = QListWidgetItem()
        item.setText(file_name)
        self.image_list_widget.addItem(item)
        if select:
            self.image_list_widget.setCurrentItem(item)
            self.select_image()

    def refresh_image_list_widget(self):
        """ Clear and fill image list widget """
        self.image_list_widget.clear()
        for img in self.images_with_annotations:
            self.add_image_to_list_widget(
                img.image_file.replace(self.workspace, ""))

    def remove_current_annotation(self):
        """ Remove currently selected annotation """
        if self.cur_annotation_index == -1:
            warning_dialog("Warning", "no annotation selected")
            return
        del (self.cur_annotated_image.annotation_list[
            self.cur_annotation_index])
        self.set_annotation_list()

    def remove_current_image(self):
        """ Remove currently selected image. Remove ItemWidget and delete files """
        if self.cur_annotated_image is None:
            warning_dialog("Warning", "no image selected")
            return
        image_file = self.cur_annotated_image.image_file
        label_file = image_file.replace("images",
                                        "labels").replace("jpg", "txt")
        self.image_list_widget.removeItemWidget(
            self.image_list_widget.currentItem())
        self.images_with_annotations.remove(self.cur_annotated_image)

        os.remove(image_file)
        if os.path.isfile(label_file):
            os.remove(label_file)

        self.refresh_image_list_widget()

    def get_workspace(self):
        """ Gets and sets the output directory via a QFileDialog. Save before, if changes were done. """
        if self.changes_done:
            utils.save_annotations(self.cur_annotated_image.image_file,
                                   self.cur_annotated_image.annotation_list)
            self.changes_done = False

        self.load_workspace(
            QFileDialog.getExistingDirectory(self.widget,
                                             "Select output directory"))

    def load_workspace(self, path):
        """
        Sets the workspace directory. Checks for missing directories and files,
        then loads all images, annotations & label list.
        :param path: The path of the directory
        """
        if not path:
            path = "/tmp"

        self.workspace = path
        self.output_path_edit.setText(path)

        # clear all lists and references
        self.labels = []
        self.cur_annotation_index = -1
        self.cur_annotated_image = None
        self.images_with_annotations = []
        self.changes_done = False
        self.class_id = -1
        self.label = ""

        # clear combo box and listWidgets
        self.option_selector.clear()
        self.image_list_widget.clear()
        self.annotation_list_widget.clear()

        if utils.check_workspace(self.workspace):
            image_dir = self.workspace + "/images"
            label_file = self.workspace + "/labels.txt"

            self.labels = utils.read_labels(label_file)
            for label in self.labels:
                self.option_selector.addItem(label[0])

            for dirname, dirnames, filenames in os.walk(image_dir):
                for filename in sorted(filenames):
                    image_file = dirname + '/' + filename
                    label_file = image_file.replace(
                        "images",
                        "labels").replace(".jpg",
                                          ".txt").replace(".png", ".txt")
                    annotated_image = utils.read_annotated_image(
                        image_file, label_file)
                    self.images_with_annotations.append(annotated_image)
                    self.add_image_to_list_widget("/images/" + filename)
            print("workspace loaded successfully")

    def grab_frame(self):
        """ Grab current frame, save to workspace and show it."""
        if self.workspace is None or self.workspace == "":
            warning_dialog("Warning", "select workspace first")
            return
        cv_image = self.cur_im_widget.get_image()
        if cv_image is None:
            warning_dialog("warning", "no frame to grab")
            return
        file_name = "/images/{}.jpg".format(
            datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S_%f"))
        new_image = utils.AnnotatedImage(self.workspace + file_name, [])
        self.cur_annotated_image = new_image
        self.images_with_annotations.append(new_image)
        cv2.imwrite(self.workspace + file_name, cv_image)
        self.add_image_to_list_widget(file_name, True)
        self.select_image()
#        self.sel_im_widget.set_image(cv_image, None, None)

    def roi_callback(self):
        """ Called when a roi is drawn on an image_widget. Edit annotation if possible. """
        if self.class_id == -1 or self.label == "":
            warning_dialog("Warning", "select label first")
            self.changes_done = True
            return
        if self.cur_annotation_index < 0:
            warning_dialog("Warning", "select annotation first")
            self.changes_done = True
            return

        # set bounding box
        x_center, y_center, width, height = self.sel_im_widget.get_normalized_roi(
        )
        annotation = self.cur_annotated_image.annotation_list[
            self.cur_annotation_index]
        annotation.bbox = utils.BoundingBox(x_center, y_center, width, height)

        # set selected label
        self.label = self.option_selector.currentText()
        if self.labels is None or len(self.labels) == 0:
            return
        self.class_id = [i[0] for i in self.labels].index(self.label)
        annotation.label = self.class_id

        self.set_annotation_list()
        self.show_image_from_workspace()
        self.sel_im_widget.clear()

        self.changes_done = True

    def show_image_from_workspace(self):
        """ Show current selected image and annotations """
        if self.cur_annotated_image is None:
            return
        img = cv2.imread(self.cur_annotated_image.image_file)
        if img is not None:
            self.sel_im_widget.set_image(
                img, self.cur_annotated_image.annotation_list,
                self.cur_annotation_index)

    def image_callback(self, msg):
        """
        Called when a new sensor_msgs/Image is coming in
        :param msg: The image message
        """
        try:
            cv_image = self.bridge.imgmsg_to_cv2(msg, "bgr8")
        except CvBridgeError as e:
            rospy.logerr(e)

        self.cur_im_widget.set_image(cv_image, None, None)

    def trigger_configuration(self):
        """
        Callback when the configuration button is clicked
        """
        topic_name, ok = QInputDialog.getItem(
            self.widget, "Select topic name", "Topic name",
            rostopic.find_by_type('sensor_msgs/Image'))
        if ok:
            self.create_subscriber(topic_name)

    def create_subscriber(self, topic_name):
        """
        Method that creates a subscriber to a sensor_msgs/Image topic
        :param topic_name: The topic_name
        """
        if self.sub:
            self.sub.unregister()
        self.sub = rospy.Subscriber(topic_name, Image, self.image_callback)
        rospy.loginfo("Listening to %s -- spinning .." % self.sub.name)
        self.widget.setWindowTitle("Label plugin, listening to (%s)" %
                                   self.sub.name)

    def shutdown_plugin(self):
        """
        Callback function when shutdown is requested
        """
        if self.changes_done:
            utils.save_annotations(self.cur_annotated_image.image_file,
                                   self.cur_annotated_image.annotation_list)

    def save_settings(self, plugin_settings, instance_settings):
        """
        Callback function on shutdown to store the local plugin variables
        :param plugin_settings: Plugin settings
        :param instance_settings: Settings of this instance
        """
        instance_settings.set_value("workspace_dir", self.workspace)

    def restore_settings(self, plugin_settings, instance_settings):
        """
        Callback function fired on load of the plugin that allows to restore saved variables
        :param plugin_settings: Plugin settings
        :param instance_settings: Settings of this instance
        """
        workspace = None
        try:
            workspace = instance_settings.value("workspace_dir")
        except:
            pass
        self.load_workspace(workspace)
        self.create_subscriber(
            str(instance_settings.value("topic_name", "/xtion/rgb/image_raw")))
예제 #21
0
    def __init__(self, context):
        """
        Annotation plugin to create and edit data sets either by manual annotation or automatically, e.g. using
        a tracker, and generating larger data sets with data augmentation.
        :param context: Parent QT widget
        """
        super(AnnotationPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Label Plugin')

        self.widget = QWidget()
        context.add_widget(self.widget)
        self.widget.resize(1800, 1000)
        """left side (current image, grab img button, ...)"""

        self.cur_im_widget = ImageWidget(self.widget,
                                         self.roi_callback,
                                         clear_on_click=False)
        self.cur_im_widget.setGeometry(QRect(20, 20, 640, 480))

        self.grab_img_button = QPushButton(self.widget)
        self.grab_img_button.setText("Grab frame")
        self.grab_img_button.clicked.connect(self.grab_frame)
        self.grab_img_button.setGeometry(QRect(20, 600, 100, 50))
        """right side (selected image, workspace...)"""

        self.sel_im_widget = ImageWidget(self.widget,
                                         self.roi_callback,
                                         clear_on_click=True)
        self.sel_im_widget.setGeometry(QRect(720, 20, 640, 480))
        """list widgets for images and annotations"""

        self.annotation_list_widget = QListWidget(self.widget)
        self.annotation_list_widget.setGeometry(QRect(1400, 50, 150, 200))
        self.annotation_list_widget.setObjectName("annotation_list_widget")
        self.annotation_list_widget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.annotation_list_widget.currentItemChanged.connect(
            self.select_annotation)

        self.image_list_widget = QListWidget(self.widget)
        self.image_list_widget.setGeometry(QRect(1550, 50, 250, 500))
        self.image_list_widget.setObjectName("image_list_widget")
        self.image_list_widget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)
        self.image_list_widget.currentItemChanged.connect(self.select_image)

        self.output_path_edit = QLineEdit(self.widget)
        self.output_path_edit.setGeometry(QRect(1400, 20, 300, 30))
        self.output_path_edit.setDisabled(True)

        self.edit_path_button = QPushButton(self.widget)
        self.edit_path_button.setText("set ws")
        self.edit_path_button.setGeometry(QRect(1700, 20, 100, 30))
        self.edit_path_button.clicked.connect(self.get_workspace)
        """ buttons for adding or deleting annotations"""
        self.add_annotation_button = QPushButton(self.widget)
        self.add_annotation_button.setText("add")
        self.add_annotation_button.setGeometry(QRect(1400, 250, 75, 30))
        self.add_annotation_button.clicked.connect(self.add_annotation)

        self.remove_annotation_button = QPushButton(self.widget)
        self.remove_annotation_button.setText("del")
        self.remove_annotation_button.setGeometry(QRect(1475, 250, 75, 30))
        self.remove_annotation_button.clicked.connect(
            self.remove_current_annotation)
        """label combo box, line edit and button for adding labels"""
        self.option_selector = QComboBox(self.widget)
        self.option_selector.currentIndexChanged.connect(self.class_change)
        self.option_selector.setGeometry(1400, 280, 150, 30)

        self.label_edit = QLineEdit(self.widget)
        self.label_edit.setGeometry(QRect(1400, 310, 100, 30))
        self.label_edit.setDisabled(False)

        self.edit_label_button = QPushButton(self.widget)
        self.edit_label_button.setText("add")
        self.edit_label_button.setGeometry(QRect(1500, 310, 50, 30))
        self.edit_label_button.clicked.connect(self.add_label)
        """ button for image deletion"""
        self.remove_image_button = QPushButton(self.widget)
        self.remove_image_button.setText("delete image")
        self.remove_image_button.setGeometry(QRect(1550, 550, 150, 30))
        self.remove_image_button.clicked.connect(self.remove_current_image)
        """ export data """
        self.gen_data_label = QLabel(self.widget)
        self.gen_data_label.setText("Export workspace: ")
        self.gen_data_label.setGeometry(QRect(1550, 650, 250, 50))

        self.export_ws_button = QPushButton(self.widget)
        self.export_ws_button.setText("Export")
        self.export_ws_button.setGeometry(QRect(1550, 700, 125, 50))
        self.export_ws_button.clicked.connect(self.export_workspace_to_tf)

        self.conf_export_button = QPushButton(self.widget)
        self.conf_export_button.setText("Configure")
        self.conf_export_button.setGeometry(QRect(1675, 700, 125, 50))
        self.conf_export_button.clicked.connect(self.set_export_parameters)
        """ generate augmented data """

        self.gen_data_label = QLabel(self.widget)
        self.gen_data_label.setText("Generate augmented dataset:")
        self.gen_data_label.setGeometry(QRect(1550, 800, 250, 50))

        self.gen_data_button = QPushButton(self.widget)
        self.gen_data_button.setText("Generate")
        self.gen_data_button.setGeometry(QRect(1550, 850, 125, 50))
        self.gen_data_button.clicked.connect(self.generate_augmented_data)

        self.gen_data_button = QPushButton(self.widget)
        self.gen_data_button.setText("Configure")
        self.gen_data_button.setGeometry(QRect(1675, 850, 125, 50))
        self.gen_data_button.clicked.connect(
            self.set_data_augmentation_parameters)
        """ functional stuff"""
        self.bridge = CvBridge()

        self.sub = None

        self.class_id = -1
        self.label = ""
        self.changes_done = False

        self.workspace = None
        self.labels = []
        self.images_with_annotations = []
        self.cur_annotated_image = None
        self.cur_annotation_index = -1

        self.class_change()

        # export parameters
        self.default_config_path = None
        self.pretrained_graph = None
        self.p_test = 0.2
        self.batch_size = 12

        # data augmentation parameters
        self.gen_dir = None
        self.num_illuminate = 1
        self.num_scale = 1
        self.num_blur = 1
class AnnotationPlugin(Plugin):
    def __init__(self, context):
        """
        Annotation plugin to create data sets or test the Annotate.srv service
        :param context: Parent QT widget
        """
        super(AnnotationPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Label Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)

        # Layout and attach to widget
        layout = QVBoxLayout()
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget,
                                         self.image_roi_callback,
                                         clear_on_click=True)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._edit_path_button = QPushButton("Edit path")
        self._edit_path_button.clicked.connect(self._get_output_directory)
        grid_layout.addWidget(self._edit_path_button, 1, 1)

        self._output_path_edit = QLineEdit()
        self._output_path_edit.setDisabled(True)
        grid_layout.addWidget(self._output_path_edit, 1, 2)

        self._labels_edit = QLineEdit()
        self._labels_edit.setDisabled(True)
        grid_layout.addWidget(self._labels_edit, 2, 2)

        self._edit_labels_button = QPushButton("Edit labels")
        self._edit_labels_button.clicked.connect(self._get_labels)
        grid_layout.addWidget(self._edit_labels_button, 2, 1)

        self._save_button = QPushButton("Annotate again!")
        self._save_button.clicked.connect(self.annotate_again_clicked)
        grid_layout.addWidget(self._save_button, 2, 3)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set subscriber to None
        self._sub = None
        self._srv = None

        self.labels = []
        self.label = ""
        self.output_directory = ""

    def image_roi_callback(self, roi_image):
        """
        Callback from the image widget when the user has selected a ROI
        :param roi_image: The opencv image of the ROI
        """
        if not self.labels:
            warning_dialog(
                "No labels specified!",
                "Please first specify some labels using the 'Edit labels' button"
            )
            return

        height, width = roi_image.shape[:2]

        option = option_dialog("Label", self.labels)
        if option:
            self.label = option
            self._image_widget.add_detection(0, 0, width, height, option)
            self.annotate(roi_image)

    def annotate_again_clicked(self):
        """
        Triggered when button clicked
        """
        roi_image = self._image_widget.get_roi_image()
        if roi_image is not None:
            self.annotate(roi_image)

    def annotate(self, roi_image):
        """
        Create an annotation
        :param roi_image: The image we want to annotate
        """
        self.annotate_srv(roi_image)
        self.store_image(roi_image)

    def annotate_srv(self, roi_image):
        """
        Call the selected Annotate.srv
        :param roi_image: The full opencv image we want to annotate
        """
        if roi_image is not None and self.label is not None and self._srv is not None:
            height, width = roi_image.shape[:2]
            try:
                self._srv(image=self.bridge.cv2_to_imgmsg(roi_image, "bgr8"),
                          annotations=[
                              Annotation(label=self.label,
                                         roi=RegionOfInterest(x_offset=0,
                                                              y_offset=0,
                                                              width=width,
                                                              height=height))
                          ])
            except Exception as e:
                warning_dialog("Service Exception", str(e))

    def _create_service_client(self, srv_name):
        """
        Create a service client proxy
        :param srv_name: Name of the service
        """
        if self._srv:
            self._srv.close()

        if srv_name in rosservice.get_service_list():
            rospy.loginfo("Creating proxy for service '%s'" % srv_name)
            self._srv = rospy.ServiceProxy(
                srv_name, rosservice.get_service_class_by_name(srv_name))

    def store_image(self, roi_image):
        """
        Store the image
        :param roi_image: Image we would like to store
        """
        if roi_image is not None and self.label is not None and self.output_directory is not None:
            image_writer.write_annotated(self.output_directory, roi_image,
                                         self.label, True)

    def _get_output_directory(self):
        """
        Gets and sets the output directory via a QFileDialog
        """
        self._set_output_directory(
            QFileDialog.getExistingDirectory(self._widget,
                                             "Select output directory"))

    def _set_output_directory(self, path):
        """
        Sets the output directory
        :param path: The path of the directory
        """
        if not path:
            path = "/tmp"

        self.output_directory = path
        self._output_path_edit.setText("Saving images to %s" % path)

    def _get_labels(self):
        """
        Gets and sets the labels
        """
        text, ok = QInputDialog.getText(
            self._widget, 'Text Input Dialog',
            'Type labels semicolon separated, e.g. banana;apple:',
            QLineEdit.Normal, ";".join(self.labels))
        if ok:
            labels = set([
                _sanitize(label) for label in str(text).split(";")
                if _sanitize(label)
            ])  # Sanitize to alphanumeric, exclude spaces
            self._set_labels(labels)

    def _set_labels(self, labels):
        """
        Sets the labels
        :param labels: label string array
        """
        if not labels:
            labels = []

        self.labels = labels
        self._labels_edit.setText("%s" % labels)

    def _image_callback(self, msg):
        """
        Called when a new sensor_msgs/Image is coming in
        :param msg: The image messaeg
        """
        try:
            cv_image = self.bridge.imgmsg_to_cv2(msg, "bgr8")
        except CvBridgeError as e:
            rospy.logerr(e)

        self._image_widget.set_image(cv_image)

    def trigger_configuration(self):
        """
        Callback when the configuration button is clicked
        """
        topic_name, ok = QInputDialog.getItem(
            self._widget, "Select topic name", "Topic name",
            rostopic.find_by_type('sensor_msgs/Image'))
        if ok:
            self._create_subscriber(topic_name)

        available_rosservices = []
        for s in rosservice.get_service_list():
            try:
                if rosservice.get_service_type(s) in _SUPPORTED_SERVICES:
                    available_rosservices.append(s)
            except:
                pass

        srv_name, ok = QInputDialog.getItem(self._widget,
                                            "Select service name",
                                            "Service name",
                                            available_rosservices)
        if ok:
            self._create_service_client(srv_name)

    def _create_subscriber(self, topic_name):
        """
        Method that creates a subscriber to a sensor_msgs/Image topic
        :param topic_name: The topic_name
        """
        if self._sub:
            self._sub.unregister()
        self._sub = rospy.Subscriber(topic_name, Image, self._image_callback)
        rospy.loginfo("Listening to %s -- spinning .." % self._sub.name)
        self._widget.setWindowTitle("Label plugin, listening to (%s)" %
                                    self._sub.name)

    def shutdown_plugin(self):
        """
        Callback function when shutdown is requested
        """
        pass

    def save_settings(self, plugin_settings, instance_settings):
        """
        Callback function on shutdown to store the local plugin variables
        :param plugin_settings: Plugin settings
        :param instance_settings: Settings of this instance
        """
        instance_settings.set_value("output_directory", self.output_directory)
        instance_settings.set_value("labels", self.labels)
        if self._sub:
            instance_settings.set_value("topic_name", self._sub.name)

    def restore_settings(self, plugin_settings, instance_settings):
        """
        Callback function fired on load of the plugin that allows to restore saved variables
        :param plugin_settings: Plugin settings
        :param instance_settings: Settings of this instance
        """
        path = None
        try:
            path = instance_settings.value("output_directory")
        except:
            pass
        self._set_output_directory(path)

        labels = None
        try:
            labels = instance_settings.value("labels")
        except:
            pass
        self._set_labels(labels)

        self._create_subscriber(
            str(instance_settings.value("topic_name", "/usb_cam/image_raw")))
        self._create_service_client(
            str(
                instance_settings.value("service_name",
                                        "/image_recognition/my_service")))
예제 #23
0
    def __init__(self):
        QWidget.__init__(self)

        # loaind ui from xml
        uic.loadUi(os.path.join(DIRPATH, 'app.ui'), self)

        # FIXME - libpng warning: iCCP: known incorrect sRGB profile
        self.setWindowIcon(QIcon("./images/robot_icon.png"))

        # keep the window fixed sized
        self.setFixedSize(self.size())

        # button event handlers
        self.btnStartCaptureForVideoAnalysis.clicked.connect(
            self.start_capture_for_video_analysis)
        self.btnStopCaptureForVideoAnalysis.clicked.connect(
            self.stop_capture_for_video_analysis)

        self.btnChooseClassifierXML.clicked.connect(
            self.choose_classifier_file)

        self.btnChooseImage.clicked.connect(self.choose_image_for_analysis)

        self.setup_tray_menu()

        # add camera ids
        for i in range(0, 11):
            self.cboxCameraIds.addItem(str(i))
            self.cboxCameraIds1.addItem(str(i))

        # setting up handlers for menubar actions
        self.actionAbout.triggered.connect(self.about)
        self.actionExit.triggered.connect(qApp.quit)
        self.actionPreferences.triggered.connect(self.show_preferences)

        # video analysis image widget
        self.img_widget_vid_analysis = ImageWidget()
        self.hlayoutVideoAnalysis.addWidget(self.img_widget_vid_analysis)

        # face training image widget
        self.img_widget_face_training = ImageWidget()
        self.hlayoutFaceTrainingImg.addWidget(self.img_widget_face_training)

        # face identification image widget
        self.img_widget_identify_face = ImageWidget()
        self.hlayoutIdentifyFace.addWidget(self.img_widget_identify_face)

        # image analysis image widget
        self.img_widget_img_analysis = ImageWidget()
        self.hlayoutImageAnalysis.addWidget(self.img_widget_img_analysis)
        img = cv2.imread("images/human.png")
        self.img_widget_img_analysis.handle_image_data(img)

        self.vid_capture = VideoCapture()
        self.vid_capture.got_image_data_from_camera.connect(
            self.process_image_data_from_camera)

        self.highlight_faces = self.chkHighlightFaces.isChecked()
        self.chkHighlightFaces.stateChanged.connect(
            self.highlight_faces_checkbox_changed)
        self.chckGrayscale.stateChanged.connect(
            self.grayscale_checkbox_changed)

        # face trainer dataset browser btn handler
        self.btnBrowseDatasetForFaceTrainer.clicked.connect(
            self.browse_dataset_for_face_trainer)
        self.btnBrowseClassifierForFaceTrainer.clicked.connect(
            self.browse_classifier_file_for_face_trainer)
        self.btnStartFaceTrainer.clicked.connect(self.start_face_trainer)

        self.btnBrowseIdentifyFace.clicked.connect(self.browse_identify_face)

        self.btnTalk.clicked.connect(self.lets_talk)

        # create and start robot
        self.robot = Robot(self.lblRobot)

        self.mouth = Mouth()

        # connect global signals to slots
        g_emitter().feed_mouth.connect(self.mouth.feed_text)
        g_emitter().set_speaking_state.connect(self.robot.set_speaking_state)
        g_emitter().set_idle_state.connect(self.robot.set_idle_state)

        self.robot.start()
        self.mouth.start()
class TestPlugin(Plugin):
    def __init__(self, context):
        super(TestPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Test Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)

        # Layout and attach to widget
        layout = QVBoxLayout()
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget, self.image_roi_callback)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._info = QLineEdit()
        self._info.setDisabled(True)
        self._info.setText(
            "Draw a rectangle on the screen to perform object recognition of that ROI"
        )
        layout.addWidget(self._info)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set subscriber and service to None
        self._sub = None
        self._srv = None

    def image_roi_callback(self, roi_image):
        if self._srv is None:
            warning_dialog(
                "No service specified!",
                "Please first specify a service via the options button (top-right gear wheel)"
            )
            return

        try:
            result = self._srv(
                image=self.bridge.cv2_to_imgmsg(roi_image, "bgr8"))
        except Exception as e:
            warning_dialog("Service Exception", str(e))
            return

        text_array = [
            "%s: %.2f" % (r.label, r.probability) for r in result.recognitions
        ]

        if text_array:
            self._image_widget.set_text(
                text_array[0])  # Show first option in the image
            option_dialog("Classification results",
                          text_array)  # Show all results in a dropdown

    def _image_callback(self, msg):
        try:
            cv_image = self.bridge.imgmsg_to_cv2(msg, "bgr8")
        except CvBridgeError as e:
            rospy.logerr(e)

        self._image_widget.set_image(cv_image)

    def trigger_configuration(self):
        topic_name, ok = QInputDialog.getItem(
            self._widget, "Select topic name", "Topic name",
            rostopic.find_by_type('sensor_msgs/Image'))
        if ok:
            self._create_subscriber(topic_name)

        available_rosservices = []
        for s in rosservice.get_service_list():
            try:
                if rosservice.get_service_type(
                        s) == "object_recognition_srvs/Recognize":
                    available_rosservices.append(s)
            except:
                pass

        srv_name, ok = QInputDialog.getItem(self._widget,
                                            "Select service name",
                                            "Service name",
                                            available_rosservices)
        if ok:
            self._create_service_client(srv_name)

    def _create_subscriber(self, topic_name):
        if self._sub:
            self._sub.unregister()
        self._sub = rospy.Subscriber(topic_name, Image, self._image_callback)
        rospy.loginfo("Listening to %s -- spinning .." % self._sub.name)
        self._widget.setWindowTitle("Test plugin, listening to (%s)" %
                                    self._sub.name)

    def _create_service_client(self, srv_name):
        if self._srv:
            self._srv.close()
        rospy.loginfo("Creating proxy for service '%s'" % srv_name)
        self._srv = rospy.ServiceProxy(srv_name, Recognize)

    def shutdown_plugin(self):
        pass

    def save_settings(self, plugin_settings, instance_settings):
        if self._sub:
            instance_settings.set_value("topic_name", self._sub.name)

    def restore_settings(self, plugin_settings, instance_settings):
        self._create_subscriber(
            str(instance_settings.value("topic_name", "/usb_cam/image_raw")))
        self._create_service_client(
            str(
                instance_settings.value("service_name",
                                        "/object_recognition/blaat")))
예제 #25
0
class ManualPlugin(Plugin):

    def __init__(self, context):
        """
        ManualPlugin class that performs a manual recognition based on a request
        :param context: QT context, aka parent
        """
        super(ManualPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Manual Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)
        
        # Layout and attach to widget
        layout = QVBoxLayout()  
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget, self.image_roi_callback)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._labels_edit = QLineEdit()
        self._labels_edit.setDisabled(True)
        grid_layout.addWidget(self._labels_edit, 2, 2)

        self._edit_labels_button = QPushButton("Edit labels")
        self._edit_labels_button.clicked.connect(self._get_labels)
        grid_layout.addWidget(self._edit_labels_button, 2, 1)

        self._done_recognizing_button = QPushButton("Done recognizing..")
        self._done_recognizing_button.clicked.connect(self._done_recognizing)
        self._done_recognizing_button.setDisabled(True)
        grid_layout.addWidget(self._done_recognizing_button, 3, 2)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set service to None
        self._srv = None
        self._srv_name = None

        self._response = RecognizeResponse()
        self._recognizing = False

    def _get_labels(self):
        """
        Gets and sets the labels
        """
        text, ok = QInputDialog.getText(self._widget, 'Text Input Dialog',
                                        'Type labels semicolon separated, e.g. banana;apple:',
                                        QLineEdit.Normal, ";".join(self.labels))
        if ok:
            # Sanitize to alphanumeric, exclude spaces
            labels = set([_sanitize(label) for label in str(text).split(";") if _sanitize(label)])
            self._set_labels(labels)

    def _set_labels(self, labels):
        """
        Sets the labels
        :param labels: label string array
        """
        if not labels:
            labels = []

        self.labels = labels
        self._labels_edit.setText("%s" % labels)

    def _done_recognizing(self):
        self._image_widget.clear()
        self._recognizing = False

    def recognize_srv_callback(self, req):
        """
        Method callback for the Recognize.srv
        :param req: The service request
        """
        self._response.recognitions = []
        self._recognizing = True

        try:
            cv_image = self.bridge.imgmsg_to_cv2(req.image, "bgr8")
        except CvBridgeError as e:
            rospy.logerr(e)

        self._image_widget.set_image(cv_image)
        self._done_recognizing_button.setDisabled(False)

        timeout = 60.0  # Maximum of 60 seconds
        future = rospy.Time.now() + rospy.Duration(timeout)
        rospy.loginfo("Waiting for manual recognition, maximum of %d seconds", timeout)
        while not rospy.is_shutdown() and self._recognizing:
            if rospy.Time.now() > future:
                raise rospy.ServiceException("Timeout of %d seconds exceeded .." % timeout)
            rospy.sleep(rospy.Duration(0.1))

        self._done_recognizing_button.setDisabled(True)

        return self._response

    def image_roi_callback(self, roi_image):
        """
        Callback triggered when the user has drawn an ROI on the image
        :param roi_image: The opencv image in the ROI
        """
        if not self.labels:
            warning_dialog("No labels specified!", "Please first specify some labels using the 'Edit labels' button")
            return

        height, width = roi_image.shape[:2]

        option = option_dialog("Label", self.labels)
        if option:
            self._image_widget.add_detection(0, 0, width, height, option)
            self._stage_recognition(self._image_widget.get_roi(), option)

    def _stage_recognition(self, roi, label):
        """
        Stage a manual recognition
        :param roi: ROI
        :param label: The label
        """
        x, y, width, height = roi
        r = Recognition(roi=RegionOfInterest(x_offset=x, y_offset=y, width=width, height=height))
        r.categorical_distribution.probabilities = [CategoryProbability(label=label, probability=1.0)]
        r.categorical_distribution.unknown_probability = 0.0

        self._response.recognitions.append(r)

    def trigger_configuration(self):
        """
        Callback when the configuration button is clicked
        """

        srv_name, ok = QInputDialog.getText(self._widget, "Select service name", "Service name")
        if ok:
            self._create_service_server(srv_name)

    def _create_service_server(self, srv_name):
        """
        Method that creates a service server for a Recognize.srv
        :param srv_name:
        """
        if self._srv:
            self._srv.shutdown()

        if srv_name:
            rospy.loginfo("Creating service '%s'" % srv_name)
            self._srv_name = srv_name
            self._srv = rospy.Service(srv_name, Recognize, self.recognize_srv_callback)

    def shutdown_plugin(self):
        """
        Callback function when shutdown is requested
        """
        pass

    def save_settings(self, plugin_settings, instance_settings):
        """
        Callback function on shutdown to store the local plugin variables
        :param plugin_settings: Plugin settings
        :param instance_settings: Settings of this instance
        """
        instance_settings.set_value("labels", self.labels)
        if self._srv:
            instance_settings.set_value("srv_name", self._srv_name)

    def restore_settings(self, plugin_settings, instance_settings):
        """
        Callback function fired on load of the plugin that allows to restore saved variables
        :param plugin_settings: Plugin settings
        :param instance_settings: Settings of this instance
        """
        labels = None
        try:
            labels = instance_settings.value("labels")
        except:
            pass
        self._set_labels(labels)
        self._create_service_server(str(instance_settings.value("srv_name", "/my_recognition_service")))
예제 #26
0
class LabelPlugin(Plugin):
    def __init__(self, context):
        super(LabelPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Label Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)

        # Layout and attach to widget
        layout = QVBoxLayout()
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget, self.image_roi_callback)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._edit_path_button = QPushButton("Edit path")
        self._edit_path_button.clicked.connect(self._get_output_directory)
        grid_layout.addWidget(self._edit_path_button, 1, 1)

        self._output_path_edit = QLineEdit()
        self._output_path_edit.setDisabled(True)
        grid_layout.addWidget(self._output_path_edit, 1, 2)

        self._labels_edit = QLineEdit()
        self._labels_edit.setDisabled(True)
        grid_layout.addWidget(self._labels_edit, 2, 2)

        self._edit_labels_button = QPushButton("Edit labels")
        self._edit_labels_button.clicked.connect(self._get_labels)
        grid_layout.addWidget(self._edit_labels_button, 2, 1)

        self._save_button = QPushButton("Save another one")
        self._save_button.clicked.connect(self.store_image)
        grid_layout.addWidget(self._save_button, 2, 3)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set subscriber to None
        self._sub = None

        self.labels = []
        self.roi_image = None
        self.label = ""
        self.output_directory = ""

    def image_roi_callback(self, roi_image):
        if not self.labels:
            warning_dialog(
                "No labels specified!",
                "Please first specify some labels using the 'Edit labels' button"
            )
            return

        self.roi_image = roi_image

        option = option_dialog("Label", self.labels)
        if option:
            self.label = option
            self._image_widget.set_text(option)

        self.store_image()

    def store_image(self):
        if not None in [self.roi_image, self.label, self.output_directory]:
            _write_image_to_file(self.output_directory, self.roi_image,
                                 self.label)

    def _get_output_directory(self):
        self._set_output_directory(
            QFileDialog.getExistingDirectory(self._widget,
                                             "Select output directory"))

    def _set_output_directory(self, path):
        if not path:
            path = "/tmp"

        self.output_directory = path
        self._output_path_edit.setText("Saving images to %s" % path)

    def _get_labels(self):
        text, ok = QInputDialog.getText(
            self._widget, 'Text Input Dialog',
            'Type labels semicolon separated, e.g. banana;apple:',
            QLineEdit.Normal, ";".join(self.labels))
        if ok:
            labels = set([
                _sanitize(label) for label in str(text).split(";")
                if _sanitize(label)
            ])  # Sanitize to alphanumeric, exclude spaces
            self._set_labels(labels)

    def _set_labels(self, labels):
        if not labels:
            labels = []

        self.labels = labels
        self._labels_edit.setText("%s" % labels)

    def _image_callback(self, msg):
        try:
            cv_image = self.bridge.imgmsg_to_cv2(msg, "bgr8")
        except CvBridgeError as e:
            rospy.logerr(e)

        self._image_widget.set_image(cv_image)

    def trigger_configuration(self):
        topic_name, ok = QInputDialog.getItem(
            self._widget, "Select topic name", "Topic name",
            rostopic.find_by_type('sensor_msgs/Image'))
        if ok:
            self._create_subscriber(topic_name)

    def _create_subscriber(self, topic_name):
        if self._sub:
            self._sub.unregister()
        self._sub = rospy.Subscriber(topic_name, Image, self._image_callback)
        rospy.loginfo("Listening to %s -- spinning .." % self._sub.name)
        self._widget.setWindowTitle("Label plugin, listening to (%s)" %
                                    self._sub.name)

    def shutdown_plugin(self):
        pass

    def save_settings(self, plugin_settings, instance_settings):
        instance_settings.set_value("output_directory", self.output_directory)
        instance_settings.set_value("labels", self.labels)
        if self._sub:
            instance_settings.set_value("topic_name", self._sub.name)

    def restore_settings(self, plugin_settings, instance_settings):
        path = None
        try:
            path = instance_settings.value("output_directory")
        except:
            pass
        self._set_output_directory(path)

        labels = None
        try:
            labels = instance_settings.value("labels")
        except:
            pass
        self._set_labels(labels)

        self._create_subscriber(
            str(instance_settings.value("topic_name", "/usb_cam/image_raw")))
예제 #27
0
class TestPlugin(Plugin):
    def __init__(self, context):
        """
        TestPlugin class to evaluate the image_recognition_msgs interfaces
        :param context: QT context, aka parent
        """
        super(TestPlugin, self).__init__(context)

        # Widget setup
        self.setObjectName('Test Plugin')

        self._widget = QWidget()
        context.add_widget(self._widget)

        # Layout and attach to widget
        layout = QVBoxLayout()
        self._widget.setLayout(layout)

        self._image_widget = ImageWidget(self._widget,
                                         self.image_roi_callback,
                                         clear_on_click=True)
        layout.addWidget(self._image_widget)

        # Input field
        grid_layout = QGridLayout()
        layout.addLayout(grid_layout)

        self._info = QLineEdit()
        self._info.setDisabled(True)
        self._info.setText(
            "Draw a rectangle on the screen to perform recognition of that ROI"
        )
        layout.addWidget(self._info)

        # Bridge for opencv conversion
        self.bridge = CvBridge()

        # Set subscriber and service to None
        self._sub = None
        self._srv = None

    def recognize_srv_call(self, roi_image):
        """
        Method that calls the Recognize.srv
        :param roi_image: Selected roi_image by the user
        """
        try:
            result = self._srv(
                image=self.bridge.cv2_to_imgmsg(roi_image, "bgr8"))
        except Exception as e:
            warning_dialog("Service Exception", str(e))
            return

        print result

        for r in result.recognitions:
            text_array = []
            best = CategoryProbability(
                label="unknown",
                probability=r.categorical_distribution.unknown_probability)
            for p in r.categorical_distribution.probabilities:
                text_array.append("%s: %.2f" % (p.label, p.probability))
                if p.probability > best.probability:
                    best = p

            self._image_widget.add_detection(r.roi.x_offset, r.roi.y_offset,
                                             r.roi.width, r.roi.height,
                                             best.label)

            if text_array:
                option_dialog(
                    "Classification results (Unknown probability=%.2f)" %
                    r.categorical_distribution.unknown_probability,
                    text_array)  # Show all results in a dropdown

    def get_face_properties_srv_call(self, roi_image):
        """
        Method that calls the GetFaceProperties.srv
        :param roi_image: Selected roi_image by the user
        """
        try:
            result = self._srv(face_image_array=[
                self.bridge.cv2_to_imgmsg(roi_image, "bgr8")
            ])
        except Exception as e:
            warning_dialog("Service Exception", str(e))
            return

        msg = ""
        for properties in result.properties_array:
            msg += "- FaceProperties(gender=%s, age=%s, glasses=%s, mood=%s)" % \
                   ("male" if properties.gender == FaceProperties.MALE else "female", properties.age,
            "false" if properties.glasses == 0 else "true", properties.mood)

        info_dialog("Face Properties array", msg)

    def image_roi_callback(self, roi_image):
        """
        Callback triggered when the user has drawn an ROI on the image
        :param roi_image: The opencv image in the ROI
        """
        if self._srv is None:
            warning_dialog(
                "No service specified!",
                "Please first specify a service via the options button (top-right gear wheel)"
            )
            return

        if self._srv.service_class == Recognize:
            self.recognize_srv_call(roi_image)
        elif self._srv.service_class == GetFaceProperties:
            self.get_face_properties_srv_call(roi_image)
        else:
            warning_dialog("Unknown service class", "Service class is unkown!")

    def _image_callback(self, msg):
        """
        Sensor_msgs/Image callback
        :param msg: The image message
        """
        try:
            cv_image = self.bridge.imgmsg_to_cv2(msg, "bgr8")
        except CvBridgeError as e:
            rospy.logerr(e)
            return

        self._image_widget.set_image(cv_image)

    def trigger_configuration(self):
        """
        Callback when the configuration button is clicked
        """
        topic_name, ok = QInputDialog.getItem(
            self._widget, "Select topic name", "Topic name",
            rostopic.find_by_type('sensor_msgs/Image'))
        if ok:
            self._create_subscriber(topic_name)

        available_rosservices = []
        for s in rosservice.get_service_list():
            try:
                if rosservice.get_service_type(s) in _SUPPORTED_SERVICES:
                    available_rosservices.append(s)
            except:
                pass

        srv_name, ok = QInputDialog.getItem(self._widget,
                                            "Select service name",
                                            "Service name",
                                            available_rosservices)
        if ok:
            self._create_service_client(srv_name)

    def _create_subscriber(self, topic_name):
        """
        Method that creates a subscriber to a sensor_msgs/Image topic
        :param topic_name: The topic_name
        """
        if self._sub:
            self._sub.unregister()
        self._sub = rospy.Subscriber(topic_name, Image, self._image_callback)
        rospy.loginfo("Listening to %s -- spinning .." % self._sub.name)
        self._widget.setWindowTitle("Test plugin, listening to (%s)" %
                                    self._sub.name)

    def _create_service_client(self, srv_name):
        """
        Method that creates a client service proxy to call either the GetFaceProperties.srv or the Recognize.srv
        :param srv_name:
        """
        if self._srv:
            self._srv.close()

        if srv_name in rosservice.get_service_list():
            rospy.loginfo("Creating proxy for service '%s'" % srv_name)
            self._srv = rospy.ServiceProxy(
                srv_name, rosservice.get_service_class_by_name(srv_name))

    def shutdown_plugin(self):
        """
        Callback function when shutdown is requested
        """
        pass

    def save_settings(self, plugin_settings, instance_settings):
        """
        Callback function on shutdown to store the local plugin variables
        :param plugin_settings: Plugin settings
        :param instance_settings: Settings of this instance
        """
        if self._sub:
            instance_settings.set_value("topic_name", self._sub.name)

    def restore_settings(self, plugin_settings, instance_settings):
        """
        Callback function fired on load of the plugin that allows to restore saved variables
        :param plugin_settings: Plugin settings
        :param instance_settings: Settings of this instance
        """
        self._create_subscriber(
            str(instance_settings.value("topic_name", "/usb_cam/image_raw")))
        self._create_service_client(
            str(
                instance_settings.value("service_name",
                                        "/image_recognition/my_service")))
예제 #28
0
class VideoAnnotator(QtGui.QWidget):
    def __init__(self):
        super(VideoAnnotator, self).__init__()

        self.vid = None

        self.pic = None
        self.sld = None
        self.sld2 = None

        self.ranges = None

        # Number of distinct viewable video positions (slider granularity)
        self.num_positions = 50000

        self.initUI()

    def initUI(self):
        vbox = QtGui.QVBoxLayout()

        # Create the widget that displays the video frame
        self.pic = ImageWidget()

        # A horizontal slider to scroll through the video
        self.sld = QtGui.QSlider(QtCore.Qt.Horizontal)
        # self.sld.setFocusPolicy(QtCore.Qt.NoFocus)
        self.sld.setRange(0, self.num_positions)
        self.sld.setValue(100)
        self.sld.valueChanged[int].connect(self.change_slider_value)

        # A special widget that displays the marked ranges and average frame colors
        # (Is also called slider, because it should later take over the role of the conventional slider)
        self.sld2 = SliderWidget()

        # The ranges class manages the marked video ranges and sends them to the widget when changed
        self.ranges = Ranges(update_function=self.sld2.setRanges)
        self.load_or_save_ranges(save=False)

        # A label with a quick introduction
        man_label = QtGui.QLabel()
        man_label.setText(
            "Use the slider to navigate (Mouse + keyboard).\n" +
            "Q = Start preview range, A = Start ad range, Z = Start ignore range\n"
            +
            "D = End current range, Bksp = remove last element.\n Auto-saves on close."
        )
        man_label.setSizePolicy(QtGui.QSizePolicy.Minimum,
                                QtGui.QSizePolicy.Fixed)

        # Put everything together and show it
        vbox.addWidget(self.pic)
        vbox.addWidget(self.sld)
        vbox.addWidget(self.sld2)
        vbox.addWidget(man_label)

        self.setLayout(vbox)
        self.setWindowTitle('Video Annotator')
        self.setAcceptDrops(True)
        self.show()

    def current_position(self, slider_value=None):
        if slider_value is None:
            return self.sld.value() / self.num_positions
        else:
            return slider_value / self.num_positions

    def change_slider_value(self, value):
        if self.vid is not None:
            self.pic.setImage(self.vid.get_frame(self.current_position(value)))

    def load_video(self, filename):
        self.vid = Video(filename)
        self.vid.compute_averages(50)
        #self.vid.compute_averages(1000)

        self.pic.setImage(self.vid.get_frame(0.0))
        self.sld2.setAverages(self.vid.get_averages())
        self.ranges = Ranges(update_function=self.sld2.setRanges)
        self.load_or_save_ranges(save=False)
        self.sld2.setRanges(self.ranges.get_ranges())

    def keyPressEvent(self, e):
        if e.key() == QtCore.Qt.Key_Escape:
            self.close()
        elif e.key() == QtCore.Qt.Key_Backspace:
            self.ranges.remove_last_element()
        elif e.key() == QtCore.Qt.Key_A:
            self.ranges.add_range_start('ad', self.current_position())
        elif e.key() == QtCore.Qt.Key_Q:
            self.ranges.add_range_start('preview', self.current_position())
        elif e.key() == QtCore.Qt.Key_Z:
            self.ranges.add_range_start('ignore', self.current_position())
        elif e.key() == QtCore.Qt.Key_D:
            self.ranges.add_range_end(self.current_position())

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        url = event.mimeData().urls()[0]
        path = str(url.toLocalFile())
        if os.path.isfile(path):
            # Save old ranges
            self.load_or_save_ranges(save=True)
            # Open new video
            self.load_video(path)

    def load_or_save_ranges(self, save=False):
        if self.vid is not None:
            filename = os.path.splitext(
                self.vid.get_filename())[0] + '_annotation.txt'
            if save:
                with open(filename, 'w') as f:
                    json.dump(self.ranges.get_ranges(), f)
            else:
                if os.path.isfile(filename):
                    with open(filename, 'r') as f:
                        range_data = json.load(f)
                        self.ranges.set_ranges(range_data)

    def closeEvent(self, e):
        self.load_or_save_ranges(save=True)