본문 바로가기
Autonomous Vehicle/Computer Vision

OpenCV : Euclidean Clustering White Pixels Algorithm

by kim.jeff 2020. 8. 26.

이진화된 이미지 픽셀데이터에서 거리기반 군집화인 유클라디언 클러스터링 알고리즘을 사용하여 분류하는 예제를 알아보도록 하겠습니다.

 


OpenCV : Euclidean Clustering White Pixels Algorithm 


1. 전체코드

#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>

using namespace std;
using namespace cv;

struct EuclideanDistanceFunctor
{
       int _dist2;
       EuclideanDistanceFunctor(int dist) : _dist2(dist*dist) {}

       bool operator()(const Point& lhs, const Point& rhs) const
       {
           return ((lhs.x - rhs.x)*(lhs.x - rhs.x) + (lhs.y - rhs.y)*(lhs.y - rhs.y)) < _dist2;
       }
};

int main()
{
       // Load the image (grayscale)
       Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

       // Get all non black points
       vector<Point> pts;
       findNonZero(img, pts);

       // Define the distance between clusters
       int euclidean_distance = 20;

       // Apply partition 
       // All pixels within the the given distance will belong to the same cluster

       vector<int> labels;

       // With functor
       //int n_labels = partition(pts, labels, EuclideanDistanceFunctor(euclidean_distance));

       // With lambda function
       int th2 = euclidean_distance * euclidean_distance;
       int n_labels = partition(pts, labels, [th2](const Point& lhs, const Point& rhs) {
           return ((lhs.x - rhs.x)*(lhs.x - rhs.x) + (lhs.y - rhs.y)*(lhs.y - rhs.y)) < th2;
       });


       // Store all points in same cluster, and compute centroids
       vector<vector<Point>> clusters(n_labels);
       vector<Point> centroids(n_labels, Point(0,0));

       for (int i = 0; i < pts.size(); ++i)
       {
           clusters[labels[i]].push_back(pts[i]);
           centroids[labels[i]] += pts[i];
       }
       for (int i = 0; i < n_labels; ++i)
       {
           centroids[i].x /= clusters[i].size();
           centroids[i].y /= clusters[i].size();
       }

       // Draw results

       // Build a vector of random color, one for each class (label)
       vector<Vec3b> colors;
       for (int i = 0; i < n_labels; ++i)
       {
           colors.push_back(Vec3b(rand() & 255, rand() & 255, rand() & 255));
       }

       // Draw the points
       Mat3b res(img.rows, img.cols, Vec3b(0, 0, 0));
       for (int i = 0; i < pts.size(); ++i)
       {
           res(pts[i]) = colors[labels[i]];
       }

       // Draw centroids
       for (int i = 0; i < n_labels; ++i)
       {
           circle(res, centroids[i], 3, Scalar(colors[i][0], colors[i][1], colors[i][2]), CV_FILLED);
           circle(res, centroids[i], 6, Scalar(255 - colors[i][0], 255 - colors[i][1], 255 - colors[i][2]));
       }


       imshow("Clusters", res);
       waitKey();

       return 0;
}

2. 실험 데이터 및 결과

색깔별로 그리고 그 중심점에 원을 그려서 클러스터링을 시각화 하였네요. 코드 설명은 주석을 통해 확인하세요. 


<참고문헌>

https://stackoverrun.com/ko/q/5215019

 

C++ 및 OpenCV : 흰색 픽셀 클러스터링 알고리즘

저는 이진 이미지 (흑백 픽셀)가 있습니다. 서로 간의 거리에 따라 흰색 픽셀을 그룹 (개체)으로 클러스터하고 싶습니다. 각 클러스터의 중심. (보라색에 프레임) 클러스터링 방법은 결과 I를 제��

stackoverrun.com