Python: точечная кластеризация / усреднение - PullRequest
0 голосов
/ 13 марта 2019

У меня есть детектор, который возвращает ограничивающие рамки обнаруженных объектов, по большей части он работает нормально.Однако я хочу рассмотреть 10 кадров, а не 1 кадр, чтобы выполнить обнаружение, чтобы я мог устранить больше ложных срабатываний.

Способ, которым обычно работает мой детектор, таков:

1. Get a frame.
2. Conduct the algorithm. 
3. Record the centers into a dictionary per each frame. 

Я подумал, что это поможет уменьшить количество ложных срабатываний:

1. Set up a loop of 10: 
   1. Get a frame.
   2. Conduct the algorithm. 
   3. Record the centers into a dictionary per each frame.
2. Loop over the recorded points after every 10 frames.
3. Use a clustering algorithm or simple distance averaging
4. Get the final centers.

Итак, я уже реализовал часть этой логики.Я на шаге 1.3, мне нужно найти способ сгруппировать координаты и завершить оценку.

После 10 кадров мой словарь содержит такие значения (не может вставить все):

      (4067.0, 527.0): ['torx8', 'screw8'], 
      (4053.0, 527.0): ['torx8', 'screw1'], 
      (2627.0, 707.0): ['torx8', 'screw12'], 
      (3453.0, 840.0): ['torx6', 'screw14'], 
      (3633.0, 1373.0): ['torx6', 'screw15'], 
      (3440.0, 840.0): ['torx6', 'screw14'], 
      (3447.0, 840.0): ['torx6', 'screw14'], 
      (1660.0, 1707.0): ['torx8', 'screw3'], 
      (2633.0, 700.0): ['torx8', 'screw7'], 
      (2627.0, 693.0): ['torx8', 'screw8'], 
      (4060.0, 533.0): ['torx8', 'screw6'], 
      (3627.0, 1367.0): ['torx6', 'screw13'], 
      (2600.0, 680.0): ['torx8', 'screw15'], 
      (2607.0, 680.0): ['torx8', 'screw7']

Как вы можете заметить, большинство этих точек уже совпадают с точкамисдвиг пикселей, поэтому я пытаюсь найти способ избавиться от так называемых дубликатов.

Существует ли разумный и эффективный способ решения этой проблемы?Первое, что пришло мне в голову, было кластеризация k-средних, но я не уверен, подходит ли это к этой проблеме.

У кого-нибудь был подобный опыт?

РЕДАКТИРОВАТЬ: Хорошо, я добился определенного прогресса и смог кластеризовать точки с помощью иерархической кластеризации, потому что в моем случае у меня естьнет априорных знаний о количестве кластеров.Следовательно, требуется приближение.

# cluster now
points = StandardScaler().fit_transform(points)   
db = self.dbscan.fit(points)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_

# Number of clusters in labels, ignoring noise if present.
n_clusters_ = len(set(db.labels_)) - (1 if -1 in db.labels_ else 0)
n_noise_ = list(db.labels_).count(-1)

# Black removed and is used for noise instead.
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
        for each in np.linspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise.
        col = [0, 0, 0, 1]

    class_member_mask = (labels == k)

    xy = points[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
            markeredgecolor='k', markersize=14)

    xy = points[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
            markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

Clustering Result

, что прекрасно работает.Я могу устранить ложные срабатывания (см. Черную точку), однако я до сих пор не знаю, как получить среднее значение по кластеру.Например, после того, как я найду кластеры, как я могу зациклить каждый кластер и усреднить все значения X, Y?(Очевидно, что до StandardScaler().fit_transform(points), поскольку после этого я теряю координаты пикселей, они помещаются между минус одним и одним.)

1 Ответ

0 голосов
/ 14 марта 2019

Хорошо, наконец, я понял. Так как мне также понадобятся мои очки в их первоначальной шкале (не между -1 и 1), мне также пришлось сделать масштабирование. Во всяком случае, здесь полная магия:

def cluster_dbscan(self, points, visualize=False):

        # scale the points between -1 and 1
        scaler = StandardScaler()
        scaled_points = scaler.fit_transform(points)

        # cluster
        db = DBSCAN(eps=self.clustering_epsilon, min_samples=self.clustering_min_samples, metric='euclidean')
        db.fit(scaled_points)
        core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
        core_samples_mask[db.core_sample_indices_] = True

        # Number of clusters in labels, ignoring noise if present.
        n_clusters_ = len(set(db.labels_)) - (1 if -1 in db.labels_ else 0)
        n_noise_ = list(db.labels_).count(-1)

        if (visualize == True):
            # Black removed and is used for noise instead.
            unique_labels = set(db.labels_)
            colors = [plt.cm.Spectral(each)
                    for each in np.linspace(0, 1, len(unique_labels))]
            for k, col in zip(unique_labels, colors):
                if k == -1:
                    # Black used for noise.
                    col = [0, 0, 0, 1]

                class_member_mask = (db.labels_ == k)

                xy = scaled_points[class_member_mask & core_samples_mask]
                plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
                        markeredgecolor='k', markersize=14)

                xy = scaled_points[class_member_mask & ~core_samples_mask]
                plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
                        markeredgecolor='k', markersize=6)

            plt.title('Estimated number of clusters: %d' % n_clusters_)
            plt.show()

        # back to original scale
        points = scaler.inverse_transform(scaled_points) 

        # loop over the clusters, get the centers
        centers = np.zeros((n_clusters_, 2)) # for x and y
        for i in range(0, n_clusters_):
            cluster_points = points[db.labels_ == i]
            cluster_mean = np.mean(cluster_points, axis=0)
            centers[i, :] = cluster_mean

        # we need the original points
        return centers
...