Esempio n. 1
0
    def on_touch_up(self, touch):
        global userShape
        
        wordToLearn = wordManager.getCurrentCollection()
        if len(userShape) < 5:
            
            closeFigures(figuresToClose = range(1,len(wordToLearn)+1))
            wordToLearn = raw_input("Next word:\n")
            newWord(wordToLearn)
            userInputCapture.display_grid(numColumns = len(wordToLearn))

        else:
            userShape = downsampleShape(userShape,numPoints_shapeModeler,xyxyFormat=True)

            shapeCentre = ShapeModeler.getShapeCentre(userShape)
            for i in range(len(wordToLearn)):
                if(shapeCentre[0] > (self.width/len(wordToLearn))*i):
                    shapeIndex_demoFor = i

            shapeType = wordManager.shapeAtIndexInCurrentCollection(shapeIndex_demoFor)
            print('Received demo for letter ' + shapeType)

            userShape = numpy.reshape(userShape, (-1, 1)); #explicitly make it 2D array with only one column
            userShape = ShapeModeler.normaliseShapeHeight(numpy.array(userShape))

            shape = wordManager.respondToDemonstration(shapeType, userShape)

            userShape = []
            self.canvas.remove(touch.ud['line'])
            if shape != -1:
                showShape(shape, shapeIndex_demoFor)
def param_gui(letter_name, shapeModeler):
    global sliders, mainPlot, fig, pca_params
    fig, ax = plt.subplots()
    whiteSpace = 0.15 + num_params*0.05
    plt.subplots_adjust( bottom=whiteSpace)
    plt.axis('equal')
    
    #plot of initial shape
    params = np.zeros((num_params,1))
    shape = shapeModeler.makeShape(params)
    shape = ShapeModeler.normaliseShape(shape)
    numPointsInShape = len(shape)/2
    x_shape = shape[0:numPointsInShape]
    y_shape = shape[numPointsInShape:]

    mainPlot, = plt.plot(x_shape, -y_shape)
    plt.axis([-1, 1, -1, 1],autoscale_on=False, aspect='equal')
    plt.title(letter_name)

    #add sliders to modify parameter values
    parameterVariances = shapeModeler.getParameterVariances()
    sliders = [0]*num_params
    for i in range(num_params):
        slider = Slider(plt.axes([0.25, 0.1+0.05*(num_params-i-1), 0.65, 0.03], axisbg=axcolor),
             'Parameter '+str(i+1), -5*parameterVariances[i], 5*parameterVariances[i], valinit=0)
        slider.on_changed(partial(update, shapeModeler))
        sliders[i] = slider
    
    resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
    button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
    button.on_clicked(reset)
    plt.show()

    return pca_params
def downsampleShape(shape):
    #downsample user-drawn shape so appropriate size for shapeLearner
    numPointsInShape = len(shape)/2;
    x_shape = shape[0:numPointsInShape];
    y_shape = shape[numPointsInShape:];
    
    if isinstance(x_shape,numpy.ndarray): #convert arrays to lists for interp1d
        x_shape = (x_shape.T).tolist()[0];
        y_shape = (y_shape.T).tolist()[0];
        
    #make shape have the same number of points as the shape_modeler
    t_current = numpy.linspace(0, 1, numPointsInShape);
    t_desired = numpy.linspace(0, 1, numPoints_shapeModeler);
    f = interpolate.interp1d(t_current, x_shape, kind='cubic');
    x_shape = f(t_desired);
    f = interpolate.interp1d(t_current, y_shape, kind='cubic');
    y_shape = f(t_desired);
       
    shape = [];
    shape[0:numPoints_shapeModeler] = x_shape;
    shape[numPoints_shapeModeler:] = y_shape;

    shape = ShapeModeler.normaliseShapeHeight(numpy.array(shape));
    shape = numpy.reshape(shape, (-1, 1)); #explicitly make it 2D array with only one column

    return shape
def downsampleShape(shape):
    #downsample user-drawn shape so appropriate size for shapeLearner
    numPointsInShape = len(shape)/2
    x_shape = shape[0:numPointsInShape]
    y_shape = shape[numPointsInShape:]

    if isinstance(x_shape,numpy.ndarray): #convert arrays to lists for interp1d
        x_shape = (x_shape.T).tolist()[0]
        y_shape = (y_shape.T).tolist()[0]

    #make shape have the same number of points as the shape_modeler
    t_current = numpy.linspace(0, 1, numPointsInShape)
    t_desired = numpy.linspace(0, 1, NUMPOINTS_SHAPEMODELER)
    f = interpolate.interp1d(t_current, x_shape, kind='linear')
    x_shape = f(t_desired)
    f = interpolate.interp1d(t_current, y_shape, kind='linear')
    y_shape = f(t_desired)

    shape = []
    shape[0:NUMPOINTS_SHAPEMODELER] = x_shape
    shape[NUMPOINTS_SHAPEMODELER:] = y_shape

    shape = ShapeModeler.normaliseShapeHeight(numpy.array(shape))
    shape = numpy.reshape(shape, (-1, 1)) #explicitly make it 2D array with only one column

    return shape
Esempio n. 5
0
def preparePlot(shapeModeler):
    global sliders, mainPlot, fig
    fig, ax = plt.subplots();
    whiteSpace = 0.15 + numParams*0.05;
    plt.subplots_adjust( bottom=whiteSpace);
    plt.axis('equal');
    
    #plot of initial shape
    params = np.zeros((numParams,1));
    shape = shapeModeler.makeShape(params);
    shape = ShapeModeler.normaliseShape(shape);
    numPointsInShape = len(shape)/2;
    x_shape = shape[0:numPointsInShape];
    y_shape = shape[numPointsInShape:];

    mainPlot, = plt.plot(x_shape, -y_shape);
    plt.axis([-1, 1, -1, 1],autoscale_on=False, aspect='equal');

    #add sliders to modify parameter values
    parameterVariances = shapeModeler.getParameterVariances();
    sliders = [0]*numParams;
    for i in range(numParams):
        slider = Slider(plt.axes([0.25, 0.1+0.05*(numParams-i-1), 0.65, 0.03], axisbg=axcolor),
             'Parameter '+str(i+1), -5*parameterVariances[i], 5*parameterVariances[i], valinit=0);
        slider.on_changed(update);
        sliders[i] = slider;
    
    resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
    button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
    button.on_clicked(reset)
    plt.show()
Esempio n. 6
0
    def shapeWord(word, downsampling_factor=None):
        """Assembles the paths of the letters of the given word into a global shape.

        :param word: a ShapeLearnerManager instance for the current word
        :param downsampling_factor: if provided, the final shape of each letter
        is (independantly) resampled to (nb_pts / downsampling_factor) points

        :returns: a ShapedWord that contains the path of individual letters
        """
        
        paths = []

        offset_x = offset_y = 0
        for shape in word.shapesOfCurrentCollection():

            path = []

            w, ah, bh = LETTER_BOUNDINGBOXES[shape.shapeType]
            scale_factor = ah + bh # height ratio between this letter and a 'a'
            #no need for a width scaling since the shape are only *height*-normalized (cf below)

            glyph = ShapeModeler.normaliseShapeHeight(shape.path)
            numPointsInShape = len(glyph)/2  

            x_shape = glyph[0:numPointsInShape].flatten().tolist()
            y_shape = glyph[numPointsInShape:].flatten().tolist()

            if offset_x != 0 or offset_y != 0: # not the first letter
                offset_x -= x_shape[0] * SIZESCALE_WIDTH * scale_factor
                offset_y += y_shape[0] * SIZESCALE_HEIGHT * scale_factor

            for i in range(numPointsInShape):
                x = x_shape[i] * SIZESCALE_WIDTH * scale_factor
                y = -y_shape[i] * SIZESCALE_HEIGHT * scale_factor

                x += offset_x
                y += offset_y


                path.append((x,y))

            paths.append(path)

            if shape.shapeType in ['i', 'j']:
                # HACK: waiting for proper multi-stroke learning
                logger.info("Adding a 'dot' to the letter")
                dot_path = [ (offset_x + 0.0 * SIZESCALE_WIDTH * scale_factor, offset_y + 0.8 * SIZESCALE_WIDTH * scale_factor),
                         (offset_x + 0.05 * SIZESCALE_WIDTH * scale_factor, offset_y + 0.85 * SIZESCALE_HEIGHT * scale_factor),
                         (offset_x + 0.0 * SIZESCALE_WIDTH * scale_factor, offset_y + 0.85 * SIZESCALE_HEIGHT * scale_factor),
                         (offset_x + 0.0 * SIZESCALE_WIDTH * scale_factor, offset_y + 0.8 * SIZESCALE_HEIGHT * scale_factor)
                        ]
                paths.append(dot_path)

            # connect the letter to the ending point of the previous one
            offset_x = path[-1][0]
            offset_y = path[-1][1]



        return ShapedWord(word.currentCollection, paths)
Esempio n. 7
0
def downsampleShape(shape):
    #downsample user-drawn shape so appropriate size for shapeLearner
    numPointsInShape = len(shape) / 2
    x_shape = shape[0:numPointsInShape]
    y_shape = shape[numPointsInShape:]

    if isinstance(x_shape,
                  numpy.ndarray):  #convert arrays to lists for interp1d
        x_shape = (x_shape.T).tolist()[0]
        y_shape = (y_shape.T).tolist()[0]

    #make shape have the same number of points as the shape_modeler
    t_current = numpy.linspace(0, 1, numPointsInShape)
    t_desired = numpy.linspace(0, 1, NUMPOINTS_SHAPEMODELER)
    f = interpolate.interp1d(t_current, x_shape, kind='linear')
    x_shape = f(t_desired)
    f = interpolate.interp1d(t_current, y_shape, kind='linear')
    y_shape = f(t_desired)

    shape = []
    shape[0:NUMPOINTS_SHAPEMODELER] = x_shape
    shape[NUMPOINTS_SHAPEMODELER:] = y_shape

    shape = ShapeModeler.normaliseShapeHeight(numpy.array(shape))
    shape = numpy.reshape(
        shape, (-1, 1))  #explicitly make it 2D array with only one column

    return shape
    def on_touch_up(self, touch):
        global userShape
        touch.ud['line'].points
        userShape = downsampleShape(userShape,
                                    numPoints_shapeModeler,
                                    xyxyFormat=True)
        shapeCentre = ShapeModeler.getShapeCentre(userShape)

        for i in range(len(wordToLearn)):
            if (shapeCentre[0] > (self.width / len(wordToLearn)) * i):
                shapeIndex_demoFor = i

        shapeType = wordManager.shapeAtIndexInCurrentCollection(
            shapeIndex_demoFor)

        print('Received demo for letter ' + shapeType)

        userShape = np.reshape(userShape, (-1, 1))
        #explicitly make it 2D array with only one column
        shape = wordManager.respondToDemonstration(shapeIndex_demoFor,
                                                   userShape)
        wordManager.save_all(shapeIndex_demoFor)

        userShape = []
        self.canvas.remove(touch.ud['line'])
        showShape(shape, shapeIndex_demoFor)
    def on_touch_up(self, touch):
        global userShape
        touch.ud['line'].points
        userShape = downsampleShape(userShape,numPoints_shapeModeler,xyxyFormat=True)
        shapeCentre = ShapeModeler.getShapeCentre(userShape)

        shapeType = letter
            
        print('Received reference for letter ' + shapeType)

        userShape = numpy.reshape(userShape, (-1, 1));
        userShape = ShapeModeler.normaliseShapeHeight(numpy.array(userShape))
        
        filename = dataSetFile
        print('saving in'+filename)
        
        # scan the dataset :
        lines = []
        try: 
            with open(filename, 'r') as f:
                lines.append(f.readline())
                nb_samples =  int(lines[0].strip())
                for i in range(nb_samples+1):
                    lines.append(f.readline())
        except IOError:
            raise RuntimeError("no reading permission for file"+filename)
            
        nb_samples+=1
        
        # past the dataset :
        try:
            with open(filename, 'w') as f:
                f.write('nb_sample:\n')
                f.write('%i\n'%nb_samples)
                f.write('nb_pts:\n')
                f.write('70\n')
                f.write('ref:\n')
                f.write(' '.join(map(str,userShape.T[0]))+'\n')
                f.write('...\n')
                for i in range(nb_samples-1):
                    f.write(lines[i+2])
        except IOError:
            raise RuntimeError("no writing permission for file"+filename)

        userShape = []
        self.canvas.remove(touch.ud['line'])
Esempio n. 10
0
def prepareShapeModel(datasetDirectory, shape):
    import glob
    datasetFiles_shape = glob.glob(datasetDirectory + '/' + shape + '.dat')
    if (len(datasetFiles_shape) < 1):
        raise Exception("Dataset not available at " + datasetDirectory +
                        " for shape " + shape)
    shapeModeler = ShapeModeler(filename=datasetFiles_shape[0],
                                num_principle_components=numParams)
    #import pdb; pdb.set_trace()
    return shapeModeler
Esempio n. 11
0
def update(val):
    global sliders, mainPlot, fig
    params = np.zeros((numParams, 1))
    for i in range(numParams):
        params[i] = sliders[i].val
    shape = shapeModeler.makeShape(params)
    shape = ShapeModeler.normaliseShape(shape)
    numPointsInShape = len(shape) / 2
    x_shape = shape[0:numPointsInShape]
    y_shape = shape[numPointsInShape:]
    mainPlot.set_data(x_shape, -y_shape)
    fig.canvas.draw_idle()
Esempio n. 12
0
def update(val):
    global sliders , mainPlot, fig
    params = np.zeros((numParams,1));
    for i in range(numParams):
        params[i] = sliders[i].val;
    shape = shapeModeler.makeShape(params);
    shape = ShapeModeler.normaliseShape(shape);
    numPointsInShape = len(shape)/2;
    x_shape = shape[0:numPointsInShape];
    y_shape = shape[numPointsInShape:];
    mainPlot.set_data(x_shape, -y_shape);
    fig.canvas.draw_idle();
def make_traj_msg(shape, shapeCentre, headerString, startTime, downsample, deltaT):      
    if(startTime!=t0):
        penUpToFirst = True;
    else:
        penUpToFirst = False;
    
    traj = Path();
    traj.header.frame_id = FRAME#headerString;
    traj.header.stamp = rospy.Time.now()+rospy.Duration(delayBeforeExecuting);
    shape = ShapeModeler.normaliseShapeHeight(shape);
    numPointsInShape_orig = len(shape)/2;   
    
    x_shape = shape[0:numPointsInShape_orig];
    y_shape = shape[numPointsInShape_orig:];
    
    if(downsample):
        #make shape have the appropriate number of points
        t_current = numpy.linspace(0, 1, numPointsInShape_orig);
        t_desired = numpy.linspace(0, 1, numDesiredShapePoints);
        f = interpolate.interp1d(t_current, x_shape[:,0], kind='cubic');
        x_shape = f(t_desired);
        f = interpolate.interp1d(t_current, y_shape[:,0], kind='cubic');
        y_shape = f(t_desired);

        numPointsInShape = len(x_shape);
        downsampleFactor = numPointsInShape_orig/float(numPointsInShape);
    else:
        numPointsInShape = numPointsInShape_orig;

    for i in range(numPointsInShape):
        point = PoseStamped();

        point.pose.position.x = x_shape[i]*sizeScale_width;
        point.pose.position.y = -y_shape[i]*sizeScale_height;
        
        point.pose.position.x+= + shapeCentre[0];
        point.pose.position.y+= + shapeCentre[1];
        
        point.header.frame_id = FRAME;
        point.header.stamp = rospy.Time(startTime+i*deltaT+t0); #@TODO allow for variable time between points for now

        if(penUpToFirst and i==0):
            point.header.seq = 1;

        traj.poses.append(deepcopy(point));

    if(downsample):
        return traj, downsampleFactor
    else:
        return traj
def update(shapeModeler, val):
    global sliders , mainPlot, fig, pca_params
    pca_params = np.zeros((num_params, 1))

    for i in range(num_params):
        pca_params[i] = sliders[i].val
    
    shape = shapeModeler.makeShape(pca_params)
    shape = ShapeModeler.normaliseShape(shape)
    numPointsInShape = len(shape)/2
    x_shape = shape[0:numPointsInShape]
    y_shape = shape[numPointsInShape:]
    mainPlot.set_data(x_shape, -y_shape)
    fig.canvas.draw_idle()
def prepareShapesModel(datasetDirectory, num_params):

    shapes = {}

    nameFilter = re.compile(regexp)
    datasets = glob.glob(datasetDirectory + '/*.dat')

    for dataset in datasets:
        name = os.path.splitext(os.path.basename(dataset))[0]

        if nameFilter.match(name):
            shapeModeler = ShapeModeler(init_filename=dataset,
                                        num_principle_components=num_params)
            shapes[name] = shapeModeler

    return shapes
Esempio n. 16
0
    def respondToDemonstration(self, shape):
        """
        Algo:
        
        1) takes the shape of the demonstration
        
        2) takes the curent learned shape
        
        3) re-performs PCA taking in account the domonstrated shape,
           then obtains a new space with new eigen vectors
           
        4) projects demonstrated and learned shapes into this new space 
           and gets their new parameters  
           
        5) updates the learned parameters as the algebric middle 
           between demonstrated parameters and curent learned parameters. 
        """
        demo_shape = ShapeModeler.normaliseShapeHeight(numpy.array(shape))
        
        # take the shape corresponding to the curent learned parameters in the curent space
        learned_shape = self.shapeModeler.makeShape(self.params)
        
        # add the demo shape to the matrix for PCA and re-compute reference-shape params
        self.shapeModeler.extendDataMat(demo_shape)
        ref_params = self.shapeModeler.refParams
        
        # re-compute parameters of the learned shape and the demo shape in the new PCA-space
        params_demo, _ = self.shapeModeler.decomposeShape(demo_shape)
        self.params, _ = self.shapeModeler.decomposeShape(learned_shape)
        
        # learning :
        diff_params = params_demo - self.params
        self.params += diff_params/2 #go towards the demonstrated shape


        #self.params[self.paramsToVary[0]-1] = params_demo[self.paramsToVary[0]-1] #ONLY USE FIRST PARAM
        #store it as an attempt (this isn't super appropriate but whatever)
        if (self.doGroupwiseComparison):
            newParamValue = self.params[
                self.paramsToVary[0] - 1, 0]  #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
            #print('Demo params: '+str(self.params))
            bisect.insort(self.params_sorted, newParamValue)
            self.shapeToParamsMapping.append(self.params)
            #self.respondToFeedback(len(self.params_sorted)-3) # give feedback of most recent shape so bounds modify
        return self.shapeModeler.makeShape(self.params), self.params, params_demo
    def on_touch_up(self, touch):
        global userShape
        touch.ud['line'].points
        userShape = downsampleShape(userShape,numPoints_shapeModeler,xyxyFormat=True)
        shapeCentre = ShapeModeler.getShapeCentre(userShape)
        
        for i in range(len(wordToLearn)):
            if(shapeCentre[0] > (self.width/len(wordToLearn))*i):
                shapeIndex_demoFor = i

        shapeType = wordManager.shapeAtIndexInCurrentCollection(shapeIndex_demoFor)
            
        print('Received demo for letter ' + shapeType)

        userShape = np.reshape(userShape, (-1, 1)); #explicitly make it 2D array with only one column
        shape = wordManager.respondToDemonstration(shapeIndex_demoFor, userShape)
        wordManager.save_all(shapeIndex_demoFor)
        

        userShape = []
        self.canvas.remove(touch.ud['line'])
        showShape(shape, shapeIndex_demoFor)
def onUserDrawnShapeReceived(path, shapePreprocessingMethod, positionToShapeMappingMethod):
    global activeShapeForDemonstration_type 
    
    #preprocess to turn multiple strokes into one path
    if(shapePreprocessingMethod == 'longestStroke'):
        path = processShape_longestStroke(strokes); 
    else:
        path = processShape_firstStroke(strokes);
            
            
    #identify type of shape which demonstration was for
    location = ShapeModeler.getShapeCentre(path);

    if(positionToShapeMappingMethod == 'basedOnColumnOfScreen'):
        shapeType_demoFor = getShapeCode_basedOnColumnOfScreen(location);

    elif(positionToShapeMappingMethod == 'basedOnRowOfScreen'):
        shapeType_demoFor = getShapeCode_basedOnColumnOfScreen(location);    

    elif(positionToShapeMappingMethod == 'basedOnShapeAtPosition'):
        shapeType_demoFor = getShapeCode_basedOnShapeAtPosition(location);
        
    else:
        shapeType_demoFor = getShapeCode_basedOnClosestShapeToPosition(location);
       
       
    #block the space from robot use
    try:
        display_shape_at_location = rospy.ServiceProxy('display_shape_at_location', displayShapeAtLocation);
        request = displayShapeAtLocationRequest();
        request.shape_type_code = shapeType_demoFor;
        request.location.x = location[0];
        request.location.y = location[1];
        #todo: allow for blocking different sized shapes
        response = display_shape_at_location(request);
        result = response.success;
        #todo: do something if unsuccessful
    except rospy.ServiceException, e:
        rospy.logerr("Service call failed: %s",e);
Esempio n. 19
0
    def __init__(self, settings):

        self.paramsToVary = settings.paramsToVary
        #self.numPrincipleComponents = max(self.paramsToVary)
        self.numPrincipleComponents = NUM_PRINCIPLE_COMPONENTS
        #assign a ShapeModeler to use
        print(settings.initDatasetFile)
        self.shapeModeler = ShapeModeler(init_filename=settings.initDatasetFile,
                                         update_filenames=settings.updateDatasetFiles,
                                         param_filename=settings.paramFile,
                                         num_principle_components=self.numPrincipleComponents)

        self.bounds = settings.initialBounds
        for i in range(len(self.paramsToVary)):
            parameterVariances = self.shapeModeler.getParameterVariances()
            if (numpy.isnan(settings.initialBounds[i, 0]) or numpy.isnan(
                    settings.initialBounds[i, 1])):  #want to set initial bounds as std. dev. multiple
                boundsFromStdDevMultiples = numpy.array(settings.initialBounds_stdDevMultiples[i, :]) * \
                                            parameterVariances[settings.paramsToVary[i] - 1]

                if (numpy.isnan(settings.initialBounds[i, 0])):
                    self.bounds[i, 0] = boundsFromStdDevMultiples[0]
                if (numpy.isnan(settings.initialBounds[i, 1])):
                    self.bounds[i, 1] = boundsFromStdDevMultiples[1]

        self.doGroupwiseComparison = settings.doGroupwiseComparison
        self.shape_learning = settings.shape_learning
        self.minParamDiff = settings.minParamDiff

        self.initialParamValue = settings.initialParamValue
        self.params = numpy.zeros((self.numPrincipleComponents, 1))

        for i in range(self.numPrincipleComponents):
            self.params[i][0] = -self.initialParamValue[i]

        self.initialBounds = deepcopy(self.bounds)
        self.converged = False
        self.numIters = 0
        self.numItersConverged = 0
Esempio n. 20
0
def preparePlot(shapeModeler):
    global sliders, mainPlot, fig
    fig, ax = plt.subplots()
    whiteSpace = 0.15 + numParams * 0.05
    plt.subplots_adjust(bottom=whiteSpace)
    plt.axis('equal')

    #plot of initial shape
    params = np.zeros((numParams, 1))
    shape = shapeModeler.makeShape(params)
    shape = ShapeModeler.normaliseShape(shape)
    numPointsInShape = len(shape) / 2
    x_shape = shape[0:numPointsInShape]
    y_shape = shape[numPointsInShape:]

    mainPlot, = plt.plot(x_shape, -y_shape)
    plt.axis([-1, 1, -1, 1], autoscale_on=False, aspect='equal')

    #add sliders to modify parameter values
    parameterVariances = shapeModeler.getParameterVariances()
    sliders = [0] * numParams
    for i in range(numParams):
        slider = Slider(plt.axes(
            [0.25, 0.1 + 0.05 * (numParams - i - 1), 0.65, 0.03],
            axisbg=axcolor),
                        'Parameter ' + str(i + 1),
                        -5 * parameterVariances[i],
                        5 * parameterVariances[i],
                        valinit=0)
        slider.on_changed(update)
        sliders[i] = slider

    resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
    button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
    button.on_clicked(reset)
    plt.show()
Esempio n. 21
0
class ShapeLearner:
    def __init__(self, settings):

        self.paramsToVary = settings.paramsToVary
        #self.numPrincipleComponents = max(self.paramsToVary)
        self.numPrincipleComponents = NUM_PRINCIPLE_COMPONENTS
        #assign a ShapeModeler to use
        print(settings.initDatasetFile)
        self.shapeModeler = ShapeModeler(init_filename=settings.initDatasetFile,
                                         update_filenames=settings.updateDatasetFiles,
                                         param_filename=settings.paramFile,
                                         num_principle_components=self.numPrincipleComponents)

        self.bounds = settings.initialBounds
        for i in range(len(self.paramsToVary)):
            parameterVariances = self.shapeModeler.getParameterVariances()
            if (numpy.isnan(settings.initialBounds[i, 0]) or numpy.isnan(
                    settings.initialBounds[i, 1])):  #want to set initial bounds as std. dev. multiple
                boundsFromStdDevMultiples = numpy.array(settings.initialBounds_stdDevMultiples[i, :]) * \
                                            parameterVariances[settings.paramsToVary[i] - 1]

                if (numpy.isnan(settings.initialBounds[i, 0])):
                    self.bounds[i, 0] = boundsFromStdDevMultiples[0]
                if (numpy.isnan(settings.initialBounds[i, 1])):
                    self.bounds[i, 1] = boundsFromStdDevMultiples[1]

        self.doGroupwiseComparison = settings.doGroupwiseComparison
        self.shape_learning = settings.shape_learning
        self.minParamDiff = settings.minParamDiff

        self.initialParamValue = settings.initialParamValue
        self.params = numpy.zeros((self.numPrincipleComponents, 1))

        for i in range(self.numPrincipleComponents):
            self.params[i][0] = -self.initialParamValue[i]

        self.initialBounds = deepcopy(self.bounds)
        self.converged = False
        self.numIters = 0
        self.numItersConverged = 0

    ### ----------------------------------------------------- START LEARNING
    def startLearning(self):
        #make initial shape
        if (numpy.isnan(self.initialParamValue[0])):
            [shape, paramValues] = self.shapeModeler.makeRandomShapeFromUniform(self.params, self.paramsToVary,
                                                                                self.bounds)
            self.params = paramValues
        else:
            shape = self.shapeModeler.makeShape(self.params)

        self.bestParamValue = self.params[
            self.paramsToVary[0] - 1]  #   USE ONLY FIRST PARAM IN LIST FOR SELF-LEARNING ALGORITHM

        if (self.doGroupwiseComparison):
            self.params_sorted = [self.bounds[0, 0],
                                  self.bounds[0, 1]] #   USE ONLY FIRST PARAM IN LIST FOR SELF-LEARNING ALGORITHM
            bisect.insort(self.params_sorted, self.bestParamValue)
            self.shapeToParamsMapping = [self.params]
        else:
            self.newParamValue = self.bestParamValue
            self.params = [self.newParamValue]

        return shape, self.params

    ### ---------------------------------------- START LEARNING - TRIANGULAR
    def startLearningAt(self, startingBounds, startingParamValues):
        self.bounds = startingBounds

        #make initial shape
        [shape, paramValues] = self.shapeModeler.makeRandomShapeFromTriangular(self.params, self.paramsToVary,
                                                                              self.bounds, startingParamValues)
        self.params = paramValues
        self.bestParamValue = paramValues[
            self.paramsToVary[0] - 1]  #   USE ONLY FIRST PARAM IN LIST FOR SELF-LEARNING ALGORITHM
        if (self.doGroupwiseComparison):
            self.params_sorted = [self.bounds[0, 0],
                                  self.bounds[0, 1]] #   USE ONLY FIRST PARAM IN LIST FOR SELF-LEARNING ALGORITHM
            bisect.insort(self.params_sorted, self.bestParamValue)
            self.shapeToParamsMapping = [self.params]
        else:
            self.newParamValue = self.bestParamValue

        return shape, self.bestParamValue


    ### ----------------------------------------------- MAKE DIFFERENT SHAPE
    def makeShapeDifferentTo(self, paramValue):
        #make new shape to compare with
        [newShape, newParams] = self.shapeModeler.makeRandomShapeFromTriangular(self.params, self.paramsToVary,
                                                                                self.bounds, [
                paramValue])  #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
        newParamValue = newParams[self.paramsToVary[0] - 1, 0] #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
        #ensure it is significantly different
        numAttempts = 1
        while (abs(newParamValue - paramValue) < self.minParamDiff and numAttempts < maxNumAttempts):
            [newShape, newParams] = self.shapeModeler.makeRandomShapeFromTriangular(self.params, self.paramsToVary,
                                                                                    self.bounds, [
                    paramValue]) #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
            newParamValue = newParams[
                self.paramsToVary[0] - 1, 0] #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
            numAttempts += 1

        if (numAttempts >= maxNumAttempts):  #couldn't find a 'different' shape in range
            print('Oh no!')  #this should be prevented by the convergence test below

        #store it as an attempt
        if (self.doGroupwiseComparison):
            bisect.insort(self.params_sorted, newParamValue)
            self.shapeToParamsMapping.append(newParams)

        return newShape, newParamValue

    ### ------------------------------------------------- MAKE SIMILAR SHAPE
    def makeShapeSimilarTo(self, paramValue):
        #make new shape, but don't enforce that it is sufficiently different
        [newShape, newParamValues] = self.shapeModeler.makeRandomShapeFromTriangular(self.params, self.paramsToVary,
                                                                                     self.bounds, [
                paramValue])  #USE FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
        newParamValue = newParamValues[self.paramsToVary[0] - 1, 0] #USE FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM

        #store it as an attempt
        if (self.doGroupwiseComparison):
            bisect.insort(self.params_sorted, newParamValue)
            self.shapeToParamsMapping.append(newParamValues)

        return newShape, newParamValue

    ### ---------------------------------------- GENERATE SIMULATED FEEDBACK
    def generateSimulatedFeedback(self, shape, newParamValue):
        #code in place of feedback from user: go towards goal parameter value
        goalParamValue = numpy.float64(0) #-1.5*parameterVariances[self.paramToVary-1]
        goalParamsValue = numpy.zeros((self.numPrincipleComponents, 1))
        goalParamsValue[self.paramsToVary - 1, 0] = goalParamValue
        if (self.doGroupwiseComparison):
            errors = numpy.ndarray.tolist(abs(self.shapeToParamsMapping - goalParamsValue))
            bestShape_idx = errors.index(min(errors))
        else:
            errors = [abs(self.bestParamValue - goalParamValue), abs(newParamValue - goalParamValue)]
            bestShape_idx = errors.index(min(errors))
        return bestShape_idx

    ### ------------------------------------------------ RESPOND TO FEEDBACK
    def respondToFeedback(self, bestShape):
        #update bestParamValue based on feedback received
        if (self.doGroupwiseComparison):
            params_best = self.shapeToParamsMapping[bestShape]

            self.bestParamValue = params_best[
                self.paramsToVary[0] - 1, 0]  #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
            bestParamValue_index = bisect.bisect(self.params_sorted,
                                                 self.bestParamValue) - 1  #indexing seems to start at 1 with bisect
            newBounds = [self.params_sorted[bestParamValue_index - 1], self.params_sorted[bestParamValue_index + 1]]

            #restrict bounds if they were caused by other shapes, because it must be sufficiently different to said shape(s)
            if ((bestParamValue_index - 1) > 0):  #not the default min
                newBounds[0] += self.minParamDiff
            if ((bestParamValue_index + 1) < (len(self.params_sorted) - 1)):  #not the default max
                newBounds[1] -= self.minParamDiff

            if (not (newBounds[0] > newBounds[1])):  #protect from bounds switching expected order
                self.bounds[0, :] = newBounds #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM

            diff_params = params_best - self.params
            diff = numpy.linalg.norm(diff_params)
            self.params += diff_params / 2
        else:  #do pairwise comparison with most recent shape and previous
            #restrict limits
            if ( bestShape == 'new' ):  #new shape is better
                worstParamValue = self.bestParamValue
                bestParamValue = self.newParamValue
                self.params[self.paramsToVary - 1, 0] = bestParamValue
            else:  #new shape is worse
                worstParamValue = self.newParamValue
                bestParamValue = self.bestParamValue
                self.params[self.paramsToVary - 1, 0] = bestParamValue

            if ( worstParamValue == min(self.bestParamValue, self.newParamValue) ):  #shape with lower value is worse
                self.bounds[0] = worstParamValue  #increase min bound to worst so we don't try any lower
            else:  #shape with higher value is worse
                self.bounds[1] = worstParamValue  #decrease max bound to worst so we don't try any higher

            ### ------------------------------------------------------------ ITERATE

    def generateNewShapeGivenFeedback(self, bestShape):
        #------------------------------------------- respond to feedback
        self.respondToFeedback(bestShape)  #update bounds and bestParamValue

        #----------------------------------------- check for convergence
        #continue if there are more shapes to try which are different enough
        if ((abs(self.bounds[0, 1] - self.bestParamValue) - self.minParamDiff < tol) and (abs(
                    self.bestParamValue - self.bounds[
                    0, 0]) - self.minParamDiff) < tol):  #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
            self.converged = True
        else:
            self.converged = False


        #-------------------------------------------- continue iterating
        self.numIters += 1

        #try again if shape is not good enough
        if (not self.converged):
            self.numItersConverged = 0
            [newShape, newParamValue] = self.makeShapeDifferentTo(self.bestParamValue)
            self.newParamValue = newParamValue
            return self.numItersConverged, newShape, newParamValue

        else:
            self.numItersConverged += 1
            [newShape, newParamValue] = self.makeShapeSimilarTo(self.bestParamValue)
            self.newParamValue = newParamValue
            return self.numItersConverged, newShape, newParamValue

    def getLearnedParams(self):
        return self.params

    def getLearnedShape(self):
        return self.shapeModeler.makeShape(self.params), self.params

    def getParameterBounds(self):
        return self.bounds

    def setParameterBounds(self, bounds):
        self.bounds = bounds

    def respondToDemonstration(self, shape):
        """
        Algo:
        
        1) takes the shape of the demonstration
        
        2) takes the curent learned shape
        
        3) re-performs PCA taking in account the domonstrated shape,
           then obtains a new space with new eigen vectors
           
        4) projects demonstrated and learned shapes into this new space 
           and gets their new parameters  
           
        5) updates the learned parameters as the algebric middle 
           between demonstrated parameters and curent learned parameters. 
        """
        demo_shape = ShapeModeler.normaliseShapeHeight(numpy.array(shape))
        
        # take the shape corresponding to the curent learned parameters in the curent space
        learned_shape = self.shapeModeler.makeShape(self.params)
        
        # add the demo shape to the matrix for PCA and re-compute reference-shape params
        self.shapeModeler.extendDataMat(demo_shape)
        ref_params = self.shapeModeler.refParams
        
        # re-compute parameters of the learned shape and the demo shape in the new PCA-space
        params_demo, _ = self.shapeModeler.decomposeShape(demo_shape)
        self.params, _ = self.shapeModeler.decomposeShape(learned_shape)
        
        # learning :
        diff_params = params_demo - self.params
        self.params += diff_params/2 #go towards the demonstrated shape


        #self.params[self.paramsToVary[0]-1] = params_demo[self.paramsToVary[0]-1] #ONLY USE FIRST PARAM
        #store it as an attempt (this isn't super appropriate but whatever)
        if (self.doGroupwiseComparison):
            newParamValue = self.params[
                self.paramsToVary[0] - 1, 0]  #USE ONLY FIRST PARAM FOR SELF-LEARNING ALGORITHM ATM
            #print('Demo params: '+str(self.params))
            bisect.insort(self.params_sorted, newParamValue)
            self.shapeToParamsMapping.append(self.params)
            #self.respondToFeedback(len(self.params_sorted)-3) # give feedback of most recent shape so bounds modify
        return self.shapeModeler.makeShape(self.params), self.params, params_demo
    
    def save_all(self):
        self.shapeModeler.save_all()
    
    def save_demo(self):
        self.shapeModeler.save_demo()

    def save_params(self):
        paramValue = []
        for i in range(self.numPrincipleComponents):
             paramValue.append(-self.params[i][0])
        self.shapeModeler.save_params(paramValue, self.shape_learning)
Esempio n. 22
0
def showShape(shape):
    plt.figure(1)
    plt.clf()
    ShapeModeler.normaliseAndShowShape(shape)
def showShape(shape,shapeIndex ):
    plt.figure(shapeIndex+1)
    plt.clf()
    ShapeModeler.normaliseAndShowShape(shape.path)
Esempio n. 24
0
    def find_letter(self, path):

        x,y = ShapeModeler.getShapeCentre(path)
        return self.closest_letter(x, y)
Esempio n. 25
0
    def on_touch_up(self, touch):
        global userShape

        word = []
        total_score =0
        rest = userShape

        scan = downsampleShape(userShape, numPoints_shapeModeler,xyxyFormat=True)
        shapeCentre = ShapeModeler.getShapeCentre(scan)
        scan = np.reshape(scan, (-1, 1)); #explicitly make it 2D array with only one column
        scan = ShapeModeler.normaliseShapeHeight(np.array(scan))

        scores = np.array(separator(scan))

        scores = scores/np.max(scores)
        scores = scores*np.abs(scores)
        scores[scores<0.1]=0

        indices = np.array(range(len(scores)))
        sep = indices[scores>0]
        #print zip(sep[:-1],sep[1:])
        
        for i in sep:
            x = scan[i]
            if len(scan[scan[i:numPoints_shapeModeler]<x])>0:
                scores[i]=0
            if len(scan[scan[:i]>x])>0:
                scores[i]=0
        
        u = True
        while u:
            u = False
            sep = indices[scores>0]
            for i,j in zip(sep[:-1],sep[1:]):
                if j-i<5:
                    u = True
                    if scores[i]>scores[j]:
                        scores[j] = 0
                    else:
                        scores[i] = 0

        plt.clf()
        ShapeModeler.showShape_score(scan,scores)

        word = []

        sep = indices[scores>0]
        for i,j in zip(sep[:-1],sep[1:]):

            shape = scan[i:j+1].T.tolist()[0] + scan[numPoints_shapeModeler+i:numPoints_shapeModeler+j+1].T.tolist()[0]
            shape = downsampleShape(shape, numPoints_shapeModeler)
            shape = np.reshape(shape,(-1,1))
            shape = ShapeModeler.normaliseShapeHeight(np.array(shape))

            best_letter = '?'
            errors = {}
            values = []
            for letter in abc:
                space = spaces[letter]
                error = space.getMinDist(shape)
                errors[letter] = error
                values.append(error)

            best_letter = min(errors, key = errors.get)
            word.append(best_letter)


        print 'found ' + str(word) 
        

        print '######################'
        print ''
        userShape = []
        self.canvas.remove(touch.ud['line'])
Esempio n. 26
0
settings_shapeLearners = []
userInputCaptures = []

nb_param = 10

spaces = {}

abc = [
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
]
for letter in abc:
    (shapeType, init_datasetFile, update_datasetFiles,
     datasetParam) = generateSettings(letter)
    spaces[letter] = ShapeModeler(init_filename=init_datasetFile,
                                  update_filenames=update_datasetFiles,
                                  param_filename=datasetParam,
                                  num_principle_components=nb_param)


def downsampleShape(shape, numDesiredPoints, xyxyFormat=False):
    numPointsInShape = len(shape) / 2
    if (xyxyFormat):
        #make xyxy format
        x_shape = shape[0::2]
        y_shape = shape[1::2]
    else:
        x_shape = shape[0:numPointsInShape]
        y_shape = shape[numPointsInShape:]

    if isinstance(x_shape, np.ndarray):  #convert arrays to lists for interp1d
        x_shape = (x_shape.T).tolist()[0]
Esempio n. 27
0
def showShape(shape, shapeIndex):
    plt.figure(shapeIndex+1, figsize=(3,3))
    plt.clf()
    ShapeModeler.normaliseAndShowShape(shape.path)
    plt.draw()
Esempio n. 28
0
    def on_touch_up(self, touch):
        global userShape

        word = []
        total_score = 0
        rest = userShape

        scan = downsampleShape(userShape,
                               numPoints_shapeModeler,
                               xyxyFormat=True)
        shapeCentre = ShapeModeler.getShapeCentre(scan)
        scan = np.reshape(scan, (-1, 1))
        #explicitly make it 2D array with only one column
        scan = ShapeModeler.normaliseShapeHeight(np.array(scan))

        scores = np.array(separator(scan))

        scores = scores / np.max(scores)
        scores = scores * np.abs(scores)
        scores[scores < 0.1] = 0

        indices = np.array(range(len(scores)))
        sep = indices[scores > 0]
        #print zip(sep[:-1],sep[1:])

        for i in sep:
            x = scan[i]
            if len(scan[scan[i:numPoints_shapeModeler] < x]) > 0:
                scores[i] = 0
            if len(scan[scan[:i] > x]) > 0:
                scores[i] = 0

        u = True
        while u:
            u = False
            sep = indices[scores > 0]
            for i, j in zip(sep[:-1], sep[1:]):
                if j - i < 5:
                    u = True
                    if scores[i] > scores[j]:
                        scores[j] = 0
                    else:
                        scores[i] = 0

        plt.clf()
        ShapeModeler.showShape_score(scan, scores)

        word = []

        sep = indices[scores > 0]
        for i, j in zip(sep[:-1], sep[1:]):

            shape = scan[i:j +
                         1].T.tolist()[0] + scan[numPoints_shapeModeler +
                                                 i:numPoints_shapeModeler + j +
                                                 1].T.tolist()[0]
            shape = downsampleShape(shape, numPoints_shapeModeler)
            shape = np.reshape(shape, (-1, 1))
            shape = ShapeModeler.normaliseShapeHeight(np.array(shape))

            best_letter = '?'
            errors = {}
            values = []
            for letter in abc:
                space = spaces[letter]
                error = space.getMinDist(shape)
                errors[letter] = error
                values.append(error)

            best_letter = min(errors, key=errors.get)
            word.append(best_letter)

        print 'found ' + str(word)

        print '######################'
        print ''
        userShape = []
        self.canvas.remove(touch.ud['line'])
Esempio n. 29
0
def showShape(shape ):
    plt.figure(1)
    plt.clf()
    ShapeModeler.normaliseAndShowShape(shape)
def showShape(shape, shapeIndex):
    plt.figure(shapeIndex + 1)
    plt.clf()
    ShapeModeler.normaliseAndShowShape(shape.path)