gaussian_histogram_features.py
Go to the documentation of this file.
00001 #
00002 # Copyright (c) 2010, Georgia Tech Research Corporation
00003 # All rights reserved.
00004 #
00005 # Redistribution and use in source and binary forms, with or without
00006 # modification, are permitted provided that the following conditions are met:
00007 #     * Redistributions of source code must retain the above copyright
00008 #       notice, this list of conditions and the following disclaimer.
00009 #     * Redistributions in binary form must reproduce the above copyright
00010 #       notice, this list of conditions and the following disclaimer in the
00011 #       documentation and/or other materials provided with the distribution.
00012 #     * Neither the name of the Georgia Tech Research Corporation nor the
00013 #       names of its contributors may be used to endorse or promote products
00014 #       derived from this software without specific prior written permission.
00015 #
00016 # THIS SOFTWARE IS PROVIDED BY GEORGIA TECH RESEARCH CORPORATION ''AS IS'' AND
00017 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 # DISCLAIMED. IN NO EVENT SHALL GEORGIA TECH BE LIABLE FOR ANY DIRECT, INDIRECT,
00020 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00021 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00022 # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00023 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00024 # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00025 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 #
00027 
00028 #  \author Martin Schuster (Healthcare Robotics Lab, Georgia Tech.)
00029 
00030 from features import features
00031 
00032 import laser_camera_segmentation.gaussian_curvature as gaussian_curvature
00033 import scipy.stats as stats
00034 import numpy as np
00035 import opencv as cv
00036 import scipy.spatial.kdtree as kdtree
00037 import hrl_lib.util as ut
00038 from hrl_lib.util import getTime
00039 import os
00040 
00041 import laser_camera_segmentation.texture_features as texture_features
00042 
00043 import processor
00044 import copy
00045 
00046 class gaussian_histogram_features(features):
00047     '''
00048     classdocs
00049     '''
00050     
00051     #all_save_load: set to true only if nonzero_indices contain all pts in pt-cloud!
00052     def prepare(self, features_k_nearest_neighbors, nonzero_indices = None, all_save_load = False, regenerate_neightborhood_indices = False):
00053         #print np.shape(self.processor.pts3d_bound), 'shape pts3d_bound'
00054 
00055         imgTmp = cv.cvCloneImage(self.processor.img)
00056         self.imNP = ut.cv2np(imgTmp,format='BGR')
00057         self.processor.map2d = np.asarray(self.processor.map[0][0:2]) #copied from laser to image mapping
00058         
00059         if features_k_nearest_neighbors == None or features_k_nearest_neighbors == False: #use range
00060             self.kdtree2d = kdtree.KDTree(self.processor.pts3d_bound.T)
00061             
00062             #print len(nonzero_indices)
00063             #print np.shape(np.asarray((self.processor.pts3d_bound.T)[nonzero_indices]))
00064             
00065             if nonzero_indices != None:
00066                 print getTime(), 'query ball tree for ', len(nonzero_indices), 'points'
00067                 kdtree_query = kdtree.KDTree((self.processor.pts3d_bound.T)[nonzero_indices])
00068             else:
00069                 print getTime(), 'query ball tree'
00070                 kdtree_query = kdtree.KDTree(self.processor.pts3d_bound.T)
00071             
00072             filename = self.processor.config.path+'/data/'+self.processor.scan_dataset.id+'_sphere_neighborhood_indices_'+str(self.processor.feature_radius)+'.pkl'
00073             if all_save_load == True and os.path.exists(filename) and regenerate_neightborhood_indices == False:
00074                 #if its already there, load it:
00075                 print getTime(), 'loading',filename
00076                 self.kdtree_queried_indices = ut.load_pickle(filename)    
00077             else:
00078                 self.kdtree_queried_indices = kdtree_query.query_ball_tree(self.kdtree2d, self.processor.feature_radius, 2.0, 0.2) #approximate
00079                 print getTime(), 'queried kdtree: ',len(self.kdtree_queried_indices),'points, radius:',self.processor.feature_radius
00080                 if all_save_load == True:
00081                     ut.save_pickle(self.kdtree_queried_indices, filename)
00082                     
00083             #make dict out of list for faster operations? (doesn't seem to change speed significantly):
00084             #self.kdtree_queried_indices = dict(zip(xrange(len(self.kdtree_queried_indices)), self.kdtree_queried_indices))
00085         
00086         else: #experiemental: use_20_nearest_neighbors == True
00087             #TODO: exclude invalid values in get_featurevector (uncomment code there)
00088            
00089             self.kdtree2d = kdtree.KDTree(self.processor.pts3d_bound.T)
00090             self.kdtree_queried_indices = []
00091             print getTime(), 'kdtree single queries for kNN start, k=', features_k_nearest_neighbors
00092             count = 0
00093             for point in ((self.processor.pts3d_bound.T)[nonzero_indices]):
00094                 count = count + 1
00095                 result = self.kdtree2d.query(point, features_k_nearest_neighbors,0.2,2,self.processor.feature_radius)
00096                 #existing = result[0][0] != np.Inf
00097                 #print existing
00098                 #print result[1]
00099                 self.kdtree_queried_indices += [result[1]] #[existing]
00100                 if count % 4096 == 0:
00101                     print getTime(),count
00102             print getTime(), 'kdtree singe queries end'
00103             
00104             #convert to numpy array -> faster access
00105             self.kdtree_queried_indices = np.asarray(self.kdtree_queried_indices)
00106         
00107         #print self.kdtree_queried_indices
00108         #takes long to compute:
00109         #avg_len = 0
00110         #minlen = 999999
00111         #maxlen = 0
00112         #for x in self.kdtree_queried_indices:
00113         #    avg_len += len(x)
00114         #    minlen = min(minlen, len(x))
00115         #    maxlen = max(maxlen, len(x))
00116         #avg_len = avg_len / len(self.kdtree_queried_indices)
00117         #print getTime(), "range neighbors: avg_len", avg_len, 'minlen', minlen, 'maxlen', maxlen
00118         
00119         
00120         #create HSV numpy images:
00121         # compute the hsv version of the image 
00122         image_size = cv.cvGetSize(self.processor.img)
00123         img_h = cv.cvCreateImage (image_size, 8, 1)
00124         img_s = cv.cvCreateImage (image_size, 8, 1)
00125         img_v = cv.cvCreateImage (image_size, 8, 1)
00126         img_hsv = cv.cvCreateImage (image_size, 8, 3)
00127         
00128         cv.cvCvtColor (self.processor.img, img_hsv, cv.CV_BGR2HSV)
00129         
00130         cv.cvSplit (img_hsv, img_h, img_s, img_v, None)
00131         self.imNP_h = ut.cv2np(img_h)
00132         self.imNP_s = ut.cv2np(img_s)
00133         self.imNP_v = ut.cv2np(img_v)
00134         
00135         textures = texture_features.eigen_texture(self.processor.img)
00136         self.imNP_tex1 = textures[:,:,0]
00137         self.imNP_tex2 = textures[:,:,1]
00138         
00139         self.debug_before_first_featurevector = True
00140         
00141         self.generate_voi_histogram(self.processor.point_of_interest,self.processor.voi_width)
00142               
00143 
00144 
00145     #has to have at least length 2 because of openCV matrices!!!!
00146     def get_indexvector(self, type):
00147         
00148         var_idx = []
00149         #start indices
00150         rh1 = 0 #zhist, normal, eigenvalue1, ev2
00151         ch1 = rh1 + 6 #hsi zhist, maxheight-diff, tex1, tex2
00152         ci = ch1 + 25
00153         end = ci + 4 #
00154         if type=='range':
00155             for i in range(rh1, ch1):
00156                 var_idx.append(i) 
00157         elif type=='color':
00158             for i in range(ch1, end):
00159                 var_idx.append(i)                                        
00160         #for plotting:
00161         elif type=='hsvi':
00162             for i in range(ci,end):
00163                 var_idx.append(i)                         
00164         else: #all
00165             for i in range(rh1, end):
00166                 var_idx.append(i)   
00167 
00168         return np.array(var_idx)    
00169         
00170         
00171         
00172     #get the feature vector for a specific point
00173     def get_featurevector(self, index, count, pts = None):
00174         if pts == None:
00175             pts = self.processor.pts3d_bound
00176 
00177         #print 'i',index,'c', count
00178         fv = []
00179         
00180         indices = np.asarray(self.kdtree_queried_indices[count])
00181         invalid_value = np.shape(pts)[1]
00182         #print indices
00183         #print 'iv',invalid_value
00184         indices = indices[indices != invalid_value]
00185         
00186         #print getTime(), indices
00187         #print getTime(), 'number of pts', len(indices)
00188         a = pts[:,indices]
00189         view = processor.rotate_to_plane(self.processor.scan_dataset.ground_plane_normal, np.matrix([-1,0,0.]).T)
00190         normal, eigenvalues = gaussian_curvature.gaussian_curvature(a,view)
00191         #eigenvalues = eigenvalues / np.square(r)
00192         #fv += [normal[0,0],0,normal[2,0]]
00193         #fv += normal.T.A[0].tolist()
00194         #fv += eigenvalues.tolist()
00195         #print np.asarray(pts[:,index].T[0])[0]
00196        # print 'pt',np.asarray(pts[:,index].T[0])
00197         point = pts[:,index]
00198         
00199         ev1, ev2 = self.get_voi_histogram_spread(point)
00200         #z_max_height_diff = pts[2,index] - self.get_voi_maxcount_height()
00201         #fv += [self.get_voi_histogram_value(point),z_max_height_diff,normal[0,0],normal[1,0],normal[2,0], ev1, ev2]
00202         fv += [self.get_voi_histogram_value(point),normal[0,0],normal[1,0],normal[2,0], ev1, ev2]
00203         
00204         h = self.imNP_h[self.processor.map2d[1,index],self.processor.map2d[0,index]]
00205         s = self.imNP_s[self.processor.map2d[1,index],self.processor.map2d[0,index]]
00206         i = self.processor.intensities_bound[index]
00207         hsi = self.get_voi_hsi_histogram_values(point,h,s,i)
00208         fv += [hsi[0],hsi[1],hsi[2]]
00209         #print np.shape(self.imNP_tex1)
00210         #print np.shape(self.map2d)
00211         tex1 = self.imNP_tex1[self.processor.map2d[1,index],self.processor.map2d[0,index]]
00212         tex2 = self.imNP_tex2[self.processor.map2d[1,index],self.processor.map2d[0,index]]
00213         fv += [tex1, tex2]
00214         #print tex1, tex2
00215         
00216 
00217         #color histograms:
00218         colors_h = []
00219         colors_s = []
00220         colors_v = []
00221         for idx in indices:
00222             colors_h.append(float(self.imNP_h[self.processor.map2d[1,idx],self.processor.map2d[0,idx]]))
00223             colors_s.append(float(self.imNP_s[self.processor.map2d[1,idx],self.processor.map2d[0,idx]]))
00224             colors_v.append(float(self.imNP_v[self.processor.map2d[1,idx],self.processor.map2d[0,idx]]))
00225         
00226         color_hist = stats.histogram2(np.array(colors_h), [0,51,102,153,204])
00227         color_hist = color_hist / float(np.sum(color_hist))
00228         color_hist = list(color_hist)
00229         fv += color_hist
00230         color_hist = stats.histogram2(np.array(colors_s), [0,51,102,153,204])
00231         color_hist = color_hist / float(np.sum(color_hist))
00232         color_hist = list(color_hist)
00233         fv += color_hist
00234         color_hist = stats.histogram2(np.array(colors_v), [0,51,102,153,204])
00235         color_hist = color_hist / float(np.sum(color_hist))
00236         color_hist = list(color_hist)
00237         fv += color_hist
00238         
00239         #intensities
00240         intensities = self.processor.intensities_bound[indices]
00241         intensities = np.asarray(intensities)
00242         #map to 0-255-range:   TODO: perhaps do some nonlinear transformation here? 
00243         intensities = intensities / 10000 * 255
00244         intensity_hist = stats.histogram2(intensities, [0,51,102,153,204])
00245         intensity_hist = intensity_hist / float(np.sum(intensity_hist))
00246         intensity_hist = list(intensity_hist)
00247         fv += intensity_hist    
00248     
00249         #current colors:
00250         fv += [float(self.imNP_h[self.processor.map2d[1,index],self.processor.map2d[0,index]]) / 255.0]
00251         fv += [float(self.imNP_s[self.processor.map2d[1,index],self.processor.map2d[0,index]]) / 255.0]
00252         fv += [float(self.imNP_v[self.processor.map2d[1,index],self.processor.map2d[0,index]]) / 255.0]  
00253         
00254         #current intensity value (scaled)
00255         intensity = self.processor.intensities_bound[index]
00256         #scale:
00257         intensity = intensity / 15000.0
00258         intensity = [intensity]
00259         fv += intensity  
00260 
00261         
00262         if self.debug_before_first_featurevector == True:
00263             self.debug_before_first_featurevector = False
00264             print getTime(), 'feature vector sample(gaussian histograms):', fv
00265         return fv
00266     
00267     
00268 
00269         #cube of interest around point
00270     def generate_voi_histogram(self, poi, width):
00271         print 'poi',poi,'width',width
00272         pts_indices = self.get_voi_pts_indices(poi, width)
00273         self.voi_pts_indices = pts_indices
00274         pts = np.asarray(self.processor.pts3d_bound)
00275         pts = pts[:,pts_indices]
00276         self.voi_pts = pts
00277         #mlab.points3d(pts[0,:],pts[1,:],pts[2,:], mode='point')
00278         #mlab.show() 
00279         min = 0.
00280         max = 2.
00281         self.voi_bincount = 80
00282         self.voi_interval_size = max - min
00283         bins = np.asarray(range(self.voi_bincount)) * self.voi_interval_size/float(self.voi_bincount)
00284         #print 'bins',bins
00285         hist = stats.histogram2(pts[2],bins) / float(len(pts[2]))
00286         #print 'zhist',hist
00287         #print zip(bins, hist)
00288         self.z_hist = hist
00289         self.z_hist_bins = bins
00290         
00291         slices = self.get_voi_slice_indices()
00292         self.z_hist_slices_indices = slices
00293         
00294         #precalculate spread values:
00295         self.z_hist_spread = []
00296         for indices in self.z_hist_slices_indices:
00297             a = self.processor.pts3d_bound[:,indices]
00298             u, ev12 = gaussian_curvature.spread(a)
00299             self.z_hist_spread += [(ev12[0], ev12[1])]
00300         
00301         #create h,s histograms:
00302         pts_h = []
00303         pts_s = []
00304         #print self.processor.pts3d_bound
00305         n,m = np.shape(np.asarray(self.processor.pts3d_bound))
00306         #print 'm',m,'len(self.processor.pts3d_bound[2,:].A1)',len(self.processor.pts3d_bound[2,:].A1)
00307         for index in range(m):
00308             pts_h.append(float(self.imNP_h[self.processor.map2d[1,index],self.processor.map2d[0,index]]))
00309         for index in range(m):
00310             pts_s.append(float(self.imNP_s[self.processor.map2d[1,index],self.processor.map2d[0,index]]))
00311         pts_i = np.asarray(self.processor.intensities_bound)
00312         #print 'ptsi',pts_i
00313         if np.max(pts_i) > 0:
00314             self.intensity_normalization_factor = 1.0 / float(np.max(pts_i)) * 255
00315         else:
00316             self.intensity_normalization_factor = 1.
00317         #print 'self.intensity_normalization_factor', self.intensity_normalization_factor
00318         #print pts_i
00319         pts_i *= self.intensity_normalization_factor
00320         pts_h = np.asarray(pts_h)
00321         pts_s = np.asarray(pts_s)
00322         self.z_hist_h_hists = []
00323         self.z_hist_s_hists = []
00324         self.z_hist_i_hists = []
00325         
00326         #normalize by maximum slice:
00327         max_count = 0
00328         max_count_index = 0
00329         for count_idx, indices in enumerate(slices):
00330             n = np.shape(indices)
00331             if n[0] > max_count:
00332                 max_count = n[0]
00333                 max_count_index = count_idx
00334         slize_height = (self.voi_interval_size / float(self.voi_bincount))
00335         self.z_hist_height_max =  slize_height * (max_count_index + 0.5)
00336         #print 'max_count', max_count,'index',max_count_index, 'height in max bin', self.z_hist_height_max
00337 
00338         
00339         for indices in slices:
00340             pts_h_slice = pts_h[indices]
00341             pts_s_slice = pts_s[indices]
00342             pts_i_slice = pts_i[indices]
00343             self.hsi_hist_bincount = 5
00344             bins = np.asarray(range(0,self.hsi_hist_bincount))*float(255.0/float(self.hsi_hist_bincount))
00345             #print bins
00346             #todo: smooth with kernel fct
00347             count = float(len(pts_h_slice))
00348             if count == 0: 
00349                 count = 1
00350             hist_h = stats.histogram2(pts_h_slice,bins) / count
00351             self.z_hist_h_hists.append(hist_h)
00352             hist_s = stats.histogram2(pts_s_slice,bins) / count
00353             self.z_hist_s_hists.append(hist_s)
00354             hist_i = stats.histogram2(pts_i_slice,bins) / count
00355             #print 'hist_i', hist_i, pts_i_slice, bins, pts_i
00356             self.z_hist_i_hists.append(hist_i)
00357         
00358         #print 'hh',self.z_hist_h_hists
00359         #print 'sh',self.z_hist_s_hists
00360         #print 'ih',self.z_hist_i_hists
00361         
00362     def get_voi_pts_indices(self, poi, width):
00363         pts = np.asarray(self.processor.pts3d_bound)
00364         #region of interest:
00365         conditions = np.multiply(np.multiply(np.multiply(np.multiply(np.multiply(pts[0] < poi[0]+width/2.0, pts[0] > poi[0]-width/2.0), 
00366                     pts[1] < poi[1]+width/2.0), pts[1] > poi[1]-width/2.0),
00367                     pts[2] < poi[2]+width/2.0), pts[2] > poi[2]-width/2.0)
00368                     
00369         indices = np.where(conditions)[0]
00370         return indices
00371         
00372     def get_voi_slice_indices(self):
00373         
00374         slices = []
00375         last_z = -999999
00376         
00377         for z in self.z_hist_bins:
00378             indices = copy.copy(self.voi_pts_indices)
00379             pts = self.voi_pts   
00380             conditions = np.multiply(pts[2] < z, pts[2] > last_z)
00381             indices = indices[np.where(conditions)[0]]     
00382             slices += [indices]
00383             last_z = z
00384         return slices
00385         
00386     def get_voi_histogram_value(self, point):
00387         z = point[2]
00388         z = int(z*self.voi_bincount / float(self.voi_interval_size))
00389         if z >= 0 and z < self.voi_bincount:
00390             # print z, self.z_hist[z]
00391             return self.z_hist[z]
00392         else:
00393             #print z,0
00394             return 0
00395         
00396     def get_voi_histogram_spread(self, point):
00397         z = point[2]
00398         z = int(z*self.voi_bincount / float(self.voi_interval_size))
00399         if z >= 0 and z < self.voi_bincount:
00400 #            indices = self.z_hist_slices_indices[z]
00401 #            a = self.processor.pts3d_bound[:,indices]
00402 #            u, ev12 = gaussian_curvature.spread(a)
00403 #            if abs(self.z_hist_spread[z][0] - ev12[0]) > 0.0000000001 or abs(self.z_hist_spread[z][1] - ev12[1]) > 0.0000000001:
00404 #                print 'ERROR', self.z_hist_spread[z], '!=', (ev12[0], ev12[1])
00405 #            return ev12[0], ev12[1]
00406             return self.z_hist_spread[z]
00407         else:
00408             #print z,0
00409             return 0, 0
00410         
00411         
00412     def get_voi_hsi_histogram_values(self, point,h ,s, i):
00413         z = point[2]
00414         z = int(z*self.voi_bincount / float(self.voi_interval_size))
00415         if z >= 0 and z < self.voi_bincount:
00416             h_index = int(h * self.hsi_hist_bincount / 255.0)
00417             s_index = int(s * self.hsi_hist_bincount / 255.0)
00418             i *= self.intensity_normalization_factor
00419             i_index = int(i * self.hsi_hist_bincount / 255.0)
00420             
00421             h_hist = self.z_hist_h_hists[z][h_index]
00422             s_hist = self.z_hist_s_hists[z][s_index]
00423             #print 'z',z,'i_index',i_index, i
00424             #print self.z_hist_i_hists, np.shape(self.z_hist_i_hists)
00425             i_hist = self.z_hist_i_hists[z][i_index]
00426             return h_hist, s_hist, i_hist
00427         else:
00428             #print z,0
00429             return 0, 0, 0
00430         
00431     def get_voi_maxcount_height(self):
00432         return self.z_hist_height_max
00433     
00434     


laser_camera_segmentation
Author(s): Martin Schuster, Advisor: Prof. Charlie Kemp, Lab: Healthcare Robotics Lab at Georgia Tech
autogenerated on Wed Nov 27 2013 11:56:44