$search
00001 #! /usr/bin/env python 00002 00003 import roslib 00004 roslib.load_manifest('pr2_interactive_segmentation') 00005 import rospy 00006 import geometry_msgs 00007 00008 00009 import sys, math 00010 00011 # import the necessary things for OpenCV 00012 import cv 00013 import copy 00014 import numpy 00015 import pr2_interactive_segmentation.srv 00016 ############################################################################# 00017 # some "constants" 00018 00019 win_size = 5 00020 MAX_COUNT = 500 00021 00022 ############################################################################# 00023 # some "global" variables 00024 00025 image = None 00026 pt = None 00027 flags = 0 00028 night_mode = False 00029 need_to_init = False 00030 pt_selected = False 00031 00032 00033 col = (numpy.random.randint(256, size = 500 * 3)).reshape(500,3) 00034 00035 00036 ############################################################################# 00037 # the mouse callback 00038 00039 # the callback on the trackbar 00040 def on_mouse (event, x, y, flags, param): 00041 00042 # we will use the global pt 00043 global pt 00044 global pt_select 00045 global pt_selected 00046 00047 if image is None: 00048 # not initialized, so skip 00049 return 00050 00051 if image.origin != 0: 00052 # different origin 00053 y = image.height - y 00054 00055 if event == cv.CV_EVENT_LBUTTONDOWN: 00056 # user has click, so memorize it 00057 pt = (x, y) 00058 pt_select = (x, y) 00059 print "pt_select: ", pt_select 00060 pt_selected = True 00061 00062 class FeatureDists: 00063 feature = (0.0, 0.0) 00064 dists = [] 00065 00066 ############################################################################# 00067 # so, here is the main part of the program 00068 00069 class FeatureTracker: 00070 00071 def __init__(self): 00072 00073 # display a small howto use it 00074 print "Hot keys: \n" \ 00075 "\tq - quit the program\n" \ 00076 "\tr - auto-initialize tracking\n" \ 00077 "\tc - delete all the points\n" \ 00078 "\tn - switch the \"night\" mode on/off\n" \ 00079 "\tSPACE - next frame\n" \ 00080 00081 # first, create the necessary windows 00082 cv.NamedWindow ('LkDemo', cv.CV_WINDOW_NORMAL) 00083 00084 # register the mouse callback 00085 cv.SetMouseCallback ('LkDemo', on_mouse, None) 00086 self.win_size = 15 00087 self.rigid_tracking = False 00088 self.estimateRigidServer = rospy.ServiceProxy("estimateRigid", pr2_interactive_segmentation.srv.estimateRigid()) 00089 self.getDepthServer = rospy.ServiceProxy("getDepthImage", pr2_interactive_segmentation.srv.depthImage()) 00090 self.ROI = [0,412,2190,1424] #roi for prosilica x,y,width,height 00091 self.ROI = [0,0,640,480] #roi for prosilica x,y,width,height 00092 00093 00094 00095 def initFirstFrame(self, frame, mask = None): 00096 print "initFirstFrame" 00097 self.image = cv.CreateImage (cv.GetSize (frame), 8, 3) 00098 # self.image.origin = frame.origin 00099 self.grey = cv.CreateImage (cv.GetSize (frame), 8, 1) 00100 self.prev_grey = cv.CreateImage (cv.GetSize (frame), 8, 1) 00101 self.pyramid = cv.CreateImage (cv.GetSize (frame), 8, 1) 00102 self.prev_pyramid = cv.CreateImage (cv.GetSize (frame), 8, 1) 00103 self.features = [] 00104 #self.feature_object_index = [0] * len(all_features) 00105 roimask = None 00106 if self.ROI != None: 00107 roimask = cv.CreateImage (cv.GetSize (frame), 8, 1) 00108 cv.Zero(roimask) 00109 cv.Rectangle(roimask, (self.ROI[0],self.ROI[1]), (self.ROI[0] + self.ROI[3],self.ROI[1] + self.ROI[3]), 00110 (255,255,255,0),-1) 00111 00112 00113 if self.rigid_tracking: 00114 self.getDepthServer() 00115 00116 image = self.image 00117 grey = self.grey 00118 00119 cv.Copy (frame, image) 00120 00121 # create a grey version of the image 00122 cv.CvtColor (image, grey, cv.CV_BGR2GRAY) 00123 00124 # we want to search all the good points 00125 00126 # create the wanted images 00127 eig = cv.CreateImage (cv.GetSize (grey), 32, 1) 00128 temp = cv.CreateImage (cv.GetSize (grey), 32, 1) 00129 00130 # the default parameters 00131 quality = 0.01 00132 min_distance = 10 00133 print "finding features" 00134 # search the good points 00135 features = cv.GoodFeaturesToTrack ( 00136 grey, eig, temp, 00137 MAX_COUNT, 00138 quality, min_distance, roimask, 3, 0, 0.04) 00139 00140 #filter features through mask 00141 if not mask==None: 00142 print "features", features 00143 features = [f for f in features if not mask[round(f[1]),round(f[0])] ] 00144 # filter(lambda f: not mask[round(f[1])][round(f[0])], features) 00145 00146 00147 00148 print "refining corners" 00149 # refine the corner locations 00150 features = cv.FindCornerSubPix ( 00151 grey, 00152 features, 00153 (win_size, win_size), (-1, -1), 00154 (cv.CV_TERMCRIT_ITER | cv.CV_TERMCRIT_EPS, 20, 0.03)) 00155 00156 00157 print "self.features", self.features 00158 00159 co = cv.RGB(*col[0]) 00160 for the_point in features: 00161 cv.Circle (image, (int(the_point[0]), int(the_point[1])), 7, co, -1, 8, 0) 00162 00163 00164 cv.Copy(grey, self.prev_grey) 00165 self.image = image 00166 00167 feature_object_index = [0] * len(features) 00168 00169 self.features_with_obj_idx = zip(features, feature_object_index) 00170 print self.features_with_obj_idx 00171 00172 return features 00173 00174 00175 00176 def track(self, frame, mask = None): 00177 print "track" 00178 # min_distance_to_pt_select = sys.float_info.max 00179 # point_id = sys.maxint 00180 # 00181 # init_dist_list = [] 00182 # dist_list = [] 00183 # compute_list_diff = False 00184 00185 prev_grey = self.prev_grey 00186 pyramid = self.pyramid 00187 prev_pyramid = self.prev_pyramid 00188 00189 00190 image = self.image 00191 grey = self.grey 00192 00193 cv.Copy (frame, image) 00194 00195 # create a grey version of the image 00196 cv.CvtColor (image, grey, cv.CV_BGR2GRAY) 00197 00198 if night_mode: 00199 # night mode: only display the points 00200 cv.SetZero (image) 00201 00202 00203 features_old, feature_idx_old = zip(*self.features_with_obj_idx) 00204 print "features_old",features_old 00205 # features = self.features 00206 # calculate the optical flow 00207 00208 print "calculating optical flow" 00209 features, status, track_error = cv.CalcOpticalFlowPyrLK ( 00210 prev_grey, grey, prev_pyramid, pyramid, 00211 features_old, 00212 (self.win_size, self.win_size), 3, 00213 (cv.CV_TERMCRIT_ITER|cv.CV_TERMCRIT_EPS, 20, 0.03), 00214 flags) 00215 print "num features: ", sum(status) 00216 print "status: ", status 00217 print "len(status)", len(status) 00218 00219 00220 #filter features through mask 00221 if not mask==None: 00222 features = [f for f in features if not mask[round(f[1]),round(f[0])] ] 00223 00224 00225 # self.features = features 00226 00227 for (f_old, f_new) in zip(features_old, features): 00228 cv.Line(image, (int(f_old[0]), int(f_old[1])), (int(f_new[0]),int(f_new[1])), (0,0,255,0),1) 00229 00230 #draw features 00231 # for (st,p) in zip(status, features): 00232 # if st == 0: 00233 # print" st: ", st, "p: ", p 00234 # cv.Circle (image, (int(p[0]), int(p[1])), 7, (255, 0, 255, 0), -1, 8, 0) 00235 00236 # count = 0; 00237 # for feat in features: 00238 # print "feature coordinates: ", feat, count, type(feat) 00239 # count = count + 1 00240 00241 print type(features) 00242 # all_features = cv.fromarray(numpy.asarray(features, dtype='float32')) #copy.deepcopy(features) 00243 # all_features_old = cv.fromarray(numpy.asarray(features_old, dtype='float32')) #copy.deepcopy(features_old) 00244 # H = cv.CreateMat(3,3,cv.CV_32F) 00245 00246 00247 00248 00249 00250 feature_sets_new = [] 00251 feature_object_index_new = [0] * len(features) 00252 00253 object_count = max(feature_idx_old) + 1 00254 00255 for obj_idx in range(object_count): 00256 feature_group_new = [f for (f, idx) in zip(features, feature_idx_old) if idx == obj_idx] 00257 00258 if len(feature_group_new) == 0: 00259 print "empty index !!!!!!!!!!!!! ", obj_idx 00260 continue 00261 00262 feature_group_old = [f for (f, idx) in self.features_with_obj_idx if idx == obj_idx] 00263 00264 00265 00266 idx_group_new = [obj_idx] * len(feature_group_new) 00267 00268 print "feature_group_new", feature_group_new 00269 00270 all_features = cv.fromarray(numpy.asarray(feature_group_new, dtype='float32')) #copy.deepcopy(features) 00271 all_features_old = cv.fromarray(numpy.asarray(feature_group_old, dtype='float32')) #copy.deepcopy(features_old) 00272 H = cv.CreateMat(3,3,cv.CV_32F) 00273 00274 new_object_count = 0 00275 #this code below is horrible 00276 while all_features.height > 4: 00277 00278 status = cv.CreateMat(1,all_features.height,cv.CV_8U) 00279 if self.rigid_tracking == True: 00280 print "using Rigid Motion Estimation" 00281 status, success = self.estimateRigidTransformationRANSAC(all_features_old, all_features) 00282 status = [status] 00283 statusH = cv.CreateMat(1,all_features.height,cv.CV_8U) 00284 cv.FindHomography(all_features,all_features_old,H,cv.CV_RANSAC, 5.0 , status = statusH) 00285 else: 00286 print "using Homography" 00287 cv.FindHomography(all_features,all_features_old,H,cv.CV_RANSAC, 5.0 , status = status) 00288 new_object = [] 00289 j = 0 00290 print "status", numpy.asarray(status) 00291 # print "statusH", numpy.asarray(statusH) 00292 00293 all_features_np = numpy.asarray(all_features) 00294 all_features_old_np = numpy.asarray(all_features_old) 00295 00296 status_np = numpy.asarray(status) 00297 print "len(status_np[0])",len(status_np[0]) 00298 00299 for i in range(len(status_np[0])): 00300 if status_np[0,i]: 00301 # print 'adding' 00302 new_object.append(tuple(all_features_np[j,:])) 00303 all_features_np = numpy.delete( all_features_np, j ,0) 00304 all_features_old_np = numpy.delete( all_features_old_np, j ,0) 00305 else: 00306 j += 1 00307 if len(new_object) == 0: 00308 print "should never get here" 00309 break 00310 00311 # print "new_object",new_object 00312 00313 if new_object_count == 0: #we are still in the predominat osiiotn 00314 new_idx = obj_idx 00315 else: 00316 new_idx = object_count + new_object_count 00317 00318 feature_sets_new.extend(zip(new_object, [new_idx] * len(new_object)) ) 00319 00320 print "found new object numero new_idx",new_idx 00321 # print "feature_sets_new",feature_sets_new 00322 00323 new_object_count += 1 00324 00325 00326 all_features = cv.fromarray(all_features_np) 00327 all_features_old = cv.fromarray(all_features_old_np) 00328 00329 00330 co = cv.RGB(*col[new_idx]) 00331 print "co",co 00332 for the_point in new_object: 00333 cv.Circle (image, (int(the_point[0]), int(the_point[1])), 7,co, -1, 8, 0) 00334 00335 # if len(all_features_np) > 0: 00336 # print "unassigned features left" 00337 # new_object_count += 1 00338 # new_object = [ (f1,f2) for ( 00339 # feature_sets_new.extend(zip(new_object, [new_object_count] * len(new_object)) ) 00340 # co = cv.RGB(*col[new_object_count]) 00341 # for the_point in new_object: 00342 # cv.Circle (image, (int(the_point[0]), int(the_point[1])), 10,co, -1, 8, 0) 00343 00344 00345 00346 00347 00348 00349 00350 00351 00352 00353 00354 00355 00356 00357 # while all_features.height >= 4: 00358 # status = cv.CreateMat(1,all_features.height,cv.CV_8U) 00359 # cv.FindHomography(all_features,all_features_old,H,cv.CV_RANSAC, 3.0 , status = status) 00360 # new_object = [] 00361 # j = 0 00362 # 00363 # all_features_np = numpy.asarray(all_features) 00364 # all_features_old_np = numpy.asarray(all_features_old) 00365 # 00366 # for i in range(status.width): 00367 # if status[0,i]: 00368 # new_object.append(all_features_np[j,:]) 00369 # all_features_np = numpy.delete( all_features_np, j ,0) 00370 # all_features_old_np = numpy.delete( all_features_old_np, j ,0) 00371 # else: 00372 # j += 1 00373 # if len(new_object) == 0: 00374 # break 00375 # feature_sets_new.append(new_object) 00376 # 00377 # all_features = cv.fromarray(all_features_np) 00378 # all_features_old = cv.fromarray(all_features_old_np) 00379 # 00380 # col = (numpy.random.randint(256),numpy.random.randint(256),numpy.random.randint(256),0) 00381 # 00382 # for the_point in new_object: 00383 # cv.Circle (image, (int(the_point[0]), int(the_point[1])), 3, col, -1, 8, 0) 00384 00385 # cv.ShowImage('LkDemo', image) 00386 # cv.WaitKey() 00387 00388 00389 00390 # swapping 00391 print "Swapping" 00392 self.features_with_obj_idx = feature_sets_new 00393 self.prev_grey, self.grey = grey, prev_grey 00394 self.prev_pyramid, self.pyramid = pyramid, prev_pyramid 00395 need_to_init = False 00396 self.image = image 00397 return (features, feature_sets_new) 00398 00399 # we can now display the image 00400 #def display(feature_tracker): 00401 00402 00403 def estimateRigidTransformationRANSAC(self, all_features_old, all_features ): 00404 00405 00406 req = pr2_interactive_segmentation.srv.estimateRigidRequest() 00407 # old_points = [geometry_msgs.msg.Point(f[0], f[1], 0.0) for f in all_features_old] 00408 # new_points = [geometry_msgs.msg.Point(f[0], f[1], 0.0) for f in all_features] 00409 new_points = [] 00410 old_points = [] 00411 for i in range(all_features.height): 00412 new_points.append(geometry_msgs.msg.Point(all_features[i,0], all_features[i,1], 0.0)) 00413 00414 for j in range(all_features_old.height): 00415 old_points.append(geometry_msgs.msg.Point(all_features_old[j,0], all_features_old[j,1], 0.0)) 00416 00417 req.features_old = old_points 00418 req.features_new = new_points 00419 00420 00421 res = self.estimateRigidServer(req) 00422 return res.inliers, res.success 00423 00424 00425 00426 00427 def trackRigid(self, frame, mask = None): 00428 print "track" 00429 # min_distance_to_pt_select = sys.float_info.max 00430 # point_id = sys.maxint 00431 # 00432 # init_dist_list = [] 00433 # dist_list = [] 00434 # compute_list_diff = False 00435 00436 prev_grey = self.prev_grey 00437 pyramid = self.pyramid 00438 prev_pyramid = self.prev_pyramid 00439 00440 00441 image = self.image 00442 grey = self.grey 00443 00444 cv.Copy (frame, image) 00445 00446 # create a grey version of the image 00447 cv.CvtColor (image, grey, cv.CV_BGR2GRAY) 00448 00449 if night_mode: 00450 # night mode: only display the points 00451 cv.SetZero (image) 00452 00453 00454 features_old, feature_idx_old = zip(*self.features_with_obj_idx) 00455 print "features_old",features_old 00456 # features = self.features 00457 # calculate the optical flow 00458 00459 print "calculating optical flow" 00460 features, status, track_error = cv.CalcOpticalFlowPyrLK ( 00461 prev_grey, grey, prev_pyramid, pyramid, 00462 features_old, 00463 (self.win_size, self.win_size), 3, 00464 (cv.CV_TERMCRIT_ITER|cv.CV_TERMCRIT_EPS, 20, 0.03), 00465 flags) 00466 print "num features: ", sum(status), "frame: ", fc 00467 print "status: ", status 00468 print "len(status)", len(status) 00469 00470 00471 #filter features through mask 00472 if not mask==None: 00473 features = [f for f in features if not mask[round(f[1]),round(f[0])] ] 00474 00475 00476 # self.features = features 00477 00478 for (f_old, f_new) in zip(features_old, features): 00479 cv.Line(image, (int(f_old[0]), int(f_old[1])), (int(f_new[0]),int(f_new[1])), (0,0,255,0),1) 00480 00481 #draw features 00482 # for (st,p) in zip(status, features): 00483 # if st == 0: 00484 # print" st: ", st, "p: ", p 00485 # cv.Circle (image, (int(p[0]), int(p[1])), 7, (255, 0, 255, 0), -1, 8, 0) 00486 00487 # count = 0; 00488 # for feat in features: 00489 # print "feature coordinates: ", feat, count, type(feat) 00490 # count = count + 1 00491 00492 print type(features) 00493 # all_features = cv.fromarray(numpy.asarray(features, dtype='float32')) #copy.deepcopy(features) 00494 # all_features_old = cv.fromarray(numpy.asarray(features_old, dtype='float32')) #copy.deepcopy(features_old) 00495 # H = cv.CreateMat(3,3,cv.CV_32F) 00496 00497 00498 00499 00500 00501 feature_sets_new = [] 00502 feature_object_index_new = [0] * len(features) 00503 00504 object_count = max(feature_idx_old) + 1 00505 00506 for obj_idx in range(object_count): 00507 feature_group_new = [f for (f, idx) in zip(features, feature_idx_old) if idx == obj_idx] 00508 00509 if len(feature_group_new) == 0: 00510 print "empty index !!!!!!!!!!!!! ", obj_idx 00511 continue 00512 00513 feature_group_old = [f for (f, idx) in self.features_with_obj_idx if idx == obj_idx] 00514 00515 00516 00517 idx_group_new = [obj_idx] * len(feature_group_new) 00518 00519 print "feature_group_new", feature_group_new 00520 00521 all_features = cv.fromarray(numpy.asarray(feature_group_new, dtype='float32')) #copy.deepcopy(features) 00522 all_features_old = cv.fromarray(numpy.asarray(feature_group_old, dtype='float32')) #copy.deepcopy(features_old) 00523 H = cv.CreateMat(3,3,cv.CV_32F) 00524 00525 new_object_count = 0 00526 #this code below is horrible 00527 while all_features.height >= 3: 00528 00529 status = cv.CreateMat(1,all_features.height,cv.CV_8U) 00530 status = self.estimateRigidTransformationRANSAC(all_features_old, all_features_new) 00531 new_object = [] 00532 j = 0 00533 print "status", numpy.asarray(status) 00534 00535 all_features_np = numpy.asarray(all_features) 00536 all_features_old_np = numpy.asarray(all_features_old) 00537 00538 status_np = numpy.asarray(status) 00539 print "len(status_np[0])",len(status_np[0]) 00540 00541 for i in range(len(status_np[0])): 00542 if status_np[0,i]: 00543 # print 'adding' 00544 new_object.append(tuple(all_features_np[j,:])) 00545 all_features_np = numpy.delete( all_features_np, j ,0) 00546 all_features_old_np = numpy.delete( all_features_old_np, j ,0) 00547 else: 00548 j += 1 00549 if len(new_object) == 0: 00550 print "should never get here" 00551 break 00552 00553 # print "new_object",new_object 00554 00555 if new_object_count == 0: #we are still in the predominat osiiotn 00556 new_idx = obj_idx 00557 else: 00558 new_idx = object_count + new_object_count 00559 00560 feature_sets_new.extend(zip(new_object, [new_idx] * len(new_object)) ) 00561 00562 print "found new object numero new_idx",new_idx 00563 # print "feature_sets_new",feature_sets_new 00564 00565 new_object_count += 1 00566 00567 00568 all_features = cv.fromarray(all_features_np) 00569 all_features_old = cv.fromarray(all_features_old_np) 00570 00571 00572 co = cv.RGB(*col[new_idx]) 00573 print "co",co 00574 for the_point in new_object: 00575 cv.Circle (image, (int(the_point[0]), int(the_point[1])), 3,co, -1, 8, 0) 00576 00577 00578 00579 00580 00581 00582 00583 00584 00585 00586 00587 00588 00589 00590 # while all_features.height >= 4: 00591 # status = cv.CreateMat(1,all_features.height,cv.CV_8U) 00592 # cv.FindHomography(all_features,all_features_old,H,cv.CV_RANSAC, 3.0 , status = status) 00593 # new_object = [] 00594 # j = 0 00595 # 00596 # all_features_np = numpy.asarray(all_features) 00597 # all_features_old_np = numpy.asarray(all_features_old) 00598 # 00599 # for i in range(status.width): 00600 # if status[0,i]: 00601 # new_object.append(all_features_np[j,:]) 00602 # all_features_np = numpy.delete( all_features_np, j ,0) 00603 # all_features_old_np = numpy.delete( all_features_old_np, j ,0) 00604 # else: 00605 # j += 1 00606 # if len(new_object) == 0: 00607 # break 00608 # feature_sets_new.append(new_object) 00609 # 00610 # all_features = cv.fromarray(all_features_np) 00611 # all_features_old = cv.fromarray(all_features_old_np) 00612 # 00613 # col = (numpy.random.randint(256),numpy.random.randint(256),numpy.random.randint(256),0) 00614 # 00615 # for the_point in new_object: 00616 # cv.Circle (image, (int(the_point[0]), int(the_point[1])), 3, col, -1, 8, 0) 00617 00618 # cv.ShowImage('LkDemo', image) 00619 # cv.WaitKey() 00620 00621 00622 00623 # swapping 00624 print "Swapping" 00625 self.features_with_obj_idx = feature_sets_new 00626 self.prev_grey, self.grey = grey, prev_grey 00627 self.prev_pyramid, self.pyramid = pyramid, prev_pyramid 00628 need_to_init = False 00629 self.image = image 00630 return (features, feature_sets_new) 00631 00632 00633 if __name__ == '__main__': 00634 00635 frames = sys.argv[1:] 00636 if frames == []: 00637 print "usage lkdemo.py <image files>" 00638 sys.exit(1) 00639 00640 ft = FeatureTracker() 00641 #counters 00642 fc = 0 00643 is_inited = False 00644 00645 while 1: 00646 print "waiting for key press" 00647 # handle events 00648 c = cv.WaitKey (0)%0x100 00649 00650 print "c: ", c%0x100 00651 if c == 113: 00652 # user has press the q key, so exit 00653 break 00654 00655 #all the images are stored here 00656 print fc, len(frames) 00657 if fc == len(frames)-1: 00658 break 00659 00660 # processing depending on the character 00661 if 32 <= c and c < 128: 00662 cc = chr(c).lower() 00663 if cc == 'r': 00664 need_to_init = True 00665 ft.initFirstFrame(cv.LoadImage(frames[fc])) 00666 is_inited = True 00667 fc = (fc + 10) % len(frames) 00668 elif cc == 'c': 00669 features = [] 00670 elif cc == 'n': 00671 night_mode = not night_mode 00672 elif cc == ' ': 00673 fc = (fc + 1) % len(frames) 00674 if is_inited: 00675 ft.track(cv.LoadImage(frames[fc])) 00676 00677 00678 if is_inited: 00679 cv.ShowImage ('LkDemo', ft.image) 00680 else: 00681 cv.ShowImage('LkDemo', cv.LoadImage(frames[fc]) ) 00682 # cv.WaitKey() 00683