00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 import roslib; roslib.load_manifest('laser_camera_segmentation')
00031
00032 from opencv.highgui import cvLoadImage
00033
00034 import sys
00035 import opencv.cv as cv
00036 import opencv.highgui as hg
00037
00038 from PyQt4 import QtGui, QtCore
00039
00040 import shutil
00041 import os
00042
00043
00044 from dumpObj import dumpObj
00045
00046 from labeling import label_object, scan_dataset, scans_database
00047
00048
00049
00050 import laser_camera_segmentation.scanner as scanner
00051 import laser_camera_segmentation.processor as processor
00052 import laser_camera_segmentation.configuration as configuration
00053 import hrl_lib.util as ut
00054
00055
00056 class labeling_tool(QtGui.QWidget):
00057
00058 draw_widget = None
00059 display_mode = 'image'
00060
00061 display_3d_type = 'height'
00062
00063 def __init__(self, path, parent=None):
00064
00065 self.init_in_progress = True
00066
00067 self.path = path
00068
00069
00070 self.config = configuration.configuration(path)
00071
00072 self.scanner = False
00073 self.processor = False
00074
00075
00076 self.scans_database = scans_database.scans_database()
00077 self.scans_database.load(path,'database.pkl')
00078
00079
00080 self.current_dataset = self.scans_database.get_dataset(0)
00081
00082 QtGui.QWidget.__init__(self, parent)
00083 self.setWindowTitle('labeling tool')
00084
00085
00086 left_layout = QtGui.QVBoxLayout()
00087 self.draw_widget = draw_widget(self.current_dataset.polygons, self.scans_database.get_path() + '/' + self.current_dataset.image_filename, self)
00088
00089 title_layout = QtGui.QHBoxLayout()
00090
00091 take_scan_button = QtGui.QPushButton('Scan')
00092 take_scan_button.setMaximumWidth(50)
00093 title_layout.addWidget(take_scan_button)
00094 self.connect(take_scan_button, QtCore.SIGNAL('clicked()'), self.slot_take_scan )
00095
00096 take_artag_image_button = QtGui.QPushButton('ARTag')
00097 take_artag_image_button.setMaximumWidth(50)
00098 title_layout.addWidget(take_artag_image_button)
00099 self.connect(take_artag_image_button, QtCore.SIGNAL('clicked()'), self.slot_take_artag_image )
00100
00101 button = QtGui.QPushButton('Import Img')
00102 title_layout.addWidget(button)
00103 self.connect(button, QtCore.SIGNAL('clicked()'), self.slot_import_image )
00104
00105 label = QtGui.QLabel("View: ")
00106 title_layout.addWidget(label)
00107 self.display_3d_button = QtGui.QPushButton('3D')
00108 self.display_3d_button.setMaximumWidth(40)
00109 title_layout.addWidget(self.display_3d_button)
00110 self.connect(self.display_3d_button, QtCore.SIGNAL('clicked()'), self.slot_display_3d )
00111
00112 combobox = QtGui.QComboBox()
00113 combobox.addItem("Height", QtCore.QVariant("height"))
00114 combobox.addItem("Intensities", QtCore.QVariant("intensities"))
00115
00116 combobox.addItem("Labels", QtCore.QVariant("labels"))
00117 combobox.addItem("Classifier range", QtCore.QVariant("range"))
00118 combobox.addItem("Classifier color", QtCore.QVariant("color"))
00119 combobox.addItem("Classifier all", QtCore.QVariant("all"))
00120 combobox.addItem("Classifier all+post", QtCore.QVariant("all_post"))
00121 combobox.addItem("Baseline algo", QtCore.QVariant("baseline"))
00122 combobox.addItem("h", QtCore.QVariant("h"))
00123 combobox.addItem("s", QtCore.QVariant("s"))
00124 combobox.addItem("v", QtCore.QVariant("v"))
00125 self.connect(combobox, QtCore.SIGNAL('currentIndexChanged(int)'), self.slot_update_display_3d_type)
00126 title_layout.addWidget(combobox)
00127 self.display_3d_type_combobox = combobox;
00128
00129
00130 self.display_3d_spheres_button = QtGui.QPushButton('3D_Spheres')
00131 title_layout.addWidget(self.display_3d_spheres_button)
00132 self.connect(self.display_3d_spheres_button, QtCore.SIGNAL('clicked()'), self.slot_display_3d_spheres )
00133 self.display_intensity_button = QtGui.QPushButton('Intensity')
00134 self.display_intensity_button.setMaximumWidth(50)
00135 title_layout.addWidget(self.display_intensity_button)
00136 self.connect(self.display_intensity_button, QtCore.SIGNAL('clicked()'), self.slot_display_intensity )
00137 self.display_features_button = QtGui.QPushButton('Features')
00138 title_layout.addWidget(self.display_features_button)
00139 self.display_features_button.setMaximumWidth(50)
00140 self.connect(self.display_features_button, QtCore.SIGNAL('clicked()'), self.slot_display_features )
00141 self.display_labels_button = QtGui.QPushButton('Labels')
00142 title_layout.addWidget(self.display_labels_button)
00143 self.display_labels_button.setMaximumWidth(50)
00144 self.connect(self.display_labels_button, QtCore.SIGNAL('clicked()'), self.slot_display_labels )
00145 self.display_stats_button = QtGui.QPushButton('Stats')
00146 title_layout.addWidget(self.display_stats_button)
00147 self.display_stats_button.setMaximumWidth(50)
00148 self.connect(self.display_stats_button, QtCore.SIGNAL('clicked()'), self.slot_display_stats )
00149 self.display_global_stats_button = QtGui.QPushButton('Global Stats')
00150 title_layout.addWidget(self.display_global_stats_button)
00151 self.display_global_stats_button.setMaximumWidth(50)
00152 self.connect(self.display_global_stats_button, QtCore.SIGNAL('clicked()'), self.slot_display_global_stats )
00153
00154 self.line_edits = []
00155
00156 self.add_line_edit('Title:',title_layout,'title')
00157
00158
00159 first_dataset_button = QtGui.QPushButton('<<')
00160 first_dataset_button.setMaximumWidth(30)
00161 title_layout.addWidget(first_dataset_button)
00162 self.connect(first_dataset_button, QtCore.SIGNAL('clicked()'), self.slot_first_dataset )
00163 prev_dataset_button = QtGui.QPushButton('<')
00164 prev_dataset_button.setMaximumWidth(30)
00165 title_layout.addWidget(prev_dataset_button)
00166 self.connect(prev_dataset_button, QtCore.SIGNAL('clicked()'), self.slot_prev_dataset )
00167 next_dataset_button = QtGui.QPushButton('>')
00168 next_dataset_button.setMaximumWidth(30)
00169 title_layout.addWidget(next_dataset_button)
00170 self.connect(next_dataset_button, QtCore.SIGNAL('clicked()'), self.slot_next_dataset )
00171 last_dataset_button = QtGui.QPushButton('>>')
00172 last_dataset_button.setMaximumWidth(30)
00173 title_layout.addWidget(last_dataset_button)
00174 self.connect(last_dataset_button, QtCore.SIGNAL('clicked()'), self.slot_last_dataset )
00175
00176 save_button = QtGui.QPushButton('Save')
00177 title_layout.addWidget(save_button)
00178 save_button.setMaximumWidth(50)
00179 self.connect(save_button, QtCore.SIGNAL('clicked()'), self.slot_save )
00180
00181 delete_button = QtGui.QPushButton('Delete')
00182 title_layout.addWidget(delete_button)
00183 delete_button.setMaximumWidth(50)
00184 self.connect(delete_button, QtCore.SIGNAL('clicked()'), self.slot_delete )
00185
00186
00187 self.connect(self.draw_widget, QtCore.SIGNAL('sigPolyChanged'), self.slot_update_polygons)
00188 self.connect(self.draw_widget, QtCore.SIGNAL('sigPolyLabelChanged'), self.slot_update_polygon_label)
00189 self.connect(self.draw_widget, QtCore.SIGNAL('sigDefineGroundPlane'), self.slot_define_ground_plane)
00190
00191 left_layout.addLayout(title_layout)
00192
00193
00194 row2_layout = QtGui.QHBoxLayout()
00195 left_layout.addLayout(row2_layout)
00196
00197
00198 label = QtGui.QLabel("Id:")
00199 row2_layout.addWidget(label)
00200 self.id_label = QtGui.QLabel("")
00201 row2_layout.addWidget(self.id_label)
00202
00203 self.add_line_edit('Surface: ID:',row2_layout,'surface_id')
00204 self.add_line_edit('Height',row2_layout,'surface_height')
00205
00206
00207 label = QtGui.QLabel("Type: ")
00208 row2_layout.addWidget(label)
00209 combobox = QtGui.QComboBox()
00210 combobox.addItem("Table Office", QtCore.QVariant("table_office"))
00211 combobox.addItem("Table Dorm", QtCore.QVariant("table_dorm"))
00212 combobox.addItem("Table House", QtCore.QVariant("table_house"))
00213 combobox.addItem("Shelf Office", QtCore.QVariant("shelf_office"))
00214 combobox.addItem("Shelf Dorm", QtCore.QVariant("shelf_dorm"))
00215 combobox.addItem("Shelf House", QtCore.QVariant("shelf_house"))
00216 self.connect(combobox, QtCore.SIGNAL('currentIndexChanged(int)'), self.slot_update_surface_type)
00217 row2_layout.addWidget(combobox)
00218 self.surface_type_combobox = combobox;
00219
00220 self.add_line_edit('Camera: Height:',row2_layout,'camera_height')
00221 self.add_line_edit('Camera: Angle:',row2_layout,'camera_angle')
00222
00223
00224
00225 row3_layout = QtGui.QHBoxLayout()
00226 left_layout.addLayout(row3_layout)
00227
00228
00229 button = QtGui.QPushButton("&gen'n'save features")
00230 row3_layout.addWidget(button)
00231 self.connect(button, QtCore.SIGNAL('clicked()'), self.slot_generate_save_features )
00232
00233 checkbox = QtGui.QCheckBox('&Training Set')
00234 row3_layout.addWidget(checkbox)
00235 self.connect(checkbox, QtCore.SIGNAL('stateChanged(int)'), self.slot_update_training_set)
00236 self.checkbox_training_set = checkbox
00237
00238 checkbox = QtGui.QCheckBox('Te&st Set')
00239 row3_layout.addWidget(checkbox)
00240 self.connect(checkbox, QtCore.SIGNAL('stateChanged(int)'), self.slot_update_test_set)
00241 self.checkbox_test_set = checkbox
00242
00243 checkbox = QtGui.QCheckBox('Labels, Groundp. checked')
00244 row3_layout.addWidget(checkbox)
00245 self.connect(checkbox, QtCore.SIGNAL('stateChanged(int)'), self.slot_update_is_labeled)
00246 self.checkbox_is_labeled = checkbox
00247
00248 button = QtGui.QPushButton("Train'n'save Classifiers (training set)")
00249 row3_layout.addWidget(button)
00250 self.connect(button, QtCore.SIGNAL('clicked()'), self.slot_train_and_save_Classifiers )
00251
00252 button = QtGui.QPushButton('Test Classifiers (on current)')
00253 row3_layout.addWidget(button)
00254 self.connect(button, QtCore.SIGNAL('clicked()'), self.slot_test_Classifiers )
00255
00256 button = QtGui.QPushButton('Test Classifiers (on testset)')
00257 row3_layout.addWidget(button)
00258 self.connect(button, QtCore.SIGNAL('clicked()'), self.slot_test_Classifiers_on_testset )
00259
00260 button = QtGui.QPushButton('Load Classifiers')
00261 row3_layout.addWidget(button)
00262 self.connect(button, QtCore.SIGNAL('clicked()'), self.slot_load_Classifiers )
00263
00264
00265
00266
00267
00268
00269
00270 left_layout.addWidget(self.draw_widget)
00271
00272
00273 self.right_layout = QtGui.QVBoxLayout()
00274 self.right_layout.setAlignment(QtCore.Qt.AlignTop)
00275
00276 self.outer_layout = QtGui.QHBoxLayout()
00277 self.outer_layout.addLayout(left_layout)
00278 self.outer_layout.addLayout(self.right_layout)
00279
00280
00281
00282 self.polygon_comboboxes = []
00283 self.add_polygon_combobox()
00284
00285 self.slot_update_polygons(self.current_dataset.polygons,0)
00286
00287
00288 self.setLayout(self.outer_layout)
00289
00290
00291 self.resize(900, 700)
00292 self.load_values_from_dataset()
00293
00294 self.init_in_progress = False
00295
00296
00297 self.slot_last_dataset()
00298
00299
00300 def slot_update_training_set(self, checkState):
00301 if checkState:
00302 self.current_dataset.is_training_set = True
00303 else:
00304 self.current_dataset.is_training_set = False
00305
00306 def slot_update_test_set(self, checkState):
00307 if checkState:
00308 self.current_dataset.is_test_set = True
00309 else:
00310 self.current_dataset.is_test_set = False
00311
00312 def slot_update_is_labeled(self, checkState):
00313 if checkState:
00314 self.current_dataset.is_labeled = True
00315 else:
00316 self.current_dataset.is_labeled = False
00317
00318 def closeEvent(self, x):
00319 print "Exit: saving database..."
00320 self.slot_save()
00321
00322 def slot_import_image(self):
00323 fileName = QtGui.QFileDialog.getOpenFileName(self,"Open Image", self.path, "Image Files (*.png)")
00324 print "Import image into new dataset:" + fileName
00325
00326 name = ut.formatted_time()
00327
00328 new_dataset = scan_dataset.scan_dataset()
00329 new_dataset.id = name
00330 new_dataset.image_filename = 'data/'+name+'_image.png'
00331 shutil.copy(fileName,self.path+'/'+new_dataset.image_filename)
00332
00333 self.scans_database.add_dataset(new_dataset)
00334
00335
00336 while True == self.slot_next_dataset():
00337 pass
00338
00339
00340 def add_line_edit(self,label, layout, variable):
00341 label = QtGui.QLabel(label)
00342 line_edit = QtGui.QLineEdit()
00343 line_edit.setMinimumWidth(80)
00344 self.line_edits.append((line_edit,variable))
00345 layout.addWidget(label)
00346 layout.addWidget(line_edit)
00347 self.connect(line_edit, QtCore.SIGNAL('textEdited (const QString&)'), self.slot_line_edit_changed )
00348 return line_edit
00349
00350 def slot_line_edit_changed(self,text):
00351 if True == self.init_in_progress:
00352 return
00353
00354 for (line_edit, variable) in self.line_edits:
00355 self.current_dataset.dict[variable] = str(line_edit.text())
00356
00357 def slot_next_dataset(self):
00358 dataset = self.scans_database.get_next_dataset()
00359 if False != dataset:
00360 self.current_dataset = dataset
00361 self.load_values_from_dataset()
00362 return True
00363 return False
00364
00365 def slot_prev_dataset(self):
00366 dataset = self.scans_database.get_prev_dataset()
00367 if False != dataset:
00368 self.current_dataset = dataset
00369 self.load_values_from_dataset()
00370 return True
00371 return False
00372
00373 def slot_first_dataset(self):
00374 dataset = self.scans_database.get_first_dataset()
00375 if False != dataset:
00376 self.current_dataset = dataset
00377 self.load_values_from_dataset()
00378 return True
00379 return False
00380
00381 def slot_last_dataset(self):
00382 dataset = self.scans_database.get_last_dataset()
00383 if False != dataset:
00384 self.current_dataset = dataset
00385 self.load_values_from_dataset()
00386 return True
00387 return False
00388
00389
00390 def load_values_from_dataset(self):
00391 self.init_in_progress = True
00392
00393 self.id_label.setText(self.current_dataset.id)
00394
00395 for (line_edit, variable) in self.line_edits:
00396 line_edit.setText(self.current_dataset.dict[variable])
00397
00398 for index, box in enumerate(self.polygon_comboboxes):
00399 if index < len(self.current_dataset.polygons):
00400 print str(index) + " load label:" + self.current_dataset.polygons[index].get_label()
00401 boxindex = box.findData(QtCore.QVariant(self.current_dataset.polygons[index].get_label()))
00402 box.setCurrentIndex(boxindex)
00403 else:
00404 box.setCurrentIndex(0)
00405
00406
00407 box = self.surface_type_combobox
00408 boxindex = box.findData(QtCore.QVariant(self.current_dataset.surface_type))
00409 box.setCurrentIndex(boxindex)
00410
00411 print self.current_dataset.is_training_set
00412 if self.current_dataset.is_training_set:
00413 self.checkbox_training_set.setCheckState(QtCore.Qt.Checked)
00414 else:
00415 self.checkbox_training_set.setCheckState(QtCore.Qt.Unchecked)
00416
00417 if self.current_dataset.is_test_set:
00418 self.checkbox_test_set.setCheckState(QtCore.Qt.Checked)
00419 else:
00420 self.checkbox_test_set.setCheckState(QtCore.Qt.Unchecked)
00421
00422 if self.current_dataset.is_labeled:
00423 self.checkbox_is_labeled.setCheckState(QtCore.Qt.Checked)
00424 else:
00425 self.checkbox_is_labeled.setCheckState(QtCore.Qt.Unchecked)
00426
00427
00428 print self.current_dataset.scan_filename
00429 if '' == self.current_dataset.scan_filename:
00430 self.display_3d_button.setEnabled(False)
00431 self.display_3d_spheres_button.setEnabled(False)
00432 self.display_intensity_button.setEnabled(False)
00433 else:
00434 self.display_3d_button.setEnabled(True)
00435 self.display_3d_spheres_button.setEnabled(True)
00436 self.display_intensity_button.setEnabled(True)
00437
00438 self.display_mode = 'image'
00439 self.draw_widget.set_polygons(self.current_dataset.polygons)
00440 self.draw_widget.set_image(self.scans_database.get_path() + '/' + self.current_dataset.image_filename)
00441
00442 self.init_in_progress = False
00443
00444 def slot_take_artag_image(self):
00445 if False == self.scanner:
00446 self.scanner = scanner.scanner(self.config)
00447 if False == self.processor:
00448 self.processor = processor.processor(self.config)
00449
00450 img = self.scanner.take_artag_image()
00451 self.current_dataset.image_artag_filename = self.scanner.save_artag_image(self.current_dataset.id)
00452
00453 self.slot_save()
00454
00455 if self.processor.read_artag(img).any():
00456 print "SUCCESS in reading ARTag"
00457 else:
00458 print "FAILURE in reading ARTag - try again!"
00459
00460
00461
00462 def slot_take_scan(self):
00463
00464
00465 self.slot_save()
00466
00467 if False == self.scanner:
00468 self.scanner = scanner.scanner(self.config)
00469 if False == self.processor:
00470 self.processor = processor.processor(self.config)
00471
00472 name = ut.formatted_time()
00473 self.scanner.capture_and_save(name)
00474
00475
00476
00477
00478
00479 print 'scan ' + name + ' taken'
00480
00481 self.scans_database.load(self.path,'database.pkl')
00482
00483
00484 while True == self.slot_next_dataset():
00485 pass
00486
00487 def slot_display_intensity(self):
00488 if self.display_mode != 'intensities':
00489 if False == self.processor:
00490 self.processor = processor.processor(self.config)
00491
00492
00493 self.current_dataset.ground_plane_normal = ''
00494 self.current_dataset.ground_plane_three_points = ''
00495 self.slot_save()
00496
00497
00498 self.processor.load_data(self.current_dataset.id)
00499 self.processor.process_intensities()
00500 filename = self.processor.save_intensity_image(self.current_dataset.id)
00501
00502
00503
00504 self.display_mode = 'intensities'
00505 self.draw_widget.set_image(filename)
00506 else:
00507
00508
00509 self.display_mode = 'image'
00510 self.draw_widget.set_image(self.scans_database.get_path() + '/' + self.current_dataset.image_filename)
00511
00512 def slot_display_features(self):
00513 if self.display_mode != 'features':
00514 if False == self.processor:
00515 self.processor = processor.processor(self.config)
00516
00517 self.processor.load_data(self.current_dataset.id)
00518 self.processor.process_intensities()
00519 filename = self.processor.save_intensity_image(self.current_dataset.id)
00520 self.display_mode = 'features'
00521 self.draw_widget.set_image(filename)
00522
00523 else:
00524
00525 self.display_mode = 'image'
00526 self.draw_widget.set_image(self.scans_database.get_path() + '/' + self.current_dataset.image_filename)
00527
00528
00529 def slot_display_labels(self):
00530 if self.display_mode != 'labels':
00531 if False == self.processor:
00532 self.processor = processor.processor(self.config)
00533
00534 self.processor.load_data(self.current_dataset.id)
00535 self.processor.process_labels(self.display_3d_type)
00536 filename = self.processor.save_labels_image(self.display_3d_type)
00537
00538 self.draw_widget.set_image(filename)
00539 self.display_mode = 'labels'
00540 else:
00541
00542 self.draw_widget.set_image(self.scans_database.get_path() + '/' + self.current_dataset.image_filename)
00543 self.display_mode = 'image'
00544
00545 def slot_display_stats(self):
00546 if False == self.processor:
00547 self.processor = processor.processor(self.config)
00548
00549 self.processor.load_data(self.current_dataset.id)
00550 self.processor.display_stats()
00551
00552 def slot_display_global_stats(self):
00553 if False == self.processor:
00554 self.processor = processor.processor(self.config)
00555
00556 self.processor.load_data(self.current_dataset.id)
00557 self.processor.display_stats(True)
00558
00559
00560 def slot_display_3d_spheres(self):
00561 self.slot_display_3d(True)
00562
00563 def slot_display_3d(self, spheres = False):
00564
00565 if False == self.processor:
00566 self.processor = processor.processor(self.config)
00567
00568
00569 self.slot_save()
00570
00571 self.processor.load_data(self.current_dataset.id)
00572
00573 self.processor.process_raw_data()
00574
00575 self.processor.display_3d(self.display_3d_type, spheres)
00576
00577 def slot_train_and_save_Classifiers(self):
00578
00579 if False == self.processor:
00580 self.processor = processor.processor(self.config)
00581
00582
00583 self.slot_save()
00584
00585 self.processor.load_data(self.current_dataset.id)
00586 self.processor.train_and_save_Classifiers()
00587
00588 def slot_generate_save_features(self):
00589
00590 if False == self.processor:
00591 self.processor = processor.processor(self.config)
00592
00593
00594 self.slot_save()
00595
00596 self.processor.load_data(self.current_dataset.id)
00597 self.processor.generate_save_features()
00598
00599
00600 def slot_test_Classifiers(self):
00601 if False == self.processor:
00602 self.processor = processor.processor(self.config)
00603 self.slot_save()
00604 self.processor.load_data(self.current_dataset.id)
00605 self.processor.train_and_save_Classifiers()
00606 self.processor.test_Classifiers()
00607
00608 def slot_test_Classifiers_on_testset(self):
00609 if False == self.processor:
00610 self.processor = processor.processor(self.config)
00611 self.slot_save()
00612 self.processor.load_data(self.current_dataset.id)
00613 self.processor.train_and_save_Classifiers()
00614 self.processor.test_classifiers_on_testset()
00615
00616 def slot_load_Classifiers(self):
00617 if False == self.processor:
00618 self.processor = processor.processor(self.config)
00619 self.processor.load_Classifiers()
00620
00621 def slot_save_Classifier(self):
00622 if False == self.processor:
00623 print 'ERROR: no processor object exists -> no Classifier to save!'
00624 return
00625 self.processor.save_Classifier()
00626
00627 def add_polygon_combobox(self):
00628 combobox = QtGui.QComboBox()
00629 combobox.addItem("Object", QtCore.QVariant("object"))
00630 combobox.addItem("Surface", QtCore.QVariant("surface"))
00631 combobox.addItem("Region of Interest (ROI)", QtCore.QVariant("roi"))
00632 combobox.addItem("Background", QtCore.QVariant("background"))
00633 combobox.addItem("Visible Surface-Edge", QtCore.QVariant("edge"))
00634 combobox.addItem("Wall-Surface-Edge", QtCore.QVariant("edge_up"))
00635 combobox.addItem("Downward-Surface-Edge", QtCore.QVariant("edge_down"))
00636 combobox.setCurrentIndex(0)
00637
00638 self.connect(combobox, QtCore.SIGNAL('currentIndexChanged(int)'), self.slot_update_polygon_labels)
00639 self.polygon_comboboxes.append(combobox)
00640 self.right_layout.addWidget(combobox, QtCore.Qt.AlignTop)
00641 self.slot_update_polygon_labels()
00642
00643
00644 def slot_delete(self):
00645
00646 if os.path.isfile(self.current_dataset.scan_filename):
00647 os.remove(self.path + '/' + self.current_dataset.scan_filename);
00648 if os.path.isfile(self.current_dataset.image_filename):
00649 os.remove(self.path + '/' + self.current_dataset.image_filename);
00650 if os.path.isfile(self.current_dataset.image_artag_filename):
00651 os.remove(self.path + '/' + self.current_dataset.image_artag_filename);
00652
00653 self.current_dataset = self.scans_database.delete_current_dataset()
00654 self.load_values_from_dataset()
00655 self.slot_save()
00656
00657 def slot_save(self):
00658 dumpObj(self.current_dataset)
00659
00660
00661
00662 self.scans_database.save()
00663
00664 def slot_update_surface_type(self):
00665 if True == self.init_in_progress:
00666 return
00667 box = self.surface_type_combobox
00668 self.current_dataset.surface_type = str(box.itemData(box.currentIndex()).toString())
00669
00670 def slot_update_display_3d_type(self):
00671 if True == self.init_in_progress:
00672 return
00673 box = self.display_3d_type_combobox
00674 self.display_3d_type = str(box.itemData(box.currentIndex()).toString())
00675
00676 def slot_update_polygon_label(self, index, label):
00677 if True == self.init_in_progress:
00678 return
00679
00680 box = self.polygon_comboboxes[index]
00681 boxindex = box.findData(QtCore.QVariant(label))
00682 box.setCurrentIndex(boxindex)
00683
00684 self.draw_widget.update()
00685
00686 def slot_update_polygon_labels(self):
00687 if True == self.init_in_progress:
00688 return
00689
00690 for index, box in enumerate(self.polygon_comboboxes):
00691 if index < len(self.current_dataset.polygons):
00692 self.current_dataset.polygons[index].set_label(str(box.itemData(box.currentIndex()).toString()))
00693 print str(index) + " xx " + str(box.itemData(box.currentIndex()).toString())
00694
00695 self.draw_widget.update()
00696
00697 def slot_update_polygons(self, polygons, current_index):
00698
00699 while len(self.polygon_comboboxes) < len(polygons):
00700 self.add_polygon_combobox()
00701
00702
00703 for index, box in enumerate(self.polygon_comboboxes):
00704 if index < len(polygons):
00705 self.polygon_comboboxes[index].show()
00706 else:
00707 self.polygon_comboboxes[index].hide()
00708 self.update()
00709
00710 def paintEvent(self, event):
00711 painter = QtGui.QPainter()
00712 painter.begin(self)
00713
00714 x = self.polygon_comboboxes[self.draw_widget.get_current_polygon_index()].x()
00715 y = self.polygon_comboboxes[self.draw_widget.get_current_polygon_index()].y()
00716 color = QtGui.QColor(255,0,0)
00717 painter.setPen(color)
00718 painter.setBrush(color)
00719 painter.drawEllipse(QtCore.QRectF(x-8,y+8,6,6))
00720
00721 painter.end()
00722
00723 def get_display_mode(self):
00724 return self.display_mode
00725
00726 def slot_define_ground_plane(self, ground_plane_points):
00727
00728 (self.current_dataset.ground_plane_normal, self.current_dataset.ground_plane_three_points) = self.processor.get_3d_plane_normal(ground_plane_points)
00729 self.slot_display_intensity()
00730
00731 class draw_widget(QtGui.QLabel):
00732
00733
00734 ground_plane_points = []
00735
00736 def __init__(self,polygons, image_filename, parent=None):
00737 QtGui.QWidget.__init__(self, parent)
00738
00739 self.scaleFactor = False
00740
00741 self.setBackgroundRole(QtGui.QPalette.Base)
00742
00743 self.setSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
00744 self.setScaledContents(True)
00745
00746
00747 self.set_polygons(polygons)
00748 self.set_image(image_filename)
00749
00750 self.setScaleFactor(0.8)
00751
00752 def setScaleFactor(self, f):
00753 self.scaleFactor = f
00754 self.updateImageSize()
00755
00756 def updateImageSize(self):
00757 if self.parent().get_display_mode() == 'intensities' or self.parent().get_display_mode() == 'features':
00758 self.scaleFactor = 1
00759 else:
00760 self.scaleFactor = 0.8
00761 self.parent().resize(900, 700)
00762
00763 self.setMinimumHeight(self.image.height() * self.scaleFactor)
00764 self.setMinimumWidth(self.image.width() * self.scaleFactor)
00765 self.setMaximumHeight(self.image.height() * self.scaleFactor)
00766 self.setMaximumWidth(self.image.width() * self.scaleFactor)
00767
00768 pixmap = QtGui.QPixmap.fromImage(self.image)
00769 self.resize(self.scaleFactor * pixmap.size());
00770 self.setPixmap(pixmap);
00771
00772
00773 def set_polygons(self, polygons):
00774 self.polygons = polygons
00775 self.current_polygon_index = 0
00776 self.update()
00777 self.emit(QtCore.SIGNAL("sigPolyChanged"), self.polygons, self.current_polygon_index)
00778
00779 def set_image(self, filename):
00780 print filename
00781 if os.path.isfile(filename):
00782 self.image = QtGui.QImage(filename)
00783 else:
00784 self.image = QtGui.QImage('noimage.png')
00785
00786 self.updateImageSize()
00787 self.update()
00788
00789 def paintEvent(self, event):
00790
00791 QtGui.QLabel.paintEvent(self,event)
00792 painter = QtGui.QPainter()
00793 painter.begin(self)
00794 if self.parent().get_display_mode() == 'image' or self.parent().get_display_mode() == 'labels':
00795 color = QtGui.QColor(0,0,255)
00796 color_surface = QtGui.QColor(0,255,0)
00797 color_roi = QtGui.QColor(255,255,255)
00798 color_edge = QtGui.QColor(255,255,0)
00799 color_edge_up = QtGui.QColor(255,255,255)
00800 color_edge_down = QtGui.QColor(255,150,255)
00801 color_background = QtGui.QColor(255,0,255)
00802 color_current = QtGui.QColor(255,0,0)
00803
00804 for index, polygon in enumerate(self.polygons):
00805
00806 last_point = (-1,-1)
00807 first = True;
00808 if self.current_polygon_index != index or self.parent().get_display_mode() != 'image':
00809 if polygon.get_label() == 'surface':
00810 painter.setPen(color_surface)
00811 elif polygon.get_label() == 'roi':
00812 painter.setPen(color_roi)
00813 elif polygon.get_label() == 'edge':
00814 painter.setPen(color_edge)
00815 elif polygon.get_label() == 'edge_up':
00816 painter.setPen(color_edge_up)
00817 elif polygon.get_label() == 'edge_down':
00818 painter.setPen(color_edge_down)
00819 elif polygon.get_label() == 'background':
00820 painter.setPen(color_background)
00821 else:
00822 painter.setPen(color)
00823 else:
00824 painter.setPen(color_current)
00825
00826 for point in polygon.get_points():
00827 if False == first:
00828 painter.drawLine(QtCore.QPointF(point[0],point[1]) * self.scaleFactor, QtCore.QPointF(last_point[0],last_point[1]) * self.scaleFactor)
00829 last_point = point
00830 first = False
00831
00832
00833 if (self.parent().get_display_mode() != 'image' or self.current_polygon_index != index ) and polygon.get_type() == 'polygon' and len(polygon.get_points()) :
00834 painter.drawLine(QtCore.QPointF(last_point[0],last_point[1]) * self.scaleFactor, QtCore.QPointF(polygon.get_points()[0][0],polygon.get_points()[0][1]) * self.scaleFactor)
00835 else:
00836 for point in polygon.get_points():
00837 painter.drawEllipse(QtCore.QRectF(point[0] * self.scaleFactor-3,point[1] * self.scaleFactor-3,6,6))
00838
00839 elif self.parent().get_display_mode() == 'intensities':
00840 color = QtGui.QColor(255,0,255)
00841 painter.setPen(color)
00842 for point in self.ground_plane_points:
00843 painter.drawEllipse(QtCore.QRectF(point[0] * self.scaleFactor-3,point[1] * self.scaleFactor-3,6,6))
00844 painter.end()
00845
00846
00847 def mousePressEvent(self,event):
00848
00849 if self.hasFocus():
00850 if self.parent().get_display_mode() == 'image':
00851 if event.button() == QtCore.Qt.LeftButton:
00852
00853 point = (event.x() / self.scaleFactor, event.y() / self.scaleFactor)
00854 self.polygons[self.current_polygon_index].add_point(point)
00855 self.update()
00856 self.emit(QtCore.SIGNAL("sigPolyChanged"), self.polygons, self.current_polygon_index)
00857 if event.button() == QtCore.Qt.RightButton:
00858 if False == self.polygons[self.current_polygon_index].is_empty():
00859 self.polygons[self.current_polygon_index].delete_last_point()
00860 self.update()
00861 self.emit(QtCore.SIGNAL("sigPolyChanged"), self.polygons, self.current_polygon_index)
00862 elif self.parent().get_display_mode() == 'intensities':
00863
00864 point = (event.x() / self.scaleFactor, event.y() / self.scaleFactor)
00865 print 'point:', point
00866 if True == self.parent().processor.check_3d_plane_point(point):
00867 self.ground_plane_points.append(point)
00868 if len(self.ground_plane_points) < 3:
00869 self.update()
00870 else:
00871 self.emit(QtCore.SIGNAL("sigDefineGroundPlane"), self.ground_plane_points)
00872 self.ground_plane_points = []
00873
00874
00875 elif self.parent().get_display_mode() == 'features':
00876 point = (event.x() / self.scaleFactor, event.y() / self.scaleFactor)
00877 if True == self.parent().processor.check_3d_plane_point(point):
00878 print 'point:', point
00879 point3d = self.parent().processor.get_3d_point(point)
00880 print 'point3d',point3d
00881
00882 index = self.parent().processor.get_3d_point_index_in_unrotated(point3d)
00883 self.parent().processor.load_data(self.parent().current_dataset.id)
00884 self.parent().processor.process_raw_data()
00885 self.parent().processor.features.prepare([index])
00886 self.parent().processor.feature_type = 'gaussian_histograms'
00887 fv = self.parent().processor.features.get_featurevector(index,0)
00888 print 'fv',fv
00889 self.parent().processor.display_featurevector(fv)
00890
00891
00892 self.parent().processor.load_data(self.parent().current_dataset.id)
00893 self.parent().processor.process_intensities()
00894
00895
00896
00897 else:
00898 self.setFocus()
00899
00900 def mouseDoubleClickEvent(self,event):
00901 if self.parent().get_display_mode() == 'image':
00902 if event.button() == QtCore.Qt.LeftButton:
00903 self.start_new_polygon()
00904 self.update()
00905 self.emit(QtCore.SIGNAL("sigPolyChanged"), self.polygons, self.current_polygon_index)
00906
00907 def start_new_polygon(self):
00908 if False == self.polygons[self.current_polygon_index].is_empty():
00909
00910 self.polygons.append(label_object.label_object())
00911 self.current_polygon_index = len(self.polygons) - 1
00912 print "new poly index: ", self.current_polygon_index
00913
00914 def delete_empty_polygon(self):
00915 if True == self.polygons[self.current_polygon_index].is_empty():
00916
00917 if 1 != len(self.polygons):
00918 del self.polygons[self.current_polygon_index]
00919 if 0 != self.current_polygon_index:
00920 self.current_polygon_index -= 1
00921 print "new poly index: ", self.current_polygon_index
00922 return True
00923 return False
00924
00925 def keyPressEvent(self, event):
00926 key = event.key()
00927 if key == QtCore.Qt.Key_Right:
00928 print 'right'
00929 if self.current_polygon_index < len(self.polygons) - 1:
00930 self.delete_empty_polygon()
00931 self.current_polygon_index += 1
00932 print "czurrent poly index: ", self.current_polygon_index
00933 else:
00934 self.start_new_polygon()
00935 self.parent().slot_update_polygon_labels()
00936 self.update()
00937 self.emit(QtCore.SIGNAL("sigPolyChanged"), self.polygons, self.current_polygon_index)
00938 elif key == QtCore.Qt.Key_Left:
00939 print 'left'
00940 if self.current_polygon_index > 0:
00941 if False == self.delete_empty_polygon():
00942 self.current_polygon_index -= 1
00943 print "current poly index: ", self.current_polygon_index
00944 self.update()
00945 self.emit(QtCore.SIGNAL("sigPolyChanged"), self.polygons, self.current_polygon_index)
00946 elif key == QtCore.Qt.Key_O:
00947 print 'o'
00948 self.emit(QtCore.SIGNAL("sigPolyLabelChanged"), self.current_polygon_index, 'object')
00949 elif key == QtCore.Qt.Key_S:
00950 print 's'
00951 self.emit(QtCore.SIGNAL("sigPolyLabelChanged"), self.current_polygon_index, 'surface')
00952 elif key == QtCore.Qt.Key_R:
00953 print 'r'
00954 self.emit(QtCore.SIGNAL("sigPolyLabelChanged"), self.current_polygon_index, 'roi')
00955 elif key == QtCore.Qt.Key_B:
00956 print 'b'
00957 self.emit(QtCore.SIGNAL("sigPolyLabelChanged"), self.current_polygon_index, 'background')
00958 elif key == QtCore.Qt.Key_E:
00959 print 'e'
00960 self.emit(QtCore.SIGNAL("sigPolyLabelChanged"), self.current_polygon_index, 'edge')
00961 elif key == QtCore.Qt.Key_U:
00962 print 'u'
00963 self.emit(QtCore.SIGNAL("sigPolyLabelChanged"), self.current_polygon_index, 'edge_up')
00964 elif key == QtCore.Qt.Key_D:
00965 print 'd'
00966 self.emit(QtCore.SIGNAL("sigPolyLabelChanged"), self.current_polygon_index, 'edge_down')
00967 elif key == QtCore.Qt.Key_Plus:
00968 print '+'
00969 self.setScaleFactor(self.scaleFactor * 1.25)
00970 self.update()
00971 elif key == QtCore.Qt.Key_Minus:
00972 print '-'
00973 self.setScaleFactor(self.scaleFactor * 0.8)
00974 self.update()
00975 else:
00976 QtGui.QWidget.keyPressEvent(self, event)
00977
00978 def get_polygons(self):
00979 return self.polygons
00980
00981 def get_current_polygon_index(self):
00982 return self.current_polygon_index
00983
00984
00985
00986
00987
00988 if __name__ == "__main__":
00989 app = QtGui.QApplication(sys.argv)
00990 labeling_tool = labeling_tool('/home/martin/robot1_data/usr/martin/laser_camera_segmentation/labeling');
00991
00992 labeling_tool.show()
00993 sys.exit(app.exec_())