hist_analyzer_final.py
Go to the documentation of this file.
00001 #!/usr/bin/env python  
00002 import roslib
00003 roslib.load_manifest('pr2_playpen')
00004 import rospy
00005 from pr2_playpen.srv import * #this is for Train and Check
00006 import sys
00007 import cv
00008 import numpy as np
00009 import cPickle
00010 import glob
00011 from collections import deque
00012 from std_msgs.msg import String
00013 from sensor_msgs.msg import Image
00014 from cv_bridge import CvBridge, CvBridgeError
00015 
00016 class HistAnalyzer:
00017 
00018     def __init__(self, background_noise, mask, topic=None): #'/playpen_kinect/rgb/image_color'):
00019         rospy.init_node('playpen_color_results')
00020         if topic != None:
00021             rospy.Subscriber(topic, Image, self.get_img)
00022         self.check = rospy.Service("playpen_check_success_hist", Check, self.serv_success)
00023         self.train_empty = rospy.Service("playpen_train_hist", Train, self.serv_train)
00024         self.background_noise = background_noise
00025         self.h_bins = 30
00026         self.s_bins = 32
00027         self.h_ranges = [0, 180]
00028         self.s_ranges = [0, 255]
00029         self.ranges = [self.h_ranges, self.s_ranges]
00030         self.hist = None
00031         self.mask = mask
00032         self.avg_noise = None
00033         self.online_img = None
00034         self.bridge = CvBridge()
00035         size = cv.GetSize(background_noise[0])
00036         self.IavgF = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00037         self.IdiffF = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00038         self.IprevF = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00039         self.IhiF = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00040         self.IlowF = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00041         self.Ilow1 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00042         self.Ilow2 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00043         self.Ilow3 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00044         self.Ihi1 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00045         self.Ihi2 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00046         self.Ihi3 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00047         cv.Zero(self.IavgF)
00048         cv.Zero(self.IdiffF)
00049         cv.Zero(self.IprevF)
00050         cv.Zero(self.IhiF)
00051         cv.Zero(self.IlowF)
00052         self.Icount = 0.00001
00053         self.Iscratch = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00054         self.Iscratch2 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00055         self.Igray1 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00056         self.Igray2 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00057         self.Igray3 = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
00058         self.Imaskt = cv.CreateImage(size, cv.IPL_DEPTH_8U, 1)
00059         cv.Zero(self.Iscratch)
00060         cv.Zero(self.Iscratch2)
00061         self.first = 1
00062 
00063     def accumulateBackground(self, img):
00064         cv.CvtScale(img, self.Iscratch, 1, 0)
00065         if (not self.first):
00066             cv.Acc(self.Iscratch, self.IavgF)
00067             cv.AbsDiff(self.Iscratch, self.IprevF, self.Iscratch2)
00068             cv.Acc(self.Iscratch2, self.IdiffF)
00069             self.Icount += 1.0
00070         self.first = 0
00071         cv.Copy(self.Iscratch, self.IprevF)
00072 
00073     def setHighThresh(self, thresh):
00074         cv.ConvertScale(self.IdiffF, self.Iscratch, thresh)
00075         cv.Add(self.Iscratch, self.IavgF, self.IhiF)
00076         #cv.Split(self.IhiF, self.Ihi1, self.Ihi2, self.Ihi3, None)
00077 
00078     def setLowThresh(self, thresh):
00079         cv.ConvertScale(self.IdiffF, self.Iscratch, thresh)
00080         cv.Sub(self.IavgF, self.Iscratch, self.IlowF)
00081         #cv.Split(self.IlowF, self.Ilow1, self.Ilow2, self.Ilow3, None)
00082 
00083 
00084     def createModelsfromStats(self):
00085         cv.ConvertScale(self.IavgF, self.IavgF, float(1.0/self.Icount))
00086         cv.ConvertScale(self.IdiffF, self.IdiffF, float(1.0/self.Icount))
00087 
00088         cv.AddS(self.IdiffF, cv.Scalar(1.0, 1.0, 1.0), self.IdiffF)
00089         self.setHighThresh(200.0)
00090         self.setLowThresh(200.0)
00091 
00092     def backgroundDiff(self, img, Imask):
00093         #cv.Zero(self.Imaskt)
00094         cv.Zero(Imask)
00095         cv.CvtScale(img, self.Iscratch, 1, 0)
00096         cv.InRange(self.Iscratch, self.IlowF, self.IhiF, Imask)
00097         cv.SubRS(Imask, 255, Imask)
00098         cv.MorphologyEx(Imask, Imask, None, None, cv.CV_MOP_OPEN, 1)
00099         cv.MorphologyEx(Imask, Imask, None, None, cv.CV_MOP_CLOSE, 2)    
00100 
00101         #######This stuff was for when it was 3 channel model, now only 1
00102         #######for backprojection
00103         #cv.Split(self.Iscratch, self.Igray1, self.Igray2, self.Igray3, None)
00104         #cv.InRange(self.Igray1, self.Ilow1, self.Ihi1, Imask)
00105 
00106         # cv.InRange(self.Igray2, self.Ilow2, self.Ihi2, self.Imaskt)
00107         # cv.Or(Imask, self.Imaskt, Imask)
00108 
00109         # cv.InRange(self.Igray3, self.Ilow3, self.Ihi3, self.Imaskt)
00110         # cv.Or(Imask, self.Imaskt, Imask)
00111 
00112         # cv.SubRS(Imask, 255, Imask)
00113         #cv.SaveImage('/home/mkillpack/Desktop/mask.png', Imask)
00114         #cv.Erode(Imask, Imask)
00115 
00116         return Imask
00117 
00118 
00119     def get_img(self, msg):
00120         try:
00121             self.online_img = self.bridge.imgmsg_to_cv(msg, "bgr8")
00122         except CvBridgeError, e:
00123             print e
00124 
00125     def serv_train(self, req):
00126         if req.expected== 'table':
00127             print 'great'
00128         num_samples = 0
00129         return TrainResponse(num_samples)
00130 
00131 
00132     def serv_success(self, req):
00133         result = "none"
00134         return CheckResponse(result)
00135 
00136 
00137     def calc_hist(self):
00138         self.hist = cv.CreateHist([self.h_bins, self.s_bins], cv.CV_HIST_ARRAY, self.ranges, 1)
00139         hsv = cv.CreateImage(cv.GetSize(self.background_noise[0]), 8, 3)
00140         h_plane = cv.CreateMat(self.background_noise[0].height, self.background_noise[0].width, cv.CV_8UC1)
00141         s_plane = cv.CreateMat(self.background_noise[0].height, self.background_noise[0].width, cv.CV_8UC1)
00142         for i in xrange(len(self.background_noise)):
00143             cv.CvtColor(self.background_noise[i], hsv, cv.CV_BGR2HSV)
00144             cv.Split(hsv, h_plane, s_plane, None, None)            
00145             planes = [h_plane, s_plane]#, s_plane, v_plane]
00146             cv.CalcHist([cv.GetImage(i) for i in planes], self.hist, True, self.mask)            
00147         #cv.NormalizeHist(self.hist, 10000.0)
00148 
00149     def check_for_hist(self):
00150         if self.hist == None:
00151             print "YOU CAN'T CALCULATE NOISE WITHOUT HIST MODEL OF TABLETOP"
00152             exit
00153 
00154     def calc_stats(self):
00155         self.check_for_hist()
00156         for i in xrange(len(self.background_noise)):
00157             back_proj_img1, hist1 = self.back_project_hs(self.background_noise[i])
00158 
00159             self.accumulateBackground(back_proj_img1)
00160 
00161             #cv.ShowImage("img1_back", back_proj_img1)
00162             #cv.WaitKey(33)
00163         self.createModelsfromStats()
00164 
00165         #cv.NamedWindow("Ilow", cv.CV_WINDOW_AUTOSIZE)
00166         #cv.NamedWindow("Ihi", cv.CV_WINDOW_AUTOSIZE)
00167         #cv.NamedWindow("IavgF", cv.CV_WINDOW_AUTOSIZE)
00168 
00169         #cv.ShowImage("Ihi", self.IhiF)
00170         #cv.ShowImage("Ilow", self.IlowF)
00171         #cv.ShowImage("IavgF", self.IavgF)
00172         #cv.WaitKey(33)
00173 
00174     def compare_imgs(self, img1, img2):
00175         back_proj_img, hist1 = self.back_project_hs(img1)
00176         back_proj_img2, hist2 = self.back_project_hs(img2)
00177 
00178         scratch = cv.CreateImage(cv.GetSize(back_proj_img2), 8, 1)
00179         scratch2 = cv.CreateImage(cv.GetSize(back_proj_img2), 8, 1)
00180         cv.Zero(scratch)
00181         cv.Zero(scratch2)
00182 
00183         #cv.Sub(back_proj_img, back_proj_img2, scratch2) #opposite noise, but excludes object 
00184         cv.Sub(back_proj_img2, back_proj_img, scratch2) #noise, but includes object if failed, 
00185         cv.Sub(scratch2, ha.avg_noise, scratch)
00186         
00187         return scratch
00188         
00189 
00190     def back_project_hs(self, img):
00191         self.check_for_hist()
00192         hsv = cv.CreateImage(cv.GetSize(img), 8, 3)
00193         scratch = cv.CreateImage(cv.GetSize(img), 8, 1)
00194         back_proj_img = cv.CreateImage(cv.GetSize(img), 8, 1)
00195         cv.CvtColor(img, hsv, cv.CV_BGR2HSV)
00196         h_plane_img = cv.CreateImage(cv.GetSize(img), 8, 1)
00197         s_plane_img = cv.CreateImage(cv.GetSize(img), 8, 1)
00198         cv.Split(hsv, h_plane_img, s_plane_img, None, None)            
00199         cv.CalcBackProject([h_plane_img, s_plane_img], back_proj_img, self.hist)
00200         #cv.Threshold(back_proj_img, back_proj_img, 200, 255, cv.CV_THRESH_BINARY)
00201         #cv.MorphologyEx(back_proj_img, back_proj_img, None, None, cv.CV_MOP_OPEN, 1)
00202         #cv.MorphologyEx(back_proj_img, back_proj_img, None, None, cv.CV_MOP_CLOSE, 2)    
00203         return back_proj_img, self.hist
00204 
00205 
00206 if __name__ == '__main__':
00207 
00208     import optparse
00209     p = optparse.OptionParser()
00210 
00211     p.add_option('--batch', action='store', dest='batch_folder', type="string",
00212                  default=None, help='check for success or failure in batch mode with already stored data')
00213     p.add_option('--online', action='store', dest='topic', type="string", 
00214                  default=None, help='tries to run success or failure detection online using histograms and backprojection')
00215     p.add_option('--label_manually', action='store_true', dest='manual',
00216                  default=False, help='allows user to manually label data for validation purposes')
00217 
00218 
00219 
00220     opt, args = p.parse_args()
00221 
00222 
00223     if opt.batch_folder != None:
00224         folder = opt.batch_folder+'/background_noise/'
00225         background_noise = deque() #[]
00226 
00227         cv.NamedWindow("Source", cv.CV_WINDOW_AUTOSIZE)
00228         #cv.NamedWindow("final", cv.CV_WINDOW_AUTOSIZE)
00229 
00230         for i in xrange(30):
00231             try:
00232                 background_noise.append(cv.LoadImage(folder+'file'+str(i).zfill(3)+'.png'))
00233             except:
00234                 print "no file # ", i
00235         mask = cv.LoadImage(folder+'mask.png', 0)
00236 
00237         ha = HistAnalyzer(background_noise, mask)
00238         ha.calc_hist()
00239         ha.calc_stats()
00240 
00241         print "should see avg noise"
00242         ############comment this afterwards or clean up with options #######
00243         #cv.ShowImage("Source", ha.avg_noise)
00244         #cv.WaitKey(-1)
00245         ############comment this afterwards or clean up with options #######
00246 
00247         back_sum_ls = deque() #[]
00248         Imask = cv.CreateImage(cv.GetSize(ha.background_noise[0]), cv.IPL_DEPTH_8U, 1)
00249 
00250         for i in xrange(130):
00251             try:
00252                 img = cv.LoadImage(folder+'file'+str(i).zfill(3)+'.png')
00253                 back_img, hist = ha.back_project_hs(img)
00254                 result = ha.backgroundDiff(back_img, Imask)
00255                 back_sum_ls.append(float(cv.Sum(result)[0]))
00256             except:
00257                 print "no training file # ", i
00258 
00259         avg = np.mean(back_sum_ls)
00260         std = np.std(back_sum_ls)
00261         
00262         print "here's the back_sum_ls : \n", back_sum_ls
00263 
00264         print "avg and std are :", avg, std
00265 
00266         n = 0
00267         sum_val = 0
00268 
00269         if opt.manual:
00270             manual_classification_list = []
00271 
00272         for i in xrange(9):
00273             # file_h = open(opt.batch_folder+'/object'+str(i).zfill(3)+'.pkl', 'r')
00274             # res_dict = cPickle.load(file_h)
00275             file_list = glob.glob(opt.batch_folder+'/object'+str(i).zfill(3)+'*after*.png')
00276             file_list.sort()
00277             length = int(file_list[-1][-17:-14])
00278             #length = len(glob.glob(opt.batch_folder+'/object'+str(i).zfill(3)+'*after*.png'))
00279             res_dict = {'frames':[], 'success': [None]*length}
00280             # for j in xrange(len(res_dict['success'])): 
00281 
00282 
00283             for j in xrange(length):
00284                 try:
00285                     #check for object before starting ...##########################
00286                     img = cv.LoadImageM(opt.batch_folder+'/object'+str(i).zfill(3)+'_try'+str(j).zfill(3)+'_before_pr2.png')
00287                     back_img, hist = ha.back_project_hs(img)
00288                     result = ha.backgroundDiff(back_img, Imask)
00289 
00290                     is_object = False
00291                     loc_sum = float(cv.Sum(result)[0])
00292                     if loc_sum < avg+5*std:
00293                         res_dict['success'][j] = None
00294                         print "no object to start with!?"
00295                     else:
00296                         is_object = True
00297                         print "there's an object let's check for success ..."
00298 
00299                     #check for success if object was in workspace to start with
00300                     if is_object == True:
00301                         try:
00302                             img = cv.LoadImageM(opt.batch_folder+'/object'+str(i).zfill(3)+'_try'+str(j).zfill(3)+'_after_pr2.png')
00303 
00304                             if opt.manual:
00305                                 cv.ShowImage("Source", img)
00306                                 cv.WaitKey(100)
00307                                 user_inp = raw_input('success:1, failure:0, not sure:-1 \n')
00308                                 if user_inp == 'q':
00309                                     file_manual = open('/home/mkillpack/Desktop/manual_classification_.pkl', 'w')
00310                                     cPickle.dump(manual_classification_list, file_manual)
00311                                     file_manual.close()
00312                                 else:
00313                                     manual_classification_list.append(int(user_inp))
00314                                     print "length of manual list is: ", len(manual_classification_list)
00315                                     print "number of real samples is :", 
00316                                     print len(np.where(np.array(manual_classification_list) == 1)[0]) + len(np.where(np.array(manual_classification_list) == 0)[0])
00317                                     print '\n'
00318 
00319                             else:
00320                                 back_img, hist = ha.back_project_hs(img)                        
00321                                 result2 = ha.backgroundDiff(back_img, Imask)
00322                                 n = n+1
00323                                 sum_val = sum_val + float(cv.Sum(result2)[0])
00324                                 #print "here's the sum :", cv.Sum(result2)[0]
00325 
00326                                 loc_sum2 = float(cv.Sum(result2)[0])
00327                                 if loc_sum2 < loc_sum/2.0:
00328                                     res_dict['success'][j] = True
00329                                     print "success ! \t:", loc_sum2, "\t compared to \t", loc_sum/2.0
00330                                     #ha.background_noise.popleft()
00331                                     #ha.background_noise.append(img)
00332                                 else:
00333                                     res_dict['success'][j] = False
00334                                     print "epic fail ! \t:", loc_sum2, "\t compared to \t", loc_sum/2.0
00335 
00336                                 cv.ShowImage("Source", img)
00337                                 cv.ShowImage("final", result2)
00338                                 cv.WaitKey(33)
00339                             
00340                         except:
00341                             print "no image to test named : "
00342                             print opt.batch_folder+'/object'+str(i).zfill(3)+'_try'+str(j).zfill(3)+'_after_pr2.png'
00343                             res_dict['success'][j] = None      
00344 
00345                 except:
00346                     res_dict['success'][j] =  None
00347                     print "problem in try statement"
00348 
00349             try:
00350                 os.system('rm '+opt.batch_folder+'/object'+str(i).zfill(3)+'.pkl')
00351             except:
00352                 print "PROBLEM DELETING OLD FILE..., it didn't exist"
00353                 exit
00354             file_h2 =  open(opt.batch_folder+'/object'+str(i).zfill(3)+'.pkl', 'w')
00355             cPickle.dump(res_dict, file_h2)
00356             file_h2.close()
00357             print "moving to next object..."
00358             #ha.calc_hist()
00359             #ha.calc_stats()
00360             print "done!"
00361 
00362         if opt.manual:
00363             file_manual = open('/home/mkillpack/Desktop/manual_classification_.pkl', 'w')
00364             cPickle.dump(manual_classification_list, file_manual)
00365             file_manual.close()
00366         else:
00367             print "average error for objects present :", sum_val/n            
00368 
00369     elif opt.topic != None:
00370         rospy.logerr("online evaluation is not yet implemented, but all the necessary tools should be present to do it ...")
00371         assert(False)


pr2_playpen
Author(s): Marc Killpack / mkillpack3@gatech.edu, Advisor: Prof. Charlie Kemp, Lab: Healthcare Robotics Lab at Georgia Tech
autogenerated on Wed Nov 27 2013 12:18:32