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 import roslib; roslib.load_manifest('trf_learn')
00028 import cv
00029 import rospy
00030 import sensor_msgs.msg as sm
00031
00032
00033 import numpy as np
00034 import scipy.spatial as sp
00035 import threading
00036 import Queue as qu
00037 import os.path as pt
00038 import glob
00039
00040 import pdb
00041
00042
00043 import libsvm.svmutil as su
00044
00045 import copy
00046 import os
00047
00048 import ml_lib.dataset as ds
00049 import ml_lib.dimreduce as dr
00050
00051
00052 import hrl_opencv.image3d as i3d
00053 import hrl_lib.util as ut
00054
00055 import hrl_lib.rutils as ru
00056 import hrl_lib.tf_utils as tfu
00057
00058 import trf_learn.intensity_feature as infea
00059
00060
00061
00062
00063 import time
00064 import pdb
00065
00066 UNLABELED = 2.0
00067 POSITIVE = 1.0
00068 NEGATIVE = 0.
00069
00070 def separate_by_labels(points, labels):
00071 pidx = np.where(labels == POSITIVE)[1].A1.tolist()
00072 nidx = np.where(labels == NEGATIVE)[1].A1.tolist()
00073 uidx = np.where(labels == UNLABELED)[1].A1.tolist()
00074 return points[:, uidx], points[:, pidx], points[:, nidx]
00075
00076 def confusion_matrix(true_labels, predicted):
00077 posidx = np.where(true_labels == POSITIVE)[1].A1
00078 negidx = np.where(true_labels == NEGATIVE)[1].A1
00079 m00 = m01 = m10 = m11 = 0
00080 nm00 = nm01 = nm10 = nm11 = 0
00081
00082 if len(negidx) > 0:
00083 nm00 = float(np.sum(NEGATIVE == predicted[:, negidx]))
00084 nm01 = float(np.sum(POSITIVE == predicted[:, negidx]))
00085 m00 = nm00 / len(negidx)
00086 m01 = nm01 / len(negidx)
00087
00088 if len(posidx) > 0:
00089 nm10 = float(np.sum(NEGATIVE == predicted[:, posidx]))
00090 nm11 = float(np.sum(POSITIVE == predicted[:, posidx]))
00091 m10 = nm10 / len(posidx)
00092 m11 = nm11 / len(posidx)
00093
00094 return np.matrix([[m00, m01], [m10, m11]], 'float')
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 def instances_to_image(win_size, instances, min_val, max_val):
00106 img_arrs = []
00107 for i in range(instances.shape[1]):
00108 img_arrs.append(instance_to_image(win_size, instances[:,i], min_val, max_val).copy())
00109 return cv.fromarray(np.concatenate(img_arrs, 0).copy())
00110
00111 def instance_to_image(win_size, instance, min_val, max_val):
00112 winside = win_size*2+1
00113 patch_size = winside*winside*3
00114
00115 srange = max_val - min_val
00116
00117 offset = 0
00118 patches = []
00119 num_patches = instance.shape[0] / patch_size
00120
00121
00122 for i in range(num_patches):
00123 s = instance[offset:offset+patch_size, 0]
00124 s = np.array(np.abs(np.round(((s-min_val)/srange) * 255.)), 'uint8')
00125 patches.append(np.reshape(s, (winside, winside, 3)))
00126 offset+=patch_size
00127
00128 return np.concatenate(patches, 1)
00129
00130 def insert_folder_name(apath, folder_name):
00131 path, filename = pt.split(apath)
00132 return pt.join(pt.join(path, folder_name), filename)
00133
00134 def load_data_from_file2(fname, rec_param):
00135 data_pkl = ut.load_pickle(fname)
00136 image_fname = pt.join(pt.split(fname)[0], data_pkl['image'])
00137 intensity_image = cv.LoadImageM(image_fname)
00138 center_point_bl = data_pkl['touch_point']
00139
00140 print 'Robot touched point cloud at point', center_point_bl.T
00141 distance_feature_points = None
00142 syn_locs_fname = pt.splitext(fname)[0] + '_synthetic_locs3d.pkl'
00143 if pt.isfile(syn_locs_fname):
00144 print 'found synthetic locations file', syn_locs_fname
00145 distance_feature_points = ut.load_pickle(syn_locs_fname)
00146 data_pkl['synthetic_locs3d'] = distance_feature_points
00147 else:
00148 print 'synthetic loc file not found', syn_locs_fname
00149
00150
00151
00152
00153 return infea.IntensityCloudFeatureExtractor(data_pkl['points3d'], intensity_image, center_point_bl,
00154 distance_feature_points, data_pkl['k_T_bl'],
00155 data_pkl['cal'], rec_param), data_pkl
00156
00157 def dataset_to_libsvm(dataset, filename):
00158 f = open(filename, 'w')
00159
00160 for i in range(dataset.outputs.shape[1]):
00161 if dataset.outputs[0,i] == POSITIVE:
00162 f.write('+1 ')
00163 else:
00164 f.write('-1 ')
00165
00166 for j in range(dataset.inputs.shape[0]):
00167 f.write('%d:%f ' % (j, dataset.inputs[j, i]))
00168 f.write('\n')
00169
00170 f.close()
00171
00172 def draw_labeled_points(image, dataset, pos_color=[255,102,55], neg_color=[0,184,245], scale=1.):
00173
00174 pt2d = dataset.pt2d
00175 for l, color in [(POSITIVE, pos_color), (NEGATIVE, neg_color)]:
00176 cols = np.where(l == dataset.outputs)[1]
00177 locs2d = np.matrix(np.round(pt2d[:, cols.A1]/scale), 'int')
00178 draw_points(image, locs2d, color)
00179
00180 def draw_points(img, img_pts, color, size=1, thickness=-1):
00181 for i in range(img_pts.shape[1]):
00182 center = tuple(np.matrix(np.round(img_pts[:,i]),'int').T.A1.tolist())
00183 cv.Circle(img, center, size, color, thickness)
00184
00185 def draw_dataset(dataset, img, scale=1., size=2, scan_id=None):
00186 npt2d = []
00187 ppt2d = []
00188 for i in range(dataset.inputs.shape[1]):
00189 if dataset.pt2d != None and dataset.pt2d[0,i] != None:
00190 if scan_id != None and dataset.scan_ids != None:
00191 if scan_id != dataset.scan_ids[0,i]:
00192 continue
00193 if POSITIVE == dataset.outputs[0,i]:
00194 ppt2d.append(dataset.pt2d[:,i]/scale)
00195 if NEGATIVE == dataset.outputs[0,i]:
00196 npt2d.append(dataset.pt2d[:,i]/scale)
00197 if len(ppt2d) > 0:
00198 draw_points(img, np.column_stack(ppt2d), [0,255,0], size)
00199 if len(npt2d) > 0:
00200 draw_points(img, np.column_stack(npt2d), [0,0,255], size)
00201
00202 def inverse_indices(indices_exclude, num_elements):
00203 temp_arr = np.zeros(num_elements)+1
00204 temp_arr[indices_exclude] = 0
00205 return np.where(temp_arr)[0]
00206
00207
00208 def preprocess_scan_extract_features(raw_data_fname, ext):
00209 rec_params = Recognize3DParam()
00210
00211
00212
00213
00214 feature_extractor, data_pkl = load_data_from_file2(raw_data_fname, rec_params)
00215 image_fname = pt.join(pt.split(raw_data_fname)[0], data_pkl['image'])
00216 print 'Image name is', image_fname
00217 img = cv.LoadImageM(image_fname)
00218 feature_cache_fname = pt.splitext(raw_data_fname)[0] + ext
00219 instances, points2d, points3d = feature_extractor.extract_features()
00220 labels = np.matrix([UNLABELED] * instances.shape[1])
00221
00222
00223
00224 preprocessed_dict = {'instances': instances,
00225 'points2d': points2d,
00226 'points3d': points3d,
00227 'image': image_fname,
00228 'labels': labels,
00229 'sizes': feature_extractor.get_sizes()}
00230 if data_pkl.has_key('synthetic_locs3d'):
00231 preprocessed_dict['synthetic_locs3d'] = data_pkl['synthetic_locs3d']
00232
00233 rospy.loginfo('saving results')
00234 ut.save_pickle(preprocessed_dict, feature_cache_fname)
00235 return feature_cache_fname
00236
00237 def preprocess_data_in_dir(dirname, ext):
00238 print 'Preprocessing data in', dirname
00239 data_files = glob.glob(pt.join(dirname, '*dataset.pkl'))
00240 print 'Found %d scans' % len(data_files)
00241
00242 for n in data_files:
00243 print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'
00244 print 'Loading', n
00245 cn = preprocess_scan_extract_features(n, ext)
00246 print 'Saved to', cn
00247 print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'
00248
00249 def make_point_exclusion_test_set(training_dataset, all_data_dir, ext):
00250
00251 scan_names = glob.glob(pt.join(all_data_dir, '*' + ext))
00252 dset = {'inputs': [], 'outputs': [], 'pt2d': [], 'pt3d': []}
00253 sizes = None
00254 i = 0
00255 for sn in scan_names:
00256
00257 print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'
00258 print 'Loading scan', sn
00259 cn = ut.load_pickle(sn)
00260 if sizes == None:
00261 sizes = cn['sizes']
00262 selected_pts_in_train = np.where(training_dataset.scan_ids == sn)[1]
00263 print ' There are %d points in scan' % cn['instances'].shape[1]
00264
00265
00266 if len(selected_pts_in_train) > 0:
00267 print ' There are %d of these points in the training set.' % len(selected_pts_in_train)
00268 scan_ind = training_dataset.idx_in_scan[0, selected_pts_in_train].A1
00269 select_ind = inverse_indices(scan_ind, cn['instances'].shape[1])
00270 assert((len(scan_ind) + len(select_ind)) == cn['instances'].shape[1])
00271 else:
00272 select_ind = np.array(range(cn['instances'].shape[1]))
00273 print ' Including %d points from this dataset' % len(select_ind)
00274
00275 for datak, dsetk in [('instances', 'inputs'), ('labels', 'outputs'),\
00276 ('points2d', 'pt2d'), ('points3d', 'pt3d')]:
00277 dset[dsetk].append(cn[datak][:, select_ind])
00278 i = i + 1
00279 if i > 2:
00280 break
00281
00282 return InterestPointDataset(np.column_stack(dset['inputs']),\
00283 np.column_stack(dset['outputs']),\
00284 None, None, None, sizes = sizes)
00285
00286
00287
00288
00289 class SVM:
00290
00291
00292
00293
00294 def __init__(self, dataset, params):
00295 samples = dataset.inputs.T.tolist()
00296 labels = dataset.outputs.T.A1.tolist()
00297
00298 print 'SVM: training with params => ', params
00299
00300
00301 self.model = su.svm_train(labels, samples, params)
00302 self.nsamples = len(samples)
00303
00304 def sv_indices(self):
00305 return np.where(self.model.get_support_vectors(self.nsamples))[0]
00306
00307 def predict(self, instances):
00308 xi = instances.T.tolist()
00309 return su.svm_predict([0]*instances.shape[1], xi, self.model)[0]
00310
00311 def distances(self, instances):
00312 xi = instances.T.tolist()
00313 dists = su.svm_predict([0]*instances.shape[1], xi, self.model)[2]
00314 return (np.matrix(dists)).T.A1.tolist()
00315
00316
00317 class DataScale:
00318
00319 def __init__(self):
00320 self.maxes = None
00321 self.mins = None
00322 self.ranges = None
00323
00324 def scale(self, data):
00325 if self.maxes == None:
00326 self.maxes = np.max(data,1)
00327 self.mins = np.min(data,1)
00328 self.ranges = self.maxes - self.mins
00329 self.ranges[np.where(self.ranges < .001)[0], :] = 1.
00330
00331
00332
00333 scaled = (((data - self.mins) / self.ranges) * 2.) - 1
00334 return scaled
00335
00336
00337 class PCAIntensities:
00338
00339 def __init__(self, intensities_index, reconstruction_std_lim, reconstruction_err_toler):
00340 self.intensities_mean = None
00341 self.intensities_std = None
00342 self.projection_basis = None
00343 self.intensities_index = intensities_index
00344 self.recon_err_raw = None
00345 self.reconstruction_error = None
00346 self.pca_data = None
00347 self.reconstruction_std_lim = reconstruction_std_lim
00348 self.reconstruction_err_toler = reconstruction_err_toler
00349
00350 def calculate_pca_vectors(self, data, variance_keep):
00351 data_in = data[self.intensities_index:, :]
00352
00353
00354 print 'PCAIntensities: data.shape', data.shape
00355 if self.intensities_mean != None:
00356 normed_data = (data_in - self.intensities_mean) / self.intensities_std
00357
00358 if True:
00359 print 'PCAIntensities: is_dataset_far_from_pca_subspace no, dataset is not far.'
00360 return
00361 else:
00362 print 'PCAIntensities: is_dataset_far_from_pca_subspace yes, dataset is far. recalculating pca.'
00363
00364 nsamples = min(data_in.shape[1], 3000)
00365 loaded_data = ut.load_pickle(self.pca_data)
00366 data_in = np.column_stack((data_in, loaded_data[self.intensities_index:, :]))
00367 ntotal = data_in.shape[1]
00368 data_in = data_in[:, np.random.permutation(np.array(range(ntotal)))[0:nsamples]]
00369
00370 self.intensities_mean = np.mean(data_in, 1)
00371 self.intensities_std = np.std(data_in, 1)
00372 self.intensities_std[np.where(self.intensities_std == 0)[0].A1, :] = 1
00373
00374 data_in_shifted = data_in - self.intensities_mean
00375 data_in_normed = data_in_shifted / self.intensities_std
00376 print 'PCAIntensities.calculate_pca_vectors: Constructing PCA basis'
00377
00378
00379 self.projection_basis = dr.pca_vectors(data_in_normed, variance_keep)[:,:50]
00380
00381 print 'PCAIntensities.calculate_pca_vectors: PCA basis size -', self.projection_basis.shape
00382
00383 projected = (self.projection_basis.T * data_in_normed)
00384 reconstruction = self.projection_basis * projected
00385 self.recon_err_raw = ut.norm(data_in_normed - reconstruction)
00386 self.recon_mean = np.mean(self.recon_err_raw)
00387 self.recon_std = np.std(self.recon_err_raw)
00388 self.reconstruction_error = self.calc_reconstruction_errors(projected, data_in_normed)
00389
00390 pca_data_name = time.strftime('%A_%m_%d_%Y_%I:%M%p') + '_pca_data.pkl'
00391
00392 ut.save_pickle(data, pca_data_name)
00393 self.pca_data = pca_data_name
00394
00395 def calc_reconstruction_errors(self, projected_instances, original_instances):
00396 errors = ut.norm((self.projection_basis * projected_instances) - original_instances)
00397 mal_dist_errors = (errors - self.recon_mean) / (self.recon_std**2)
00398 nhigh_errors = np.sum(np.abs(mal_dist_errors).A1 > self.reconstruction_std_lim)
00399 npoints = original_instances.shape[1]
00400 percent_error = nhigh_errors / (float(npoints))
00401 rospy.loginfo('calc_reconstruction_errors: %.2f (%d / %d) with high reconstruction errors' \
00402 % (percent_error, nhigh_errors, npoints))
00403 return percent_error
00404
00405 def is_dataset_far_from_pca_subspace(self, projected_instances, original_instances):
00406 percent_error = self.calc_reconstruction_errors(projected_instances, original_instances)
00407 return percent_error > (self.reconstruction_error + self.reconstruction_err_toler)
00408
00409 def partial_pca_project(self, instances):
00410
00411
00412
00413 instance_mean = np.mean(instances[self.intensities_index:, :], 1)
00414
00415 instances_in = (instances[self.intensities_index:, :] - instance_mean) / self.intensities_std
00416 reduced_intensities = self.projection_basis.T * instances_in
00417 return np.row_stack((instances[:self.intensities_index, :], reduced_intensities))
00418
00419 class SVMPCA_ActiveLearner:
00420
00421
00422
00423
00424 def __init__(self, use_pca, reconstruction_std_lim=None,
00425 reconstruction_err_toler=None, old_learner=None, pca=None):
00426 self.classifier = 'svm'
00427 self.classifiers = {}
00428 self.n = 3.
00429
00430
00431
00432 self.reduced_dataset = None
00433 self.dataset = None
00434
00435 self.use_pca = use_pca
00436 self.reconstruction_std_lim = reconstruction_std_lim
00437 self.reconstruction_err_toler = reconstruction_err_toler
00438 self.pca = None
00439
00440 if old_learner != None:
00441 self.pca = old_learner.pca
00442
00443 if pca != None:
00444 self.pca = pca
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 def partial_pca_project(self, instances):
00457 if self.use_pca:
00458 return self.pca.partial_pca_project(instances)
00459 else:
00460 return instances
00461
00462 def get_closest_instances(self, instances, n=1):
00463
00464 if self.use_pca:
00465 p_instances = np.matrix(self.partial_pca_project(instances))
00466 else:
00467 p_instances = instances
00468
00469 s_instances = self.scale.scale(p_instances)
00470 distances = np.array(self.classifiers['svm'].distances(s_instances))
00471 selected_indices = np.argsort(np.abs(distances))[0:n]
00472 return selected_indices.tolist(), distances[selected_indices]
00473
00474 def select_next_instances(self, instances, n=1):
00475
00476 data_idx, data_dists = self.get_closest_instances(instances, n)
00477 data_dist = abs(data_dists[0])
00478 sv_dist = abs(self.sv_dist[0])
00479
00480
00481
00482
00483 print 'SVMPCA_ActiveLearner: support vector dist %f data dist %f' % (sv_dist, data_dist)
00484 if sv_dist < data_dist:
00485 return None, None
00486 else:
00487 return data_idx, data_dists
00488
00489 def select_next_instances_no_terminate(self, instances, n=1):
00490 data_idx, data_dists = self.get_closest_instances(instances, n)
00491 data_dist = abs(data_dists[0])
00492 sv_dist = abs(self.sv_dist[0])
00493 return data_idx, data_dists, sv_dist < data_dist
00494
00495 def train(self, dataset, inputs_for_scaling, svm_params, variance_keep=.95):
00496
00497
00498
00499 self.dataset = dataset
00500 trainingset = dataset.inputs
00501 responses = dataset.outputs
00502
00503
00504 if self.use_pca:
00505
00506
00507
00508
00509 if self.pca == None:
00510 self.pca = PCAIntensities(self.dataset.metadata[-1].extent[0], self.reconstruction_std_lim, self.reconstruction_err_toler)
00511 self.pca.calculate_pca_vectors(inputs_for_scaling, variance_keep)
00512
00513
00514 trainingset = self.partial_pca_project(trainingset)
00515 inputs_for_scaling = self.partial_pca_project(inputs_for_scaling)
00516
00517 print 'SVMPCA_ActiveLearner.train: Training classifier.'
00518
00519
00520 trainingset = np.matrix(trainingset, dtype='float32').copy()
00521 responses = np.matrix(responses, dtype='float32').copy()
00522
00523 self.reduced_dataset = ds.Dataset(trainingset.copy(), responses.copy())
00524 self.scale = DataScale()
00525 if inputs_for_scaling == None:
00526 inputs_for_scaling = self.reduced_dataset.inputs
00527 else:
00528 print 'SVMPCA_ActiveLearner.train: using large input set for setting scaling parameters'
00529 self.scale.scale(inputs_for_scaling)
00530 rescaled_inputs = self.scale.scale(self.reduced_dataset.inputs)
00531 self.rescaled_dataset = ds.Dataset(rescaled_inputs, self.reduced_dataset.outputs)
00532
00533
00534 self.classifiers['svm'] = SVM(self.rescaled_dataset, svm_params)
00535
00536
00537 self.sv_instances = self.dataset.inputs[:, self.classifiers['svm'].sv_indices()]
00538 self.sv_idx, self.sv_dist = self.get_closest_instances(self.sv_instances, 1)
00539
00540
00541
00542 def classify(self, instances):
00543
00544
00545 projected_inst = np.matrix(self.partial_pca_project(instances), dtype='float32').copy()
00546 scaled_inst = self.scale.scale(projected_inst)
00547 if self.classifier == 'knn':
00548 labels = self.reduced_dataset.outputs[:, \
00549 self.classifiers['knn'].query(scaled_inst, self.n)[1].tolist()[0]]
00550 if np.sum(labels) > (self.n/2.):
00551 return POSITIVE
00552 else:
00553 return NEGATIVE
00554
00555 elif self.classifier == 'svm':
00556
00557 r = self.classifiers['svm'].predict(scaled_inst)
00558 return r
00559
00560 def _balance_classes(self, data, labels):
00561 posidx = np.where(labels == POSITIVE)[1].A1
00562 negidx = np.where(labels == NEGATIVE)[1].A1
00563 diff = abs(posidx.shape[0] - negidx.shape[0])
00564 if diff == 0:
00565 return data
00566
00567 rospy.loginfo('SVMPCA_ActiveLearner: _balance_classes difference in class sizes is %d' % diff)
00568
00569 posex = data[:, posidx]
00570 negex = data[:, negidx]
00571 if posidx.shape[0] < negidx.shape[0]:
00572 rospy.loginfo('SVMPCA_ActiveLearner. _balance_classes making data from POSITIVE instances')
00573 sset = posex
00574 else:
00575 rospy.loginfo('SVMPCA_ActiveLearner. _balance_classes making data from NEGATIVE instances')
00576 sset = negex
00577
00578 rsubset = sset[:, np.random.randint(0, sset.shape[1], diff)]
00579 rospy.loginfo('SVMPCA_ActiveLearner: _balance_classes created %d instances to make up for it' % rsubset.shape[1])
00580
00581 return np.column_stack((posex, negex, rsubset))
00582
00583 class InterestPointDataset(ds.Dataset):
00584
00585 def __init__(self, inputs, outputs, pt2d, pt3d, feature_extractor, scan_ids=None, idx_in_scan=None, sizes=None):
00586 ds.Dataset.__init__(self, inputs, outputs)
00587 self.pt2d = pt2d
00588 self.pt3d = pt3d
00589 self.scan_ids = scan_ids
00590
00591
00592 self.idx_in_scan = idx_in_scan
00593 offset = 0
00594
00595
00596 if feature_extractor != None or sizes != None:
00597 if feature_extractor != None:
00598 sizes = feature_extractor.get_sizes
00599 for k in ['expected_loc', 'distance', 'fpfh', 'intensity']:
00600 if sizes.has_key(k):
00601 start_idx = offset
00602 end_idx = offset + sizes[k]
00603 self.add_attribute_descriptor(ds.AttributeDescriptor(k, (start_idx, end_idx)))
00604 offset = end_idx
00605
00606 def select_features(self, features):
00607 fset = set(features)
00608 selected_fea = []
00609 meta_data = []
00610 offset = 0
00611 for meta in self.metadata:
00612 m = copy.deepcopy(meta)
00613 if fset.issuperset([m.name]):
00614
00615
00616
00617 size_m = m.extent[1] - m.extent[0]
00618 selected_fea.append(self.inputs[m.extent[0]:m.extent[1], :])
00619 m.extent = [offset, offset+size_m]
00620 meta_data.append(m)
00621 offset = offset + size_m
00622 self.metadata = meta_data
00623 self.inputs = np.row_stack(selected_fea)
00624
00625 def features_named(self, features):
00626 fset = set(features)
00627 selected_fea = []
00628 for meta in self.metadata:
00629 if fset.issuperset([meta.name]):
00630 selected_fea.append(self.inputs[meta.extent[0]:meta.extent[1], :])
00631 return np.row_stack(selected_fea)
00632
00633 def add(self, features, label, pt2d, pt3d, scan_id=None, idx_in_scan=None):
00634 print 'added point', pt2d[0,0], pt2d[1,0]
00635 if np.abs(pt2d[1,0]) > 10000:
00636 pdb.set_trace()
00637 if np.abs(pt2d[0,0]) > 10000:
00638 pdb.set_trace()
00639 self.inputs = np.column_stack((self.inputs, features))
00640 self.outputs = np.column_stack((self.outputs, label))
00641 self.pt2d = np.column_stack((self.pt2d, pt2d))
00642 self.pt3d = np.column_stack((self.pt3d, pt3d))
00643 if scan_id != None:
00644 self.scan_ids = np.column_stack((self.scan_ids, scan_id))
00645 if idx_in_scan != None:
00646 self.idx_in_scan = np.column_stack((self.idx_in_scan, idx_in_scan))
00647
00648 def remove(self, instance_idx):
00649 self.inputs = np.column_stack((self.inputs[:,0:instance_idx], self.inputs[:,instance_idx+1:]))
00650 self.outputs = np.column_stack((self.outputs[:,0:instance_idx], self.outputs[:,instance_idx+1:]))
00651 self.pt2d = np.column_stack((self.pt2d[:,0:instance_idx], self.pt2d[:,instance_idx+1:]))
00652 self.pt3d = np.column_stack((self.pt3d[:,0:instance_idx], self.pt3d[:,instance_idx+1:]))
00653 if self.scan_ids != None:
00654 self.scan_ids = np.column_stack((self.scan_ids[:,0:instance_idx], self.scan_ids[:,instance_idx+1:]))
00655 if self.idx_in_scan != None:
00656 self.idx_in_scan = np.column_stack((self.idx_in_scan[:,0:instance_idx], self.idx_in_scan[:,instance_idx+1:]))
00657
00658 def copy(self):
00659 ipd = InterestPointDataset(self.inputs.copy(), self.outputs.copy(),
00660 copy.copy(self.pt2d), copy.copy(self.pt3d), None)
00661 ipd.metadata = copy.deepcopy(self.metadata)
00662 return ipd
00663
00664 def subset(self, indices):
00665 ipd = InterestPointDataset(self.inputs[:, indices].copy(), self.outputs[:, indices].copy(),
00666 copy.copy(self.pt2d[:, indices]), copy.copy(self.pt3d[:, indices]), None)
00667 ipd.metadata = copy.deepcopy(self.metadata)
00668 return ipd
00669
00670 @classmethod
00671 def add_to_dataset(cls, dataset, features, label, pt2d, pt3d, scan_id, idx_in_scan, sizes):
00672 if dataset == None:
00673 dataset = InterestPointDataset(features, label, pt2d, pt3d, None, scan_id, idx_in_scan, sizes)
00674 else:
00675 dataset.add(features, label, pt2d, pt3d, scan_id=scan_id, idx_in_scan=idx_in_scan)
00676 return dataset
00677
00678
00679 class Recognize3DParam:
00680
00681 def __init__(self):
00682
00683 self.grid_resolution = .01
00684 self.win_size = 15
00685
00686
00687 self.win_multipliers = [2,4,8,16]
00688
00689 self.win3d_size = .02
00690 self.voi_bl = [.5, .5, .5]
00691 self.radius = .5
00692 self.robot_reach_radius = 2.5
00693
00694
00695
00696
00697
00698
00699
00700 self.svm_params = '-s 0 -t 2 -g .5 -c .5'
00701
00702
00703
00704
00705
00706 self.n_samples = 1500
00707 self.uni_mix = .3
00708 self.max_points_per_site = 5
00709
00710 self.uncertainty_x = .1
00711 self.uncertainty_y = .1
00712 self.uncertainty_z = .1
00713
00714
00715
00716 self.variance_keep = .99
00717 self.reconstruction_std_lim = 1.
00718 self.reconstruction_err_toler = .05
00719
00720
00721 class ImagePublisher:
00722
00723 def __init__(self, channel, cal=None):
00724 from cv_bridge import CvBridge, CvBridgeError
00725 from sensor_msgs.msg import Image
00726
00727 self.bridge = CvBridge()
00728 self.image_pub = rospy.Publisher(channel + '/image', Image)
00729 if cal != None:
00730 self.image_cal_pub = rospy.Publisher(channel + '/camera_info', sm.CameraInfo)
00731 self.cal = cal
00732 else:
00733 self.image_cal_pub = None
00734
00735 def publish(self, cv_image):
00736 self.image_pub.publish(self.bridge.cv_to_imgmsg(cv_image, "bgr8"))
00737 if self.image_cal_pub != None:
00738 self.image_cal_pub.publish(self.cal.msg)
00739
00740 def find_max_in_density(locs2d):
00741 import scipy.stats as sct
00742 import scipy
00743 x = locs2d[0,:]
00744 y = locs2d[1,:]
00745
00746 max_x = np.max(x)
00747 max_y = np.max(y)
00748 min_x = np.min(x)
00749 min_y = np.min(y)
00750
00751 X, Y = scipy.mgrid[min_x:max_x:500j, min_y:max_y:500j]
00752 positions = scipy.c_[X.ravel(), Y.ravel()]
00753 values = scipy.c_[locs2d[0,:].A1, locs2d[1,:].A1]
00754 kernel = sct.kde.gaussian_kde(values.T)
00755 Z = np.reshape(kernel(positions.T).T, X.T.shape)
00756 loc_max = np.argmax(Z)
00757 loc2d_max = np.matrix([X.flatten()[loc_max], Y.flatten()[loc_max]]).T
00758
00759
00760
00761
00762
00763
00764
00765
00766 return loc2d_max, Z
00767
00768 class ScanLabeler:
00769
00770 def __init__(self, dirname, ext, scan_to_train_on, seed_dset, features_to_use):
00771 self.scan_dir_name = dirname
00772 self.scan_names = glob.glob(pt.join(dirname, '*' + ext))
00773 self.scan_names.append(self.scan_names.pop(0))
00774 self.feature_file_ext = ext
00775 self.features_to_use = features_to_use
00776
00777 self.current_scan_pred = None
00778 self.current_scan = None
00779 self.cdisp = None
00780
00781 self.scan_idx = self.search_dataset_id(scan_to_train_on)
00782 if self.scan_idx == None:
00783 print 'ERROR: %s not found in dir %s' % (scan_to_train_on, dirname)
00784 self.scan_idx = 0
00785
00786 self.scale = 1/3.
00787
00788 self.mode = 'GROUND_TRUTH'
00789 if seed_dset == None:
00790 self.training_sname = pt.splitext(self.scan_names[self.scan_idx])[0] + '_seed.pkl'
00791 else:
00792 self.training_sname = seed_dset
00793 print 'Using seed dataset name', self.training_sname
00794 self.frame_number = 0
00795
00796 self.rec_params = Recognize3DParam()
00797 self.learner = None
00798 self.dataset = None
00799
00800 cv.NamedWindow('Scan', cv.CV_WINDOW_AUTOSIZE)
00801 cv.NamedWindow('Positive Density', cv.CV_WINDOW_AUTOSIZE)
00802 self.load_scan(self.scan_names[self.scan_idx])
00803 cv.SetMouseCallback('Scan', self.mouse_cb, None)
00804
00805
00806 def search_dataset_id(self, scan_name):
00807 scan_idx = None
00808 for i, n in enumerate(self.scan_names):
00809 if n == scan_name:
00810 scan_idx = i
00811 return scan_idx
00812
00813
00814 def classify_current_scan(self):
00815 if self.learner != None:
00816 sdset = self.select_features(self.current_scan['instances'],
00817 self.features_to_use, self.current_scan['sizes'])
00818 results = np.matrix(self.learner.classify(sdset))
00819 self.current_scan_pred = InterestPointDataset(sdset, results,
00820 self.current_scan['points2d'], self.current_scan['points3d'], None)
00821 if np.any(self.current_scan['labels'] == UNLABELED):
00822 return
00823
00824 def load_scan(self, fname):
00825 print 'Loading scan', fname
00826 self.cdisp = {}
00827 self.current_scan = ut.load_pickle(fname)
00828
00829 img = cv.LoadImageM(self.current_scan['image'])
00830 self.cdisp['tree'] = sp.KDTree(np.array(self.current_scan['points2d'].T))
00831 self.cdisp['cv'] = cv.CreateMat(int(round(img.rows*self.scale)),
00832 int(round(img.cols*self.scale)), cv.CV_8UC3)
00833 cv.Resize(img, self.cdisp['cv'])
00834 print 'loaded!'
00835 self.classify_current_scan()
00836 self.draw()
00837
00838 def save_current(self):
00839 print 'saving current scan\'s data'
00840 fname = self.scan_names[self.scan_idx]
00841 print 'WARNING: THIS SHOULD NOT BE CALLED.'
00842 ut.save_pickle(self.current_scan, fname)
00843 print 'done saving!'
00844
00845 def load_next(self):
00846 self.scan_idx = max(min(self.scan_idx+1, len(self.scan_names)-1), 0)
00847 self.load_scan(self.scan_names[self.scan_idx])
00848
00849 def load_prev(self):
00850 self.scan_idx = min(max(self.scan_idx-1, 0), len(self.scan_names)-1)
00851 self.load_scan(self.scan_names[self.scan_idx])
00852
00853 def draw(self, save_postf=""):
00854 img = cv.CloneMat(self.cdisp['cv'])
00855
00856
00857
00858
00859 pidx = np.where(self.current_scan['labels'] == POSITIVE)[1].A1.tolist()
00860 nidx = np.where(self.current_scan['labels'] == NEGATIVE)[1].A1.tolist()
00861 uidx = np.where(self.current_scan['labels'] == UNLABELED)[1].A1.tolist()
00862
00863 if len(pidx) > 0:
00864 ppoints = self.current_scan['points2d'][:, pidx]
00865 draw_points(img, ppoints * self.scale, [0,255,0], 2, 1)
00866
00867 if len(nidx) > 0:
00868 npoints = self.current_scan['points2d'][:, nidx]
00869 draw_points(img, npoints * self.scale, [0,0,255], 2, 1)
00870
00871 if len(uidx) > 0:
00872 upoints = self.current_scan['points2d'][:, uidx]
00873 draw_points(img, upoints * self.scale, [255,255,255], 2, 1)
00874
00875
00876 if self.dataset != None:
00877
00878 draw_dataset(self.dataset, img, 1./self.scale, 4, scan_id=self.scan_names[self.scan_idx])
00879
00880 if self.current_scan_pred != None:
00881 draw_labeled_points(img, self.current_scan_pred, scale=1./self.scale)
00882 locs2d = self.current_scan_pred.pt2d[:, (np.where(POSITIVE == self.current_scan_pred.outputs)[1]).A1]
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 cv.ShowImage('Scan', img)
00910 path = pt.splitext(insert_folder_name(self.scan_names[self.scan_idx], save_postf))[0]
00911 img_name = path + ('_active_learn%d.png' % (self.frame_number))
00912 cv.SaveImage(img_name, img)
00913 self.frame_number = self.frame_number + 1
00914 print '- refreshed display - %s' % img_name
00915
00916 def step(self):
00917 k = cv.WaitKey(33)
00918 if k == ord('n'):
00919 print 'Loading next scan..'
00920 self.load_next()
00921
00922 if k == ord('p'):
00923 print 'loading previous scan..'
00924 self.load_prev()
00925
00926 if k == ord('0'):
00927 self.current_scan['labels'][0, :] = NEGATIVE
00928 self.draw()
00929 print 'Labeling everything as negative!'
00930
00931 if k == ord('`'):
00932 if self.mode == 'TRAINING_SET':
00933 self.mode = 'GROUND_TRUTH'
00934 else:
00935 self.mode = 'TRAINING_SET'
00936 print 'ScanLabeler GUI mode changed to', self.mode
00937
00938 if k == ord('c'):
00939 self.save_current()
00940
00941 if k == ord('s'):
00942 if self.dataset != None:
00943
00944 ut.save_pickle(self.dataset, self.training_sname)
00945 print 'saved to', self.training_sname
00946
00947 if k == ord('l'):
00948 if self.dataset == None and pt.isfile(self.training_sname):
00949 print 'loading training set from disk'
00950 self.dataset = ut.load_pickle(self.training_sname)
00951 print 'loaded', self.training_sname
00952 self.draw()
00953
00954 if k == ord('t'):
00955 if self.dataset != None:
00956 print 'Making test set.'
00957 curr_test_set = make_point_exclusion_test_set(self.dataset, self.scan_dir_name)
00958 print 'Test set has %d instances' % curr_test_set.inputs.shape[1]
00959 fname = raw_input('Enter test set name to save to: ')
00960 print 'Saving to', fname
00961 ut.save_pickle(curr_test_set, fname)
00962 print 'Saved!'
00963
00964 if k == ord('r'):
00965 print "Training"
00966
00967 self.train(self.select_features(self.current_scan['instances'],
00968 self.features_to_use, self.current_scan['sizes']))
00969 self.classify_current_scan()
00970 self.draw()
00971
00972 if k == ord(' '):
00973 if self.learner != None:
00974 print "selecting.."
00975
00976 dset = self.select_features(self.current_scan['instances'],
00977 self.features_to_use, self.current_scan['sizes'])
00978
00979 selected_idx, selected_dist = self.learner.select_next_instances(dset)
00980 if selected_idx != None:
00981 self.add_to_training_set(selected_idx)
00982
00983 self.train(self.select_features(self.current_scan['instances'],
00984 self.features_to_use, self.current_scan['sizes']))
00985 self.classify_current_scan()
00986 self.draw()
00987 else:
00988 print '======================='
00989 print '>> LEARNER CONVERGED <<'
00990 print '======================='
00991
00992 if k == ord('z'):
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 print 'generating libsvm dataset'
01004 dfname = raw_input('enter dataset filename: ')
01005 dataset_to_libsvm(self.learner.rescaled_dataset, dfname)
01006
01007 print 'done'
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 def select_features(self, instances, features_to_use, sizes):
01030 offset = 0
01031 fset = set(features_to_use)
01032 selected_fea = []
01033 for k in ['expected_loc', 'distance', 'fpfh', 'intensity']:
01034 if not sizes.has_key(k):
01035 continue
01036 start_idx = offset
01037 end_idx = offset + sizes[k]
01038
01039 if fset.issuperset([k]):
01040 selected_fea.append(instances[start_idx:end_idx, :])
01041 offset = end_idx
01042
01043
01044 return np.row_stack(selected_fea)
01045
01046 def automatic_label(self):
01047 self.dataset = ut.load_pickle(self.training_sname)
01048 fea = self.select_features(self.current_scan['instances'], ['distance'], self.current_scan['sizes'])
01049
01050 self.train(fea)
01051
01052 for idx, name in enumerate(self.scan_names):
01053 self.scan_idx = idx
01054 self.load_scan(name)
01055 self.classify_current_scan()
01056 self.draw()
01057
01058 self.current_scan['labels'][0,:] = self.current_scan_pred.outputs[0,:]
01059 self.draw()
01060 self.save_current()
01061
01062
01063
01064
01065 def test_feature_perf(self, scans_to_train_on, features_to_use, exp_name, use_pca=None):
01066
01067 BASE_FILE_NAME = pt.splitext(insert_folder_name(self.scan_names[self.scan_idx], exp_name))[0]
01068 try:
01069 os.mkdir(pt.split(BASE_FILE_NAME)[0])
01070 except OSError, e:
01071 if e.errno != 17:
01072 pdb.set_trace()
01073 raise e
01074
01075
01076 if use_pca == None:
01077 if set(features_to_use).issuperset(['intensity']):
01078 use_pca = True
01079 else:
01080 use_pca = False
01081
01082 if not pt.isfile(self.training_sname):
01083 print 'test_feature_perf: Training file', self.training_sname, 'not found! exiting.'
01084 return
01085
01086
01087 feature_sizes = self.current_scan['sizes']
01088 nsizes = {}
01089 for f in features_to_use:
01090 nsizes[f] = feature_sizes[f]
01091
01092 dset_trained_on = []
01093 for sname in scans_to_train_on:
01094 scan_idx = self.search_dataset_id(sname)
01095 if scan_idx == None:
01096 print 'ERROR: %s not found in dir given' % (sname)
01097 dset_trained_on.append(scan_idx)
01098 self.load_scan(self.scan_names[scan_idx])
01099 rcurrent_scan = self.select_features(self.current_scan['instances'], features_to_use, feature_sizes)
01100 scan_ids = np.matrix([sname]*rcurrent_scan.shape[1])
01101 idx_in_scan = np.matrix(range(rcurrent_scan.shape[1]))
01102 if self.dataset == None:
01103 self.dataset = InterestPointDataset(rcurrent_scan, self.current_scan['labels'],
01104 self.current_scan['points2d'], self.current_scan['points3d'],
01105 None, scan_ids=scan_ids, idx_in_scan=idx_in_scan, sizes=nsizes)
01106 else:
01107 self.dataset.add(rcurrent_scan, self.current_scan['labels'], self.current_scan['points2d'],
01108 self.current_scan['points3d'], scan_id=scan_ids, idx_in_scan=idx_in_scan)
01109
01110 self.train(self.dataset.inputs, use_pca)
01111
01112 for d in dset_trained_on:
01113 self.load_scan(self.scan_names[d])
01114 self.scan_idx = d
01115 self.classify_current_scan()
01116 self.draw(exp_name)
01117
01118 k = cv.WaitKey(33)
01119
01120 print '>>>> Training set peformance'
01121 _, train_conf = self.evaluate_learner(self.dataset.inputs, self.dataset.outputs)
01122 train_set_statistics = []
01123 train_set_statistics.append({'conf': train_conf,
01124 'size': self.dataset.inputs.shape[1]})
01125
01126 print '>>>> Performance on unseen scans'
01127 print 'Loading scans we\'ll be testing on'
01128
01129 indices_of_other_scans = inverse_indices(dset_trained_on, len(self.scan_names))
01130 print 'Trained on', dset_trained_on
01131 print 'Testing with', indices_of_other_scans
01132
01133 self.dataset=None
01134 conf_unseen = []
01135 for i in indices_of_other_scans:
01136 self.load_scan(self.scan_names[i])
01137 self.scan_idx = i
01138 self.classify_current_scan()
01139 self.draw(exp_name)
01140 k = cv.WaitKey(33)
01141 sdset = self.select_features(self.current_scan['instances'], self.features_to_use, self.current_scan['sizes'])
01142 _, conf = self.evaluate_learner(sdset, self.current_scan['labels'])
01143 conf_unseen.append({'name': self.scan_names[i], 'conf': conf})
01144 perf_on_other_scans = []
01145 perf_on_other_scans.append(conf_unseen)
01146
01147
01148 training_results_name = BASE_FILE_NAME + 'active_train_iter_results.pkl'
01149 ut.save_pickle({'train_set_statistics': train_set_statistics,
01150
01151 'perf_on_other_scans': perf_on_other_scans}, training_results_name)
01152 print 'Saved training results to', training_results_name
01153
01154
01155 def generate_dataset_for_hyperparameter_grid_search(self, features_to_use):
01156 feature_sizes = self.current_scan['sizes']
01157
01158 for sname in self.scan_names:
01159 print 'generate_dataset_for_hyperparameter_grid_search: loading %s' % sname
01160 self.load_scan(sname)
01161 rcurrent_scan = self.select_features(self.current_scan['instances'], features_to_use, feature_sizes)
01162 scan_ids = np.matrix([sname]*rcurrent_scan.shape[1])
01163 idx_in_scan = np.matrix(range(rcurrent_scan.shape[1]))
01164 if self.dataset == None:
01165 self.dataset = InterestPointDataset(rcurrent_scan, self.current_scan['labels'],
01166 self.current_scan['points2d'], self.current_scan['points3d'],
01167 None, scan_ids=scan_ids, idx_in_scan=idx_in_scan, sizes=nsizes)
01168 else:
01169 self.dataset.add(rcurrent_scan, self.current_scan['labels'], self.current_scan['points2d'],
01170 self.current_scan['points3d'], scan_id=scan_ids, idx_in_scan=idx_in_scan)
01171
01172 self.train(self.dataset.inputs, True)
01173
01174
01175 def construct_learner(self, seed_set, prev_pca, g, c, ratio=None):
01176 features_used = ['intensity']
01177 learner = SVMPCA_ActiveLearner(use_pca=True,
01178 reconstruction_std_lim = self.rec_params.reconstruction_std_lim,
01179 reconstruction_err_toler = self.rec_params.reconstruction_err_toler,
01180 old_learner=self.learner, pca=prev_pca)
01181 if ratio == None:
01182 nneg = np.sum(seed_set.outputs == NEGATIVE)
01183 npos = np.sum(seed_set.outputs == POSITIVE)
01184 neg_to_pos_ratio = float(nneg)/float(npos)
01185 else:
01186 neg_to_pos_ratio = ratio
01187 weight_balance = ' -w0 1 -w1 %.2f' % neg_to_pos_ratio
01188
01189 inputs_for_pca = self.select_features(self.current_scan['instances'], features_used, self.current_scan['sizes'])
01190 svm_params = '-s 0 -t 2 -g %.6f -c %.2f' % (g, c)
01191 learner.train(seed_set,
01192
01193 inputs_for_pca,
01194 svm_params + weight_balance,
01195 self.rec_params.variance_keep)
01196 return learner
01197
01198 def evaluate_over_datasets(self, test_idx, learner, exp_name):
01199 for i in test_idx:
01200 self.learner = learner
01201 name = self.scan_names[i]
01202 self.load_scan(name)
01203 self.classify_current_scan()
01204 self.draw(exp_name)
01205
01206 def active_learn_test3(self):
01207
01208
01209 features_used = ['intensity']
01210 exp_name = 'fixed_intensity_bug_filtered_pca50_window15'
01211 path = pt.split(insert_folder_name(self.scan_names[self.scan_idx], exp_name))[0]
01212 g = .5
01213 c = .5
01214
01215 try:
01216 os.mkdir(path)
01217 except OSError, e:
01218 pass
01219
01220 train_idx = range(16)
01221 test_idx = range(20,24)
01222
01223
01224 print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'
01225 print 'Training initial learning from seed dataset'
01226
01227 print 'using', self.training_sname
01228 seed_set = ut.load_pickle(self.training_sname)
01229 metaintensity = seed_set.metadata[1]
01230 sizes = {'intensity': metaintensity.extent[1] - metaintensity.extent[0]}
01231 seed_set.metadata = [metaintensity]
01232 metaintensity.extent = [0, sizes['intensity']]
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245 test_inputs = []
01246 test_outputs = []
01247 print 'Loading test sets'
01248 for i in test_idx:
01249 name = self.scan_names[i]
01250 print 'loading', name
01251 eval_data_set = ut.load_pickle(name)
01252 test_inputs.append(self.select_features(eval_data_set['instances'], features_used, eval_data_set['sizes']))
01253 test_outputs.append(eval_data_set['labels'])
01254
01255 test_inputs = np.column_stack(test_inputs)
01256 test_outputs = np.column_stack(test_outputs)
01257
01258
01259 print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'
01260 print 'Learning phase'
01261 conf_mats = []
01262
01263
01264
01265 for i in train_idx[0:5]:
01266 self.scan_idx = i
01267 self.load_scan(name)
01268 cur_instances = self.select_features(self.current_scan['instances'],
01269 features_used, self.current_scan['sizes'])
01270 seed_set = InterestPointDataset.add_to_dataset(seed_set,
01271 cur_instances[:, :],
01272 self.current_scan['labels'][:, :],
01273 self.current_scan['points2d'][:, :],
01274 self.current_scan['points3d'][:, :],
01275 i, None,
01276 sizes=sizes)
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 learner = self.construct_learner(seed_set, None, g, c)
01295
01296 cv.SaveImage('pca_filtered_%s.png' % exp_name,\
01297 instances_to_image(\
01298 self.rec_params.win_size,\
01299 learner.pca.projection_basis,\
01300 np.min(learner.pca.projection_basis),\
01301 np.max(learner.pca.projection_basis)))
01302 prev_pca = learner.pca
01303 self.evaluate_over_datasets(test_idx, learner, exp_name)
01304
01305 pdb.set_trace()
01306 print confusion_matrix(test_outputs, np.matrix(self.construct_learner(seed_set, prev_pca, g, c).classify(test_inputs)))
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 ut.save_pickle(conf_mats, exp_name + '_confusion_mats.pkl')
01324
01325
01326
01327
01328
01329
01330
01331 def active_learn_test2(self):
01332
01333
01334 features_used = ['intensity']
01335 exp_name = 'autolearn_g05_c05_max5_pca50_fast_feature_patch15_0'
01336 path = pt.split(insert_folder_name(self.scan_names[self.scan_idx], exp_name))[0]
01337
01338 try:
01339 os.mkdir(path)
01340 except OSError, e:
01341 pass
01342
01343
01344 train_idx = np.random.permutation(range(16)).tolist()
01345
01346 test_idx = range(18,24)
01347
01348 print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'
01349 print 'Training initial learning from seed dataset'
01350
01351 print 'using', self.training_sname
01352 seed_set = ut.load_pickle(self.training_sname)
01353
01354 metaintensity = seed_set.metadata[1]
01355 sizes = {'intensity': metaintensity.extent[1] - metaintensity.extent[0]}
01356 seed_set.metadata = [metaintensity]
01357 metaintensity.extent = [0, sizes['intensity']]
01358
01359
01360
01361 pca_fname = 'pca_active_learn_test2.pkl'
01362 if pt.isfile(pca_fname):
01363 prev_pca = ut.load_pickle(pca_fname)
01364 else:
01365 prev_pca = None
01366 learner = SVMPCA_ActiveLearner(use_pca=True,
01367 reconstruction_std_lim = self.rec_params.reconstruction_std_lim,
01368 reconstruction_err_toler = self.rec_params.reconstruction_err_toler,
01369 old_learner=self.learner, pca=prev_pca)
01370 nneg = np.sum(seed_set.outputs == NEGATIVE)
01371 npos = np.sum(seed_set.outputs == POSITIVE)
01372 neg_to_pos_ratio = float(nneg)/float(npos)
01373 weight_balance = ' -w0 1 -w1 %.2f' % neg_to_pos_ratio
01374 inputs_for_pca = self.select_features(self.current_scan['instances'],
01375 features_used, self.current_scan['sizes'])
01376 learner.train(seed_set,
01377 inputs_for_pca,
01378 self.rec_params.svm_params + weight_balance,
01379 self.rec_params.variance_keep)
01380 prev_pca = learner.pca
01381 ut.save_pickle(prev_pca, pca_fname)
01382
01383 test_inputs = []
01384 test_outputs = []
01385 print 'Loading test sets'
01386 for i in test_idx:
01387 name = self.scan_names[i]
01388 print 'loading', name
01389 eval_data_set = ut.load_pickle(name)
01390 test_inputs.append(self.select_features(eval_data_set['instances'],
01391 features_used, eval_data_set['sizes']))
01392 test_outputs.append(eval_data_set['labels'])
01393
01394 test_inputs = np.column_stack(test_inputs)
01395 test_outputs = np.column_stack(test_outputs)
01396
01397
01398 print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'
01399 print 'Learning phase'
01400 conf_mats = []
01401 current_idx = 0
01402 number_of_converged_scans = 0
01403 iteration_number = 0
01404
01405 for i in train_idx:
01406
01407 name = self.scan_names[i]
01408 current_idx = i
01409
01410 print '!!!!!!!!!!!!!!!!!!!!!!!!!!!'
01411 print 'loading scan %s' % name
01412 self.scan_idx = current_idx
01413 self.load_scan(name)
01414 self.draw(exp_name)
01415 cur_instances = self.select_features(self.current_scan['instances'],
01416 features_used, self.current_scan['sizes'])
01417 converged = False
01418
01419 indices_added = []
01420 while True:
01421 if len(indices_added) > 5:
01422
01423 break
01424
01425 iteration_number += 1
01426 remaining_pt_indices = inverse_indices(indices_added, cur_instances.shape[1])
01427 remaining_instances = cur_instances[:, remaining_pt_indices]
01428 ridx, selected_dist, converged = learner.select_next_instances_no_terminate(remaining_instances)
01429 if converged:
01430 print 'Converged on scan.'
01431 break
01432
01433
01434 selected_idx = remaining_pt_indices[ridx[0]]
01435 indices_added.append(selected_idx)
01436 seed_set = InterestPointDataset.add_to_dataset(seed_set,
01437 cur_instances[:, selected_idx],
01438 self.current_scan['labels'][:, selected_idx],
01439 self.current_scan['points2d'][:, selected_idx],
01440 self.current_scan['points3d'][:, selected_idx],
01441 current_idx, selected_idx,
01442 sizes=sizes)
01443
01444
01445 learner = SVMPCA_ActiveLearner(use_pca=True,
01446 reconstruction_std_lim=self.rec_params.reconstruction_std_lim,
01447 reconstruction_err_toler=self.rec_params.reconstruction_err_toler,
01448 old_learner=self.learner, pca=prev_pca)
01449 nneg = np.sum(seed_set.outputs == NEGATIVE)
01450 npos = np.sum(seed_set.outputs == POSITIVE)
01451 neg_to_pos_ratio = float(nneg)/float(npos)
01452 weight_balance = ' -w0 1 -w1 %.2f' % neg_to_pos_ratio
01453 inputs_for_pca = self.select_features(self.current_scan['instances'], features_used, self.current_scan['sizes'])
01454 learner.train(seed_set,
01455 inputs_for_pca,
01456 self.rec_params.svm_params + weight_balance,
01457 self.rec_params.variance_keep)
01458 prev_pca = learner.pca
01459 ut.save_pickle(prev_pca, pca_fname)
01460
01461
01462 predictions = np.matrix(learner.classify(test_inputs))
01463 conf_mat = confusion_matrix(test_outputs, predictions)
01464 conf_mats.append(conf_mat)
01465 ut.save_pickle(conf_mats, exp_name + '_confusion_mats.pkl')
01466 ut.save_pickle(seed_set, exp_name + '_seed_set.pkl')
01467 print '---------------------------------'
01468 print iteration_number
01469 print 'scan idx', i
01470 print 'results'
01471 print conf_mat
01472 print conf_mat[0,0] + conf_mat[1,1]
01473
01474 self.learner = learner
01475 self.classify_current_scan()
01476 self.draw(exp_name)
01477
01478 if len(indices_added) == 0:
01479
01480 print 'OUTER LOOP CONVERGED', number_of_converged_scans
01481 number_of_converged_scans += 1
01482
01483 for i in test_idx:
01484 self.learner = learner
01485 name = self.scan_names[i]
01486 self.load_scan(name)
01487 self.classify_current_scan()
01488 self.draw(exp_name)
01489
01490
01491 predictions = np.matrix(learner.classify(test_inputs))
01492 conf_mat = confusion_matrix(test_outputs, predictions)
01493 conf_mats.append(conf_mat)
01494 ut.save_pickle(conf_mats, exp_name + '_confusion_mats.pkl')
01495 print '---------------------------------'
01496 print 'results'
01497 print conf_mat
01498 print conf_mat[0,0] + conf_mat[1,1]
01499
01500 self.learner = learner
01501 self.dataset = seed_set
01502 print 'DO NOT SAVE'
01503 print 'DO NOT SAVE'
01504 print 'DO NOT SAVE'
01505 print 'DO NOT SAVE'
01506 print 'DO NOT SAVE'
01507 print 'DO NOT SAVE'
01508 print 'DO NOT SAVE'
01509
01510 self.run_gui()
01511 pdb.set_trace()
01512
01513
01514 def active_learn_test(self, features_to_use, exp_name, use_pca=None, run_till_end=False):
01515 BASE_FILE_NAME = pt.splitext(insert_folder_name(self.scan_names[self.scan_idx], exp_name))[0]
01516 try:
01517 os.mkdir(pt.split(BASE_FILE_NAME)[0])
01518 except OSError, e:
01519 if e.errno != 17:
01520 pdb.set_trace()
01521 raise e
01522
01523
01524 if use_pca == None:
01525 if set(features_to_use).issuperset(['intensity']):
01526 use_pca = True
01527 else:
01528 use_pca = False
01529
01530 if not pt.isfile(self.training_sname):
01531 print 'active_learn_test: Training file', self.training_sname, 'not found! exiting.'
01532 return
01533
01534 feature_sizes = self.current_scan['sizes']
01535 print 'active_learn_test: Using features', features_to_use
01536 print 'active_learn_test: feature sizes'
01537 for k in ['expected_loc', 'distance', 'fpfh', 'intensity']:
01538 if feature_sizes.has_key(k):
01539 print k, feature_sizes[k]
01540
01541 total_dim = 0
01542 for f in features_to_use:
01543 total_dim += feature_sizes[f]
01544
01545 print 'active_learn_test: total feature size should be', total_dim
01546
01547
01548 rcurrent_scan = self.select_features(self.current_scan['instances'], features_to_use, feature_sizes)
01549
01550
01551 self.dataset = ut.load_pickle(self.training_sname)
01552 print 'active_learn_test: loaded seed training file', self.training_sname
01553 self.dataset.select_features(features_to_use)
01554
01555 self.train(rcurrent_scan, use_pca)
01556 self.classify_current_scan()
01557 self.draw(exp_name)
01558 k = cv.WaitKey(33)
01559
01560
01561 print 'Loading scans we\'ll be testing on'
01562 print 'TRAINING ON SCAN NAMED', self.scan_names[self.scan_idx]
01563 all_scans_except_current = []
01564 indices_of_other_scans = inverse_indices(self.scan_idx, len(self.scan_names))
01565 for i in indices_of_other_scans:
01566 sn = self.scan_names[i]
01567 print '>>', sn
01568 scan_dict = ut.load_pickle(sn)
01569 reduced_sd = {}
01570 reduced_sd['instances'] = self.select_features(scan_dict['instances'], features_to_use, feature_sizes)
01571 reduced_sd['labels'] = scan_dict['labels']
01572 reduced_sd['name'] = sn
01573 all_scans_except_current.append(reduced_sd)
01574
01575 i = 0
01576 converged = False
01577 train_set_statistics = []
01578 current_scan_statistics = []
01579 perf_on_other_scans = []
01580 converged_at_iter = None
01581 should_run = True
01582
01583
01584 while should_run:
01585 if self.learner.pca.projection_basis != None:
01586 cv.SaveImage(BASE_FILE_NAME + ('_iter_%d_basis.png' % i),\
01587 instances_to_image(\
01588 self.rec_params.win_size,\
01589 self.learner.pca.projection_basis,\
01590 np.min(self.learner.pca.projection_basis),\
01591 np.max(self.learner.pca.projection_basis)))
01592 cv.SaveImage(BASE_FILE_NAME + ('_intensity_set_%d.png' % i),\
01593 instances_to_image(self.rec_params.win_size, self.dataset.features_named(['intensity']),\
01594 0., 1.))
01595
01596 self.classify_current_scan()
01597 self.draw(exp_name)
01598 k = cv.WaitKey(33)
01599
01600 print '>>>> Train set peformance'
01601 _, train_conf = self.evaluate_learner(self.dataset.inputs, self.dataset.outputs)
01602 train_set_statistics.append({'conf': train_conf,
01603 'size': self.dataset.inputs.shape[1]})
01604
01605 print '>>>> Performance on current scan (correlated test set)'
01606 remaining_pt_indices = inverse_indices(self.dataset.idx_in_scan, rcurrent_scan.shape[1])
01607 remaining_instances = rcurrent_scan[:, remaining_pt_indices]
01608 remaining_outputs = self.current_scan['labels'][:, remaining_pt_indices]
01609
01610
01611 _, rem_conf = self.evaluate_learner(remaining_instances, remaining_outputs)
01612 current_scan_statistics.append({'conf': rem_conf})
01613
01614 print '>>>> Performance on unseen scans (test set)'
01615 conf_unseen = []
01616 for scan in all_scans_except_current:
01617 _, conf = self.evaluate_learner(scan['instances'], scan['labels'], verbose=False)
01618 conf_unseen.append({'name': scan['name'], 'conf': conf})
01619 perf_on_other_scans.append(conf_unseen)
01620
01621
01622
01623 remaining_pt_indices = inverse_indices(self.dataset.idx_in_scan, rcurrent_scan.shape[1])
01624 if len(remaining_pt_indices) > 0:
01625 ridx, selected_dist, converged = self.learner.select_next_instances_no_terminate(rcurrent_scan[:, remaining_pt_indices])
01626 if not converged or run_till_end:
01627 selected_idx = remaining_pt_indices[ridx]
01628 self.add_to_training_set(selected_idx)
01629 self.train(rcurrent_scan, use_pca)
01630 i = i + 1
01631 else:
01632 should_run = False
01633
01634 if converged and converged_at_iter == None:
01635 converged_at_iter = i
01636
01637 if i > 100 and converged:
01638 should_run = False
01639
01640 else:
01641 should_run = False
01642
01643 print '======================='
01644 print '>> LEARNER CONVERGED <<'
01645 print '======================='
01646 print 'saving dataset to', self.training_sname
01647 ut.save_pickle(self.dataset, BASE_FILE_NAME + '_converged_dset.pkl')
01648 print 'saved!'
01649
01650
01651 training_results_name = BASE_FILE_NAME + 'active_train_iter_results.pkl'
01652 ut.save_pickle({'train_set_statistics': train_set_statistics,
01653 'current_scan_statistics': current_scan_statistics,
01654 'perf_on_other_scans': perf_on_other_scans,
01655 'converged_at_iter': converged_at_iter}, training_results_name)
01656 print 'Saved training results to', training_results_name
01657
01658 def run_gui(self):
01659
01660 while not rospy.is_shutdown():
01661 self.step()
01662
01663 def mouse_cb(self, event, x, y, flags, param):
01664 if not (event == cv.CV_EVENT_LBUTTONDOWN or \
01665 event == cv.CV_EVENT_RBUTTONDOWN or \
01666 event == cv.CV_EVENT_MBUTTONDOWN):
01667 return
01668
01669 ck = [self.cdisp['tree'].query(np.array([x,y]) / self.scale, k=1)[1]]
01670 cr = self.cdisp['tree'].query_ball_point(np.array([x,y]) / self.scale, 5.)
01671
01672 print 'k nearest', len(ck), 'radius', len(cr)
01673
01674 if len(ck) > len(cr):
01675 closest_idx = ck
01676 else:
01677 closest_idx = cr
01678
01679 if self.mode == 'GROUND_TRUTH':
01680 if event == cv.CV_EVENT_LBUTTONDOWN:
01681 label = POSITIVE
01682 elif event == cv.CV_EVENT_RBUTTONDOWN:
01683 label = NEGATIVE
01684 elif event == cv.CV_EVENT_MBUTTONDOWN:
01685 label = UNLABELED
01686 else:
01687 return
01688
01689 print 'Current mode is', self.mode
01690
01691 self.current_scan['labels'][0, closest_idx] = label
01692
01693
01694
01695 if self.mode == 'TRAINING_SET':
01696
01697 if event == cv.CV_EVENT_LBUTTONDOWN:
01698 self.add_to_training_set(closest_idx)
01699
01700
01701 elif event == cv.CV_EVENT_RBUTTONDOWN:
01702 self.remove_from_training_set(closest_idx)
01703 self.draw()
01704
01705 def add_to_training_set(self, indices):
01706
01707 labeled_idx = []
01708 for idx in indices:
01709
01710
01711
01712
01713
01714
01715 if self.current_scan['labels'][0, idx] != UNLABELED:
01716 labeled_idx.append(idx)
01717
01718
01719
01720 filtered_idx = []
01721 if self.dataset != None:
01722 for idx in labeled_idx:
01723
01724 if self.dataset.idx_in_scan == None:
01725 matched_idx = []
01726 else:
01727 matched_idx = np.where(self.dataset.idx_in_scan == idx)[1].A1
01728 if len(matched_idx) > 0:
01729 if np.any(self.scan_names[self.scan_idx] == self.dataset.scan_ids[:, matched_idx]):
01730 continue
01731 filtered_idx.append(idx)
01732 else:
01733 filtered_idx += labeled_idx
01734
01735 if len(filtered_idx) < 1:
01736 print 'add_to_training_set: returned point #', labeled_idx, 'as it is already in the dataset'
01737 return
01738
01739 filtered_idx = [filtered_idx[0]]
01740 pinfo = [self.current_scan[k][:, filtered_idx] for k in \
01741 ['instances', 'labels', 'points2d', 'points3d']]
01742 pinfo.append(np.matrix([self.scan_names[self.scan_idx]] * len(filtered_idx)))
01743 pinfo.append(np.matrix(filtered_idx))
01744
01745 if self.dataset == None:
01746
01747 print 'WARNING: THIS BRANCH SHOULD BE REACHED DURING AUTONOMOUS RUN. add_to_training_set'
01748
01749 self.dataset = InterestPointDataset(self.select_features(pinfo[0], self.features_to_use, self.current_scan['sizes']),
01750 pinfo[1], pinfo[2], pinfo[3], None, pinfo[4], pinfo[5],
01751 sizes=self.current_scan['sizes'])
01752 else:
01753 self.dataset.add(self.select_features(pinfo[0], self.features_to_use, self.current_scan['sizes']), pinfo[1], \
01754 pinfo[2], pinfo[3], pinfo[4], pinfo[5])
01755
01756 print '>> Number of examples in dataset:', self.dataset.inputs.shape[1]
01757
01758 def remove_from_training_set(self, indices):
01759 if self.dataset != None:
01760 for idx in indices:
01761 matched_idx = np.where(self.dataset.idx_in_scan == idx)[1].A1
01762 if len(matched_idx) > 0:
01763 sm = np.where(self.scan_names[self.scan_idx] == self.dataset.scan_ids[:, matched_idx])[1]
01764 if len(sm) > 0:
01765 to_remove = matched_idx[sm]
01766 print 'removing', len(sm), 'points'
01767 for ridx in to_remove:
01768 self.dataset.remove(ridx)
01769
01770 def has_enough_data(self):
01771 pos_ex = np.sum(self.dataset.outputs)
01772 neg_ex = self.dataset.outputs.shape[1] - pos_ex
01773 if pos_ex > 0 and neg_ex > 0:
01774 return True
01775
01776 def train(self, inputs_for_scaling):
01777 if self.dataset != None and self.has_enough_data():
01778 use_pca=False
01779 for f in self.features_to_use:
01780 if f == 'intensity':
01781 use_pca=True
01782 nneg = np.sum(self.dataset.outputs == NEGATIVE)
01783 npos = np.sum(self.dataset.outputs == POSITIVE)
01784 print '================= Training ================='
01785 print 'NEG examples', nneg
01786 print 'POS examples', npos
01787 print 'TOTAL', self.dataset.outputs.shape[1]
01788 neg_to_pos_ratio = float(nneg)/float(npos)
01789
01790
01791
01792
01793 weight_balance = ' -w0 1 -w1 %.2f' % (neg_to_pos_ratio)
01794
01795
01796 self.learner = SVMPCA_ActiveLearner(use_pca,
01797 self.rec_params.reconstruction_std_lim,
01798 self.rec_params.reconstruction_err_toler,
01799 old_learner=self.learner)
01800
01801 self.learner.train(self.dataset,
01802 inputs_for_scaling,
01803 self.rec_params.svm_params + weight_balance,
01804 self.rec_params.variance_keep)
01805
01806
01807
01808
01809
01810
01811 if use_pca:
01812 BASE_FILE_NAME = 'pca_fast'
01813 i = 111
01814 cv.SaveImage(BASE_FILE_NAME + ('_iter_%d_basis.png' % i),\
01815 instances_to_image(\
01816 self.rec_params.win_size,\
01817 self.learner.pca.projection_basis,\
01818 np.min(self.learner.pca.projection_basis),\
01819 np.max(self.learner.pca.projection_basis)))
01820
01821
01822 print '================= DONE ================='
01823
01824 def evaluate_learner(self, instances, true_labels, verbose=True):
01825 predicted = np.matrix(self.learner.classify(instances))
01826
01827 posidx = np.where(true_labels == POSITIVE)[1].A1
01828 negidx = np.where(true_labels == NEGATIVE)[1].A1
01829 m00 = m01 = m10 = m11 = 0
01830 nm00 = nm01 = nm10 = nm11 = 0
01831 if len(negidx) > 0:
01832 nm00 = float(np.sum(NEGATIVE == predicted[:, negidx]))
01833 nm01 = float(np.sum(POSITIVE == predicted[:, negidx]))
01834 m00 = nm00 / len(negidx)
01835 m01 = nm01 / len(negidx)
01836
01837 if len(posidx) > 0:
01838 nm10 = float(np.sum(NEGATIVE == predicted[:, posidx]))
01839 nm11 = float(np.sum(POSITIVE == predicted[:, posidx]))
01840 m10 = nm10 / len(posidx)
01841 m11 = nm11 / len(posidx)
01842
01843 conf_mat = np.matrix([[m00, m01], [m10, m11]], 'float')
01844 if verbose:
01845 print 'Confusion matrix:'
01846 print '- %5.2f, %5.2f' % (100.* m00, 100.* m01)
01847 print '+ %5.2f, %5.2f' % (100.* m10, 100.* m11)
01848 print ' Total %5.2f' % (100.* (float(np.sum(true_labels == predicted)) / true_labels.shape[1]))
01849
01850 return predicted, {'mat': np.matrix([[nm00, nm01], [nm10, nm11]], 'float'),
01851 'neg': len(negidx),
01852 'pos': len(posidx)}
01853
01854
01855
01856 def add_to_dataset(self, pinfo):
01857 if self.dataset == None:
01858 self.dataset = InterestPointDataset(pinfo[0], pinfo[1], pinfo[2], \
01859 pinfo[3], None, pinfo[4], pinfo[5], sizes=self.current_scan['sizes'])
01860 else:
01861 self.dataset.add(pinfo[0], pinfo[1], \
01862 pinfo[2], pinfo[3], pinfo[4], pinfo[5])
01863
01864 class FiducialPicker:
01865
01866 def __init__(self, fname):
01867
01868 self.fname = fname
01869 self.data_pkl = ut.load_pickle(fname)
01870 image_fname = pt.join(pt.split(fname)[0], self.data_pkl['image'])
01871 self.img = cv.LoadImageM(image_fname)
01872 self.clicked_points = None
01873 self.clicked_points3d = None
01874
01875
01876
01877 bl_pc = self.data_pkl['points3d']
01878 self.image_T_laser = self.data_pkl['k_T_bl']
01879 self.image_arr = np.asarray(self.img)
01880 self.calibration_obj = self.data_pkl['cal']
01881 self.points_valid_image, self.colors_valid, self.points2d_valid = \
01882 i3d.combine_scan_and_image_laser_frame(bl_pc, self.image_T_laser,\
01883 self.image_arr, self.calibration_obj)
01884
01885 laser_T_image = np.linalg.inv(self.image_T_laser)
01886 self.points_valid_laser = tfu.transform_points(laser_T_image, self.points_valid_image[0:3,:])
01887 self.ptree = sp.KDTree(np.array(self.points2d_valid.T))
01888
01889 cv.NamedWindow('image', cv.CV_WINDOW_AUTOSIZE)
01890 cv.ShowImage('image', self.img)
01891 cv.SetMouseCallback('image', self.mouse_cb, None)
01892 self.exit = False
01893
01894
01895 def mouse_cb(self, event, x, y, flags, param):
01896 if event != cv.CV_EVENT_LBUTTONDOWN:
01897 return
01898
01899 pt = np.array([x,float(y)]).T
01900 idx = self.ptree.query(pt.T, k=1)[1]
01901
01902 if self.clicked_points != None:
01903 self.clicked_points = np.column_stack((self.clicked_points, self.points2d_valid[:, idx]))
01904 self.clicked_points3d = np.column_stack((self.clicked_points3d, self.points_valid_laser[:,idx]))
01905 else:
01906 self.clicked_points = self.points2d_valid[:, idx]
01907 self.clicked_points3d = self.points_valid_laser[:,idx]
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 def step(self):
01918 k = cv.WaitKey(33)
01919 if k == ord('s'):
01920 if self.clicked_points.shape[1] > 3:
01921 fname = pt.splitext(self.fname)[0] + '_synthetic_locs3d.pkl'
01922 print 'saving data to file:', fname
01923
01924
01925 ut.save_pickle(self.clicked_points3d, fname)
01926 else:
01927 print 'ignored save command, need more points. only has', self.clicked_points3d.shape[1]
01928
01929 if k == ord('x'):
01930 self.exit = True
01931
01932 ibuffer = cv.CloneMat(self.img)
01933 draw_points(ibuffer, self.points2d_valid, [0,255,0], 1)
01934
01935 if self.clicked_points != None:
01936 draw_points(ibuffer, self.clicked_points, [0,0,255], 3)
01937 cv.ShowImage('image', ibuffer)
01938
01939 def run(self):
01940 while not rospy.is_shutdown():
01941 self.step()
01942 if self.exit:
01943 return
01944
01945 class NarrowTextureFeatureExtractor:
01946 def __init__(self, prosilica, narrow_texture, prosilica_cal, projector, tf_listener, rec_params=None):
01947 self.cal = prosilica_cal
01948 self.prosilica = prosilica
01949 self.narrow_texture = narrow_texture
01950 self.tf_listener = tf_listener
01951 self.projector = projector
01952
01953 if rec_params == None:
01954 rec_params = Recognize3DParam()
01955 self.rec_params = rec_params
01956
01957 def read(self, expected_loc_bl, params=None):
01958
01959 rospy.loginfo('grabbing point cloud')
01960 pointcloud_msg = self.narrow_texture.read()
01961 rospy.loginfo('grabbing prosilica frame')
01962 self.projector.set(False)
01963 for i in range(3):
01964 cvimage_mat = self.prosilica.get_frame()
01965 self.projector.set(True)
01966 rospy.loginfo('processing')
01967 pointcloud_ns = ru.pointcloud_to_np(pointcloud_msg)
01968 pointcloud_bl = tfu.transform_points(tfu.transform('base_link',\
01969 'narrow_stereo_optical_frame', self.tf_listener),\
01970 pointcloud_ns)
01971
01972 image_T_bl = tfu.transform('high_def_optical_frame', 'base_link', self.tf_listener)
01973
01974 if params == None:
01975 params = self.rec_params
01976
01977
01978
01979
01980 extractor = infea.IntensityCloudFeatureExtractor(pointcloud_bl, cvimage_mat, expected_loc_bl,
01981 None, image_T_bl, self.cal, params)
01982 xs, locs2d, locs3d = extractor.extract_features()
01983
01984 rdict = {
01985
01986 'points3d': pointcloud_bl,
01987 'image': cvimage_mat}
01988
01989 return {'instances': xs,
01990 'points2d': locs2d,
01991 'points3d': locs3d,
01992 'image': cvimage_mat,
01993 'rdict': rdict,
01994 'sizes': extractor.sizes}
01995
01996
01997 if __name__ == '__main__':
01998 import sys
01999 import optparse
02000 p = optparse.OptionParser()
02001 p.add_option('-m', '--mode', action='store',
02002 dest='mode', default='label',
02003 help='fiducialpicker, preprocess, or label')
02004 p.add_option("-f", "--feature", action="append", type="string")
02005 p.add_option("-t", "--test", action="store_true")
02006 p.add_option("-r", "--train", action="append", type="string")
02007 p.add_option("-n", "--expname", action="store", default="")
02008 p.add_option("-p", "--pca", action="store_true", default=None)
02009 p.add_option("-s", "--seed", action="store", default=None, help='not strictly neccessary if you use pickles ending with _seed.pkl')
02010 p.add_option("-e", "--end", action="store_true", default=False)
02011 p.add_option("-l", "--locations", action="store", default=None)
02012 p.add_option("-a", "--autolabel", action="store_true", default=None)
02013
02014 opt, args = p.parse_args()
02015 mode = opt.mode
02016
02017 print '======================================='
02018 print 'mode:', mode
02019 print '======================================='
02020 print args
02021
02022 if mode == 'fiducialpicker':
02023 fp = FiducialPicker(args[0])
02024 fp.run()
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037 if mode == 'preprocess':
02038 rospy.init_node('detect_fpfh', anonymous=True)
02039 preprocess_data_in_dir(args[0], ext='_features_df2_dict.pkl')
02040
02041 if mode == 'locations':
02042 if opt.locations != None:
02043 locations = ut.load_pickle(opt.locations)
02044 keys = locations['data'].keys()
02045 for i, key in enumerate(keys):
02046 print i, key
02047 picked_i = int(raw_input('pick a key to use'))
02048 seed_dset = keys[i]
02049 fname = raw_input('pick a file name')
02050 dset = locations['data'][seed_dset]['dataset']
02051 dset.idx_in_scan = np.matrix(dset.inputs.shape[1] * [0])
02052 dset.scan_ids = np.matrix(dset.inputs.shape[1] * [''])
02053
02054 ut.save_pickle(dset, fname)
02055 pdb.set_trace()
02056 print 'saved %s' % fname
02057
02058
02059 if mode == 'hyper':
02060 s = ScanLabeler(args[0], ext='_features_df2_dict.pkl', scan_to_train_on=opt.train,
02061 seed_dset=opt.seed, features_to_use=opt.feature)
02062 s.generate_dataset_for_hyperparameter_grid_search(opt.feature)
02063
02064
02065 if mode == 'label':
02066 s = ScanLabeler(args[0], ext='_features_df2_dict.pkl', scan_to_train_on=opt.train,
02067 seed_dset=opt.seed, features_to_use=opt.feature)
02068
02069
02070 if opt.autolabel:
02071 s.automatic_label()
02072 elif opt.test:
02073 print 'Running automated tests'
02074 print 'Using features', opt.feature
02075 s.active_learn_test2()
02076
02077
02078
02079
02080 else:
02081 print 'launching gui.'
02082 s.run_gui()
02083
02084 if mode == 'feature':
02085 s = ScanLabeler(args[0], ext='_features_df2_dict.pkl', scan_to_train_on=opt.train[0],
02086 seed_dset=opt.seed, features_to_use=opt.feature)
02087 if len(opt.feature) == 1 and opt.feature[0] == 'distance':
02088 s.test_feature_perf(opt.train, ['distance'], opt.expname, opt.pca)
02089 else:
02090 s.test_feature_perf(opt.train, opt.feature, opt.expname, opt.pca)
02091
02092 if mode == 'call_fpfh':
02093 rospy.init_node('detect_fpfh', anonymous=True)
02094 fpfh = rospy.ServiceProxy('fpfh', fsrv.FPFHCalc)
02095
02096 print 'loading'
02097 extractor, _ = load_data_from_file(args[0], Recognize3DParam())
02098
02099 req = fsrv.FPFHCalcRequest()
02100 print 'npoints', extractor.points3d_valid_laser.shape[1]
02101 req.input = ru.np_to_pointcloud(extractor.points3d_valid_laser, 'base_link')
02102
02103 print 'requesting'
02104 res = fpfh(req)
02105 print 'response received'
02106
02107
02108
02109 histogram = np.matrix(res.hist.histograms).reshape((res.hist.npoints,33)).T
02110 points3d = np.matrix(res.hist.points3d).reshape((res.hist.npoints,3)).T
02111 print 'done'
02112 print 'done'
02113 print 'done'
02114 print 'done'
02115 print 'done'
02116
02117 if mode == 'kinect':
02118
02119
02120
02121 rospy.init_node('kinect_features')
02122 kfe = KinectFeatureExtractor()
02123 fname = opt.train[0]
02124
02125 dataset = ut.load_pickle(fname)
02126 nneg = np.sum(dataset.outputs == NEGATIVE)
02127 npos = np.sum(dataset.outputs == POSITIVE)
02128 print '================= Training ================='
02129 print 'NEG examples', nneg
02130 print 'POS examples', npos
02131 print 'TOTAL', dataset.outputs.shape[1]
02132 neg_to_pos_ratio = float(nneg)/float(npos)
02133 weight_balance = ' -w0 1 -w1 %.2f' % neg_to_pos_ratio
02134 learner = SVMPCA_ActiveLearner(use_pca=True)
02135 trained = False
02136 ip = ImagePublisher('active_learn')
02137
02138 while not rospy.is_shutdown():
02139
02140 xs, locs2d, locs3d, rdict['image'], rdict = kfe.read()
02141 if not trained:
02142 learner.train(dataset, xs, kfe.rec_params.svm_params + weight_balance,
02143 kfe.rec_params.variance_keep)
02144 trained = True
02145
02146
02147 results = np.matrix(learner.classify(sdset))
02148 current_scan_pred = InterestPointDataset(xs, results, locs2d, locs3d, None)
02149
02150
02151 img = cv.CloneMat(cdisp['cv'])
02152 draw_labeled_points(img, current_scan_pred, scale=1./self.scale)
02153 ip.publish(img)
02154
02155 rospy.spin()
02156