print 'Training... ( N =', N, ')'
  shuffler = cross_validation.ShuffleSplit(N, 1, 0.1)
  for train_idx, test_idx in shuffler:
    X_train = X[train_idx,:]
    X_test = X[test_idx,:]
    y_train = y[train_idx]
    y_test = y[test_idx]
    
    clf = svm.SVC(C=1.0, kernel='rbf', degree=3, gamma=0.003, verbose=False)
    clf.fit(X_train, y_train)
    pred = clf.predict(X_test)
    print 'Correct rate:', or_ml.correctRate(pred, y_test)

    gg = np.meshgrid(xrange(0, 180, 1), xrange(0, 256, 1))
    dd = np.column_stack((gg[0].flat, gg[1].flat))
    pred = clf.predict(dd)
    pred2d = pred.reshape(256, 180)
    joblib.dump(pred2d, opt.outfile)

    classnames = map(or_util.removeExtension, filenames)
    joblib.dump(classnames, or_util.appendToName(opt.outfile, '_classes'))

    if opt.plot:
      for i in xrange(0, C):
        plt.plot(dd[pred==i,0], dd[pred==i,1], '.')
      plt.axis([0, 180, 0, 255])
      for hs in features:
        plt.plot(hs[:,0], hs[:,1], 'o')
      # plt.legend(filenames)
      plt.show()
  def __init__(self, opt):
    self.woodenTable = joblib.load(opt.wooden)
    self.woodenClasses = joblib.load(or_util.appendToName(opt.wooden, '_classes'))
    self.plasticTable = joblib.load(opt.plastic)
    self.plasticClasses = joblib.load(or_util.appendToName(opt.plastic, '_classes'))
    self.materialClf = joblib.load(opt.material)
    self.materialClasses = joblib.load(or_util.appendToName(opt.material, '_classes'))
    self.purpleClf = joblib.load(opt.purple)
    self.purpleClasses = joblib.load(or_util.appendToName(opt.purple, '_classes'))

    rospy.init_node('object_recognition')
    self.rate = rospy.Rate(LOOP_RATE)

    self.blurTune = rospy.get_param('~blur_tune', False)
    self.blobTune = rospy.get_param('~blob_tune', False)
    self.cannyTune = rospy.get_param('~canny_tune', False)
    self.morphTune = rospy.get_param('~morph_tune', False)
    self.houghTune = rospy.get_param('~hough_tune', False)
    self.show = rospy.get_param('~show', False)
    self.tuneSetup = rospy.get_param('~tune_setup', False)
    self.collect = rospy.get_param('~collect', 'nothing')

    if self.collect != 'nothing':
      rospy.on_shutdown(self.shutdown_hook)
    if self.show:
      if self.tuneSetup:
        cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_AUTOSIZE)
        cv2.moveWindow(WINDOW_NAME, 400, 250)
        cv2.namedWindow(TRACKBAR_WINDOW, cv2.WINDOW_AUTOSIZE)
        cv2.moveWindow(TRACKBAR_WINDOW, 1050, 250)
      else:
        cv2.namedWindow(WINDOW_NAME, cv2.WINDOW_AUTOSIZE)
        cv2.moveWindow(WINDOW_NAME, 600, 250)
    if self.blurTune:
      def blurSizeTune(v): self.blurSize = v
      cv2.createTrackbar('Size', TRACKBAR_WINDOW, self.blurSize, 15, blurSizeTune)
      def sigmaXTune(v): self.sigmaX = v
      cv2.createTrackbar('Sigma x', TRACKBAR_WINDOW, self.sigmaX, 200, sigmaXTune)
    if self.blobTune:
      def minDistTune(v): self.minDist = v
      cv2.createTrackbar('Min dist', TRACKBAR_WINDOW, self.minDist, 100, minDistTune)
      def minAreaTune(v): self.minArea = v
      cv2.createTrackbar('Min area', TRACKBAR_WINDOW, self.minArea, 2000, minAreaTune)
      def maxAreaTune(v): self.maxArea = v
      cv2.createTrackbar('Max area', TRACKBAR_WINDOW, self.maxArea, 40000, maxAreaTune)
      def minCircTune(v): self.minCirc = v
      cv2.createTrackbar('Min circ', TRACKBAR_WINDOW, self.minCirc, 100, minCircTune)
      def minInerTune(v): self.minIner = v
      cv2.createTrackbar('Min iner', TRACKBAR_WINDOW, self.minIner, 100, minInerTune)
    if self.cannyTune:
      def cannyLowTune(v): self.cannyLow = v
      cv2.createTrackbar('Canny low', TRACKBAR_WINDOW, self.cannyLow, 1000, cannyLowTune)
      def cannyHighTune(v): self.cannyHigh = v
      cv2.createTrackbar('Canny high', TRACKBAR_WINDOW, self.cannyHigh, 1000, cannyHighTune)
      def cannyKernelTune(v): self.cannyKernel = v
      cv2.createTrackbar('Canny kernel', TRACKBAR_WINDOW, self.cannyKernel, 31, cannyKernelTune)
    if self.morphTune:
      def morphSizeTune(v): self.morphSize = v
      cv2.createTrackbar('Morph size', TRACKBAR_WINDOW, self.morphSize, 31, morphSizeTune)
    if self.houghTune:
      def cannyParamTune(v): self.cannyParam = v
      cv2.createTrackbar('Canny param', TRACKBAR_WINDOW, self.cannyParam, 200, cannyParamTune)
      def param1Tune(v): self.param1 = v
      cv2.createTrackbar('Param1', TRACKBAR_WINDOW, self.param1, 100, param1Tune)

    self.blobParams = cv2.SimpleBlobDetector_Params()
    self.blobParams.minDistBetweenBlobs = self.minDist
    self.blobParams.filterByArea = True
    self.blobParams.minArea = max(1, self.minArea)
    self.blobParams.maxArea = max(self.minArea, self.maxArea)
    self.blobParams.filterByColor = False
    self.blobParams.filterByCircularity = True
    self.blobParams.minCircularity = self.minCirc / 100.
    self.blobParams.filterByConvexity = True
    self.blobParams.minConvexity = self.minConv
    self.blobParams.filterByInertia = True
    self.blobParams.minInertiaRatio = self.minIner / 100.
    # These 3 are not useful
    # self.blobParams.minThreshold = 10
    # self.blobParams.maxThreshold = 240
    # self.blobParams.thresholdStep = max(1, self.stepThre)

    def rgbCallback(rosimg): self.rgbRosImg = rosimg
    self.rgbSub = rospy.Subscriber('/camera/rgb/image_raw', Image, rgbCallback)
    def depthCallback(rosimg): self.depthRosImg = rosimg
    self.depthSub = rospy.Subscriber('/camera/depth_registered/image_raw', Image, depthCallback)
    self.recognitonProvider = rospy.Service(
        '/object_recognition_provider',
        Joint,
        self.recognitionCallback)
    self.tracker = or_ml.TrackerWrapper()