00001 import numpy as np
00002
00003 import time
00004 import pylab
00005 from scipy import ndimage
00006 import cv2
00007 import os,sys
00008
00009 import config_feats
00010 import cPickle
00011 from shogun.Classifier import LibSVM
00012 from shogun.Features import RealFeatures
00013
00014 from iri_bow_object_detector.bow_detector_utils import save_data_for_log
00015 import ehbsw
00016
00017
00018
00019
00020 def local_maxima(array, min_distance = 1, periodic=False,
00021 edges_allowed=True):
00022 """Find all local maxima of the array, separated by at least
00023 min_distance.
00024 adapted from = http://old.nabble.com/Finding-local-minima-of-greater-than-a-given-depth-td18988309.html"""
00025 array = np.asarray(array)
00026 cval = 0
00027 if periodic:
00028 mode = 'wrap'
00029 elif edges_allowed:
00030 mode = 'nearest'
00031 else:
00032 mode = 'constant'
00033 cval = array.max()+1
00034 nbhood=ndimage.morphology.generate_binary_structure(len(array.shape),2)
00035 maxima = array == ndimage.maximum_filter(array, footprint=nbhood, mode=mode, cval=cval)
00036 background = (array==0)
00037 eroded_background = ndimage.morphology.binary_erosion(
00038 background, structure=nbhood, border_value=1)
00039 maxima = maxima - eroded_background
00040 maxpy, maxpx = np.where(maxima)
00041 max_points = [(maxpy[i],maxpx[i]) for i in range(len(maxpy))]
00042 if not type(max_points)==list:
00043 max_points=[max_points]
00044 return max_points
00045
00046
00047 def fit_window(heat_map, margin=10, min_dist_maxima=5):
00048
00049
00050 heat_map[np.isnan(heat_map)]=0
00051
00052 heat_map=ndimage.gaussian_filter(heat_map, 5)
00053
00054
00055 if margin>0:
00056 heat_map[:,:margin]=0
00057 heat_map[:,-margin:]=0
00058 heat_map[:margin,:]=0
00059 heat_map[-margin:,:]=0
00060
00061 ind = local_maxima(heat_map, min_distance=min_dist_maxima)
00062
00063 if len(ind)>0:
00064 ind = np.array(ind).astype('int64')
00065
00066
00067 hw=145/2
00068 hh=140/2
00069 win = [(x-hw, y-hh, x+hw, y+hh) for y,x in ind]
00070
00071 else:
00072 win = []
00073 return ind, heat_map[ind[:,0],ind[:,1]], win
00074
00075
00076
00077
00078 def prepare_feats(desc, l=2, as_shogun=False):
00079 if l==2: desc = np.sqrt(desc)
00080
00081 norms = np.apply_along_axis(np.linalg.norm, 0, desc[:-1,:], l)
00082
00083 np.seterr(divide='ignore', invalid='ignore')
00084
00085 desc[:-1,:]=desc[:-1,:]/norms
00086 np.seterr(divide='warn', invalid='warn')
00087
00088 if l==1: desc=desc[:-1,:]
00089
00090 desc[np.isnan(desc)]=0
00091 if as_shogun:
00092 desc=RealFeatures(desc.astype('float'))
00093 return desc
00094
00095
00096 def gen_windows_SWIG_wrapper(xstep=10, ystep=10, widthmin=100,
00097 widthmax=170, widthstep=10, whratios=[0.5, 1, 1.5],
00098 xmax=640, ymax=480):
00099
00100 maxboxes = len(whratios) * ((widthmax-widthmin)/widthstep) * (xmax/xstep) * (ymax/ystep)
00101 bboxes, used = ehbsw.gen_windows(maxboxes*4, xstep, ystep, widthmin, widthmax, widthstep, whratios, xmax, ymax)
00102 bboxes = bboxes[:used,:]
00103 return bboxes
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 def splash_as_box(hmap, x1, y1, x2, y2, score, normit):
00119 hmap[y1:y2][:,x1:x2] += score * np.ones((y2-y1, x2-x1))
00120 normit[y1:y2][:,x1:x2] += np.ones((y2-y1, x2-x1))
00121
00122 def create_robust_histograms(vws, bboxes, NUM_VWORDS):
00123 hs=create_histograms_SWIG_wrapper(vws, bboxes, NUM_VWORDS)
00124 valid=hs.sum(0)!=0
00125 hs=hs[:,valid]
00126 valid=list(valid.nonzero()[0])
00127 bboxes=[bboxes[i] for i in valid]
00128 return hs,bboxes
00129
00130 def create_histograms_SWIG_wrapper(vws, bboxes, NUM_VWORDS):
00131 nh = len(bboxes)
00132 mh = NUM_VWORDS[0]
00133
00134 bboxes = np.array(bboxes)
00135 vws = np.array(vws[0])
00136
00137 h = ehbsw.create_histograms(nh*mh, nh, mh, vws.astype(np.int32), bboxes.astype(np.float32))
00138 h.shape = (nh, mh)
00139 h=np.hstack((h,np.ones((h.shape[0],1))))
00140 return h.T
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 def recode_win(w,xs,ys,xo,yo):
00162 x1,y1,x2,y2=w
00163 cx = xo + (x2+x1)/2
00164 cy = yo + (y2+y1)/2
00165 w = xs * (x2-x1)/2
00166 h = ys * (y2-y1)/2
00167 nx1 = int(round(cx-w/2))
00168 ny1 = int(round(cy-h/2))
00169 nx2 = int(round(cx+w/2))
00170 ny2 = int(round(cy+h/2))
00171 return (nx1,ny1,nx2,ny2)
00172
00173 def local_search_wins(win):
00174
00175 shape_factors=[(1,1.25), (1,1), (1.25,1),
00176 (1.25, 1.25), (1.4,1), (1, 1.4), (1.4, 1.4)]
00177
00178 position_factors=[(0,0),
00179 (-32,0), (-24,0), (-16,0), (32,0),
00180 (24,0), (16,0), (0,-32), (0,-24),
00181 (0,-16), (0,32), (0,24), (0,16),
00182 (-8,-8), (-8,8), (8,-8), (8,8),
00183 (-16,-16), (-16,16), (16,-16), (16,16),
00184 (-24,-24), (-24,24), (24,-24), (24,24)]
00185 wins2=[]
00186
00187 for w in win:
00188 wins2.append([])
00189 for xs,ys in shape_factors:
00190 for xo,yo in position_factors:
00191 wins2[-1].append(recode_win(w,xs,ys,xo,yo))
00192 return wins2
00193
00194
00195 def detect_boxes(w, non_linear_svm_file, ima, mask, conf, vws):
00196 gt_bboxes = None
00197 bias = None
00198 width=mask.shape[1]
00199 height=mask.shape[0]
00200
00201 iclass = 'polo_collar'
00202 NUM_VWORDS = conf.num_vwords
00203
00204 if 0:
00205 start=time.time()
00206 bboxes = gen_windows_SWIG_wrapper(xstep=20, ystep=20, widthstep=20, xmax=width, ymax=height)
00207 hs,bboxes = create_robust_histograms(vws, bboxes, NUM_VWORDS)
00208 hs=prepare_feats(hs,2)
00209 scores = 1/(1+np.exp(-np.dot(w,hs)))
00210
00211 for i,b in enumerate(bboxes):
00212 if conf.use_mask:
00213 if mask[int(round((b[3]+b[1])/2)), int(round((b[2]+b[0])/2))]<=0:
00214 scores[i]=0
00215
00216 heat_map = np.zeros((height,width))
00217 normit = np.zeros((height,width))
00218 for p, s in zip(bboxes, scores):
00219 (x1, y1, x2, y2) = p
00220 splash_as_box(heat_map, x1, y1, x2, y2, s, normit)
00221
00222 np.seterr(divide='ignore', invalid='ignore')
00223 heat_map=np.divide(heat_map,normit)
00224 np.seterr(divide='warn', invalid='warn')
00225
00226 if conf.verb >= 1: print "TIMESTAMP: done gen_windows ", time.time()-start
00227
00228 if 1:
00229 start=time.time()
00230 vw_image = np.zeros((height, width)).astype('int32')
00231
00232 for geovw in vws[0]:
00233 x, y, vw = geovw
00234 vw_image[y,x]=vw+1
00235
00236 scores=ehbsw.ehbsw_pownorm(width*height, vw_image, 55, w.astype('float32'))
00237 scores.shape=(height,width)
00238
00239 if conf.verb >= 1: print "TIMESTAMP: done EHBSW gen_windows ", time.time()-start
00240
00241 scores=scores*(mask/255.0)
00242 save_data_for_log(scores)
00243 heat_map = scores
00244
00245
00246 if conf.merge_windows==True:
00247 ind, prob, win = fit_window(heat_map)
00248 else:
00249 prob=scores
00250 win=bboxes
00251
00252 if conf.refine_nonlinear and conf.merge_windows:
00253
00254 start=time.time()
00255 win2=local_search_wins(win)
00256 hsbbox2=[create_robust_histograms(vws, w2, NUM_VWORDS) for w2 in win2]
00257 if conf.verb >= 2: print time.time()-start, "TIMESTAMP: create_robust_histograms non linear."
00258
00259 start=time.time()
00260
00261 if not os.path.exists(non_linear_svm_file):
00262 print "File not found:", non_linear_svm_file
00263 sys.exit(-1)
00264 pf=open(non_linear_svm_file, 'rb')
00265 svm = cPickle.load(pf)
00266 chi2_width = cPickle.load(pf)
00267 AA = cPickle.load(pf)
00268 BB = cPickle.load(pf)
00269 pf.close()
00270
00271
00272 win=[]
00273 prob=[]
00274 for hs2, bboxes2 in hsbbox2:
00275 scores2 = svm.apply(prepare_feats(hs2,1,as_shogun=True)).get_labels()
00276 scores2 = scores2*AA+BB
00277 sel_neg = (scores2<0).nonzero()
00278 sel_pos = (scores2>=0).nonzero()
00279 scores2[sel_neg] = 1.0/(1.0+np.exp(scores2[sel_neg]))
00280 scores2[sel_pos] = np.exp(-scores2[sel_pos])/(1.0+np.exp(-scores2[sel_pos]))
00281
00282 orderscores2 = [(ii,s) for ii,s in enumerate(scores2)]
00283 orderscores2.sort(key=lambda x: x[1], reverse=True)
00284 win.append(bboxes2[orderscores2[0][0]])
00285 prob.append(orderscores2[0][1])
00286 if conf.single_pred==True:
00287 i=np.argmax(prob)
00288 win=[win[i]]
00289 prob=[prob[i]]
00290 if conf.verb >= 2: print time.time()-start, "TIMESTAMP: non linear svm."
00291
00292
00293
00294
00295
00296 win2=[]
00297 prob2=[]
00298 for w,p in zip(win,prob):
00299 if ((w[3]<height and w[1]>=0 and w[2]<width and w[0]>=0)
00300 and mask[int(round((w[3]+w[1])/2)), int(round((w[2]+w[0])/2))]>0):
00301 win2.append(w)
00302 prob2.append(p)
00303
00304 win=win2
00305 prob=prob2
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 return (win, prob)
00321
00322
00323
00324
00325