Exemplo n.º 1
0
Arquivo: ma.py Projeto: Ylannl/masb2d
    def filter_radiuscon(self, alpha, k, inner='in'):
        '''Filter noisy points based on contuity in radius when compared to near points'''
        self.D['filter_radiuscon'] = np.zeros(self.m) == True
        
        for i, p in enumerate(self.D['coords']):
            c_p = self.D['ma_coords_'+inner][i]
            r_p = self.D['ma_radii_'+inner][i]
            if c_p != None:
                indices,dists = self.flann.nn_index(p, k+1)

                # print indices,dists
                M = []
                for index in indices[0][1:]:
                    M.append(self.D['ma_coords_'+inner][index])
                # print M

                L = []
                for m in M:
                    # projection_len = np.linalg.norm(proj(m-p,c_p-p))
                    val = np.linalg.norm(p-m) * cos_angle(m-p, c_p-p)
                    L.append(val)
                # print L, alpha * max(L), r_p

                if r_p < alpha * max(L):
                    self.D['filter_radiuscon'][i] = True
                else:
                    self.D['filter_radiuscon'][i] = False
Exemplo n.º 2
0
    def filter_radiuscon(self, alpha, k, inner='in'):
        '''Filter noisy points based on contuity in radius when compared to near points'''
        self.D['filter_radiuscon'] = np.zeros(self.m) == True

        for i, p in enumerate(self.D['coords']):
            c_p = self.D['ma_coords_' + inner][i]
            r_p = self.D['ma_radii_' + inner][i]
            if c_p != None:
                indices, dists = self.flann.nn_index(p, k + 1)

                # print indices,dists
                M = []
                for index in indices[0][1:]:
                    M.append(self.D['ma_coords_' + inner][index])
                # print M

                L = []
                for m in M:
                    # projection_len = np.linalg.norm(proj(m-p,c_p-p))
                    val = np.linalg.norm(p - m) * cos_angle(m - p, c_p - p)
                    L.append(val)
                # print L, alpha * max(L), r_p

                if r_p < alpha * max(L):
                    self.D['filter_radiuscon'][i] = True
                else:
                    self.D['filter_radiuscon'][i] = False
Exemplo n.º 3
0
Arquivo: ma.py Projeto: Ylannl/masb2d
    def decimate_heur(self, xi=0.1, k=3, omega=math.pi/20, inner='in'):
        '''Decimation based on heuristics as defined in ma (2012)'''
        cos_omega = math.cos(omega)
        self.D['filtered'] = np.zeros(self.m) == True
        
        for i, p in enumerate(self.D['coords']):
            c_p = self.D['ma_coords_'+inner][i]
            r_p = self.D['ma_radii_'+inner][i]
            if not np.isnan(c_p[0]):
                # test 1 - angle feature points
                p_ = self.D['coords'][self.D['ma_f2_'+inner][i]]
                if cos_angle(p, c_p, p_) < cos_omega:
                    self.D['filtered'][i] = True
                    break

                # test 2 - ball containmment
                indices,dists = self.flann.nn_index(p, k+1)

                M = [ ( self.D['ma_coords_'+inner][index], self.D['ma_radii_'+inner][index] ) for index in indices[0][1:] ]

                for m, r_m in M:
                    # can this medial ball (c_p) be contained by medial ball at m?
                    if np.linalg.norm(m-c_p) + r_p < r_m * (1+xi):
                        self.D['filtered'][i] = True
                        break
Exemplo n.º 4
0
    def update_plot(self, p_i, inner):

        q_indices = self.master.ma.D['ma_shrinkhist_' + inner][p_i]
        if len(q_indices) == 0: return  # perhaps also clear the plot...
        q_coords = self.master.ma.D['coords'][q_indices]
        p_n = self.master.ma.D['normals'][p_i]

        # if not is_inner: p_n = -p_n
        p = self.master.ma.D['coords'][p_i]

        radii = [compute_radius(p, p_n, q) for q in q_coords]
        centers = [p - p_n * r for r in radii]
        thetas = [
            acos(cos_angle(p - c, q - c)) * (180 / pi)
            for c, q in zip(centers, q_coords)
        ]
        lambdas = [norm(p - q) for q in q_coords]

        r_initial = radii[0]
        radii_proportional = [r / r_initial for r in radii]
        lambda_proportional = [l / lambdas[0] for l in lambdas]

        self.plotline_a.set_xdata(range(1, 1 + len(thetas)))
        self.plotline_b.set_xdata(range(1, 1 + len(thetas)))
        self.plotline_c.set_xdata(range(1, 1 + len(thetas)))
        self.plotline_a.set_ydata(thetas)
        self.plotline_b.set_ydata(radii_proportional)
        self.plotline_c.set_ydata(lambda_proportional)

        self.canvas.draw()
Exemplo n.º 5
0
    def decimate_heur(self, xi=0.1, k=3, omega=math.pi / 20, inner='in'):
        '''Decimation based on heuristics as defined in ma (2012)'''
        cos_omega = math.cos(omega)
        self.D['filtered'] = np.zeros(self.m) == True

        for i, p in enumerate(self.D['coords']):
            c_p = self.D['ma_coords_' + inner][i]
            r_p = self.D['ma_radii_' + inner][i]
            if not np.isnan(c_p[0]):
                # test 1 - angle feature points
                p_ = self.D['coords'][self.D['ma_f2_' + inner][i]]
                if cos_angle(p, c_p, p_) < cos_omega:
                    self.D['filtered'][i] = True
                    break

                # test 2 - ball containmment
                indices, dists = self.flann.nn_index(p, k + 1)

                M = [(self.D['ma_coords_' + inner][index],
                      self.D['ma_radii_' + inner][index])
                     for index in indices[0][1:]]

                for m, r_m in M:
                    # can this medial ball (c_p) be contained by medial ball at m?
                    if np.linalg.norm(m - c_p) + r_p < r_m * (1 + xi):
                        self.D['filtered'][i] = True
                        break
Exemplo n.º 6
0
    def update_plot(self, p_i, inner):

        q_indices = self.master.ma.D['ma_shrinkhist_'+inner][p_i]
        if len(q_indices) == 0: return # perhaps also clear the plot...
        q_coords = self.master.ma.D['coords'][q_indices]
        p_n = self.master.ma.D['normals'][p_i]
        
        # if not is_inner: p_n = -p_n
        p = self.master.ma.D['coords'][p_i]

        radii = [ compute_radius(p,p_n,q) for q in q_coords ]
        centers = [ p - p_n * r for r in radii ]
        thetas = [ acos(cos_angle(p-c,q-c))*(180/pi) for c, q in zip(centers, q_coords) ]
        lambdas = [ norm(p-q) for q in q_coords ]

        r_initial = radii[0]
        radii_proportional = [r/r_initial for r in radii]
        lambda_proportional = [l/lambdas[0] for l in lambdas]

        self.plotline_a.set_xdata(range(1,1+len(thetas)))
        self.plotline_b.set_xdata(range(1,1+len(thetas)))
        self.plotline_c.set_xdata(range(1,1+len(thetas)))
        self.plotline_a.set_ydata(thetas)
        self.plotline_b.set_ydata(radii_proportional)
        self.plotline_c.set_ydata(lambda_proportional)
 
        self.canvas.draw()
Exemplo n.º 7
0
Arquivo: ma.py Projeto: Ylannl/masb2d
    def compute_theta(self, inner='in'):
        '''Compute for every boundary point p, corresponding ma point m, and other feature point p_ the angle p-m-p_ '''
        self.D['theta_'+inner] = np.zeros(self.m)
        self.D['theta_'+inner][:] = np.nan

        for i, p in enumerate(self.D['coords']):
            c_p = self.D['ma_coords_'+inner][i]
            if not np.isnan(c_p[0]):
                p_ = self.D['coords'][self.D['ma_f2_'+inner][i]]
                self.D['theta_'+inner][i] = cos_angle(p-c_p, p_-c_p)
Exemplo n.º 8
0
    def compute_theta(self, inner='in'):
        '''Compute for every boundary point p, corresponding ma point m, and other feature point p_ the angle p-m-p_ '''
        self.D['theta_' + inner] = np.zeros(self.m)
        self.D['theta_' + inner][:] = np.nan

        for i, p in enumerate(self.D['coords']):
            c_p = self.D['ma_coords_' + inner][i]
            if not np.isnan(c_p[0]):
                p_ = self.D['coords'][self.D['ma_f2_' + inner][i]]
                self.D['theta_' + inner][i] = cos_angle(p - c_p, p_ - c_p)
Exemplo n.º 9
0
    def filter_thetacon(self,
                        theta_min=37,
                        theta_delta=45,
                        theta_absmin=26,
                        inner='in'):
        """Filter noisy points based on continuity in separation angle as function of the ith iteration in the shrinking ball process"""
        # TODO: points with k=1 now receive no filtering... just discard them?
        self.D['filter_thetacon'] = np.zeros(self.m) == True

        theta_min *= (math.pi / 180)
        theta_delta *= (math.pi / 180)
        theta_absmin *= (math.pi / 180)

        def find_optimal_theta(thetas):
            theta_prev = thetas[0]
            for j, theta in enumerate(thetas[1:]):
                if ((theta_prev - theta) >= theta_delta
                        and theta <= theta_min) or (theta < theta_absmin):
                    return j
                theta_prev = theta
            # print
            return None

        for i, p in enumerate(self.D['coords']):
            p_n = self.D['normals'][i]

            q_indices = self.D['ma_shrinkhist_' + inner][i]
            if len(q_indices) <= 1: continue

            q_coords = self.D['coords'][q_indices]

            # if not is_inner: p_n = -p_n

            radii = [compute_radius(p, p_n, q) for q in q_coords]
            centers = [p - p_n * r for r in radii]
            thetas = [
                math.acos(cos_angle(p - c, q - c))
                for c, q in zip(centers, q_coords)
            ]

            optimal_theta = find_optimal_theta(thetas)
            # print optimal_theta
            if optimal_theta is not None:
                self.D['filter_thetacon'][i] = True
Exemplo n.º 10
0
Arquivo: ma.py Projeto: Ylannl/masb2d
    def filter_thetacon(self, theta_min=37, theta_delta=45, theta_absmin=26, inner='in'):
        """Filter noisy points based on continuity in separation angle as function of the ith iteration in the shrinking ball process"""
        # TODO: points with k=1 now receive no filtering... just discard them?
        self.D['filter_thetacon'] = np.zeros(self.m) == True

        theta_min *= (math.pi/180)
        theta_delta *= (math.pi/180)
        theta_absmin *= (math.pi/180)

        def find_optimal_theta(thetas):
            theta_prev = thetas[0]
            for j, theta in enumerate(thetas[1:]):
                if ( (theta_prev - theta) >= theta_delta and theta <= theta_min ) or (theta < theta_absmin):
                    return j
                theta_prev = theta
            # print
            return None

        for i, p in enumerate(self.D['coords']):
            p_n = self.D['normals'][i]

            q_indices = self.D['ma_shrinkhist_'+inner][i]
            if len(q_indices) <= 1: continue

            q_coords = self.D['coords'][q_indices]
            
            # if not is_inner: p_n = -p_n

            radii = [ compute_radius(p,p_n,q) for q in q_coords ]
            centers = [ p - p_n * r for r in radii ]
            thetas = [ math.acos(cos_angle(p-c,q-c)) for c, q in zip(centers, q_coords) ]

            optimal_theta = find_optimal_theta(thetas)
            # print optimal_theta
            if optimal_theta is not None:
                self.D['filter_thetacon'][i] = True
Exemplo n.º 11
0
Arquivo: ma.py Projeto: Ylannl/masb2d
    def compute_balls(self, inner=True, verbose=False):
        """Balls shrinking algorithm. Set `inner` to False when outer balls are wanted."""

        for i, pn in enumerate(zip(self.D['coords'], self.D['normals'])):
            p, n = pn
            if not inner:
                n = -n
            
            # when approximating 1st point initialize q with random point not equal to p
            q=p 
            # if i==0:
            #     while (q == p).all():
            #         random_index = int(rand(1)*self.D['coords'].shape[0])
            #         q = self.D['coords'][random_index]
            #     r = compute_radius(p,n,q)

            # forget optimization of r:
            r=self.SuperR
            
            msg='New iteration, initial r = {:.5}'.format(float(r))
            if verbose: print msg
            yield {'stage': 1, 'geom': (p,n), 'msg':msg}

            r_ = None
            c = None
            j = -1
            q_i = None
            q_history = []
            while True:
                j+=1
                # initialize r on last found radius
                if j>0:
                    r = r_
                elif j==0 and i>0:
                    r = r

                # compute ball center
                c = p - n*r
                #
                q_i_previous = q_i
                
                msg = 'Current iteration: #' + str(i) +', r = {:.5}'.format(float(r))
                if verbose: print msg
                yield {'stage': 2, 'geom': (q,c,r), 'msg':msg}

                ### FINDING NEAREST NEIGHBOR OF c

                # find closest point to c and assign to q
                indices,dists = self.flann.nn_index(c, 2)
                # dists, indices = self.kd_tree.query(array([c]), k=2)
                candidate_c = self.D['coords'][indices]
                # candidate_n= self.D['normals'][indices]
                # print 'candidates:', candidates
                q = candidate_c[0][0]
                # q_n = candidate_n[0][0]
                q_i = indices[0][0]
                
                # yield {'stage': 3, 'geom': (q)}

                # What to do if closest point is p itself?
                if (q==p).all():
                    # 1) if r==SuperR, apparantly no other points on the halfspace spanned by -n => that's an infinite ball
                    if r == self.SuperR: 
                        r_ = r
                        break
                    # 2) otherwise just pick the second closest point
                    else: 
                        q = candidate_c[0][1]
                        # q_n = candidate_n[0][1]
                        q_i = indices[0][1]
                
                q_history.append(q_i)
                # compute new candidate radius r_
                r_ = compute_radius(p,n,q)

                # print r, r_, p-c, q-c, cos_angle(p-c, q-c)

                ### BOUNDARY CASES

                # if r_ < 0 closest point was on the wrong side of plane with normal n => start over with SuperRadius on the right side of that plance
                if r_ < 0: 
                    r_ = self.SuperR
                # if r_ > SuperR, stop now because otherwise in case of planar surface point configuration, we end up in an infinite loop
                elif r_ > self.SuperR:
                # elif cos_angle(p-c, q-c) >= self.normal_thres:
                    r_ = self.SuperR
                    break

                c_ = p - n*r_
                # this seems to work well against noisy ma points.
                if self.denoise_absmin is not None:
                    if math.acos(cos_angle(p-c_, q-c_)) < self.denoise_absmin and j>0 and r_>np.linalg.norm(q-p):
                        # msg = 'Current iteration: -#' + str(i) +', r = {:.5}'.format(float(r))
                        # yield {'stage': 2, 'geom': (q,c_,r), 'msg':msg}
                        # keep previous radius:
                        r_=r
                        q_i = q_i_previous
                        break

                if self.denoise_delta is not None and j>0:
                    theta_now = math.acos(cos_angle(p-c_, q-c_))
                    q_previous = self.D['coords'][q_i_previous]
                    theta_prev = math.acos(cos_angle(p-c_, q_previous-c_))
                    
                    if theta_prev-theta_now > self.denoise_delta and theta_now < self.denoise_min and r_>np.linalg.norm(q-p):
                        # print "theta_prev:",theta_prev/math.pi * 180
                        # print "theta_now:",theta_now/math.pi * 180
                        # print "self.denoise_delta:",self.denoise_delta/math.pi * 180
                        # print "self.denoise_min:",self.denoise_min/math.pi * 180

                        # keep previous radius:
                        r_=r
                        q_i = q_i_previous
                        break

                if self.detect_planar != None:
                    if math.acos( cos_angle(q-p, -n) ) > self.detect_planar and j<2:
                        # yield {'stage': 2, 'geom': (q,p - n*r_,r_), 'msg':msg}
                        r_= self.SuperR
                        # r_= r
                        # q_i = q_i_previous
                        break

                ### NORMAL STOP CONDITION

                # stop iteration if r has converged
                if r == r_:
                    break
            
            if inner: inout = 'in'
            else: inout = 'out'
            
            if r_ >= self.SuperR:
                pass
            else:
                self.D['ma_radii_'+inout][i] = r_
                self.D['ma_coords_'+inout][i] = c
                self.D['ma_f1_'+inout][i] = i
                self.D['ma_f2_'+inout][i] = q_i
            self.D['ma_shrinkhist_'+inout].append(q_history[:-1])
Exemplo n.º 12
0
    def compute_balls(self, inner=True, verbose=False):
        """Balls shrinking algorithm. Set `inner` to False when outer balls are wanted."""

        for i, pn in enumerate(zip(self.D['coords'], self.D['normals'])):
            p, n = pn
            if not inner:
                n = -n

            # when approximating 1st point initialize q with random point not equal to p
            q = p
            # if i==0:
            #     while (q == p).all():
            #         random_index = int(rand(1)*self.D['coords'].shape[0])
            #         q = self.D['coords'][random_index]
            #     r = compute_radius(p,n,q)

            # forget optimization of r:
            r = self.SuperR

            msg = 'New iteration, initial r = {:.5}'.format(float(r))
            if verbose: print msg
            yield {'stage': 1, 'geom': (p, n), 'msg': msg}

            r_ = None
            c = None
            j = -1
            q_i = None
            q_history = []
            while True:
                j += 1
                # initialize r on last found radius
                if j > 0:
                    r = r_
                elif j == 0 and i > 0:
                    r = r

                # compute ball center
                c = p - n * r
                #
                q_i_previous = q_i

                msg = 'Current iteration: #' + str(i) + ', r = {:.5}'.format(
                    float(r))
                if verbose: print msg
                yield {'stage': 2, 'geom': (q, c, r), 'msg': msg}

                ### FINDING NEAREST NEIGHBOR OF c

                # find closest point to c and assign to q
                indices, dists = self.flann.nn_index(c, 2)
                # dists, indices = self.kd_tree.query(array([c]), k=2)
                candidate_c = self.D['coords'][indices]
                # candidate_n= self.D['normals'][indices]
                # print 'candidates:', candidates
                q = candidate_c[0][0]
                # q_n = candidate_n[0][0]
                q_i = indices[0][0]

                # yield {'stage': 3, 'geom': (q)}

                # What to do if closest point is p itself?
                if (q == p).all():
                    # 1) if r==SuperR, apparantly no other points on the halfspace spanned by -n => that's an infinite ball
                    if r == self.SuperR:
                        r_ = r
                        break
                    # 2) otherwise just pick the second closest point
                    else:
                        q = candidate_c[0][1]
                        # q_n = candidate_n[0][1]
                        q_i = indices[0][1]

                q_history.append(q_i)
                # compute new candidate radius r_
                r_ = compute_radius(p, n, q)

                # print r, r_, p-c, q-c, cos_angle(p-c, q-c)

                ### BOUNDARY CASES

                # if r_ < 0 closest point was on the wrong side of plane with normal n => start over with SuperRadius on the right side of that plance
                if r_ < 0:
                    r_ = self.SuperR
                # if r_ > SuperR, stop now because otherwise in case of planar surface point configuration, we end up in an infinite loop
                elif r_ > self.SuperR:
                    # elif cos_angle(p-c, q-c) >= self.normal_thres:
                    r_ = self.SuperR
                    break

                c_ = p - n * r_
                # this seems to work well against noisy ma points.
                if self.denoise_absmin is not None:
                    if math.acos(
                            cos_angle(p - c_, q - c_)
                    ) < self.denoise_absmin and j > 0 and r_ > np.linalg.norm(
                            q - p):
                        # msg = 'Current iteration: -#' + str(i) +', r = {:.5}'.format(float(r))
                        # yield {'stage': 2, 'geom': (q,c_,r), 'msg':msg}
                        # keep previous radius:
                        r_ = r
                        q_i = q_i_previous
                        break

                if self.denoise_delta is not None and j > 0:
                    theta_now = math.acos(cos_angle(p - c_, q - c_))
                    q_previous = self.D['coords'][q_i_previous]
                    theta_prev = math.acos(cos_angle(p - c_, q_previous - c_))

                    if theta_prev - theta_now > self.denoise_delta and theta_now < self.denoise_min and r_ > np.linalg.norm(
                            q - p):
                        # print "theta_prev:",theta_prev/math.pi * 180
                        # print "theta_now:",theta_now/math.pi * 180
                        # print "self.denoise_delta:",self.denoise_delta/math.pi * 180
                        # print "self.denoise_min:",self.denoise_min/math.pi * 180

                        # keep previous radius:
                        r_ = r
                        q_i = q_i_previous
                        break

                if self.detect_planar != None:
                    if math.acos(cos_angle(q - p,
                                           -n)) > self.detect_planar and j < 2:
                        # yield {'stage': 2, 'geom': (q,p - n*r_,r_), 'msg':msg}
                        r_ = self.SuperR
                        # r_= r
                        # q_i = q_i_previous
                        break

                ### NORMAL STOP CONDITION

                # stop iteration if r has converged
                if r == r_:
                    break

            if inner: inout = 'in'
            else: inout = 'out'

            if r_ >= self.SuperR:
                pass
            else:
                self.D['ma_radii_' + inout][i] = r_
                self.D['ma_coords_' + inout][i] = c
                self.D['ma_f1_' + inout][i] = i
                self.D['ma_f2_' + inout][i] = q_i
            self.D['ma_shrinkhist_' + inout].append(q_history[:-1])