2013-10-01 2 views
2

저는 이진 이미지 (흑백 픽셀)가 있습니다. 서로 간의 거리에 따라 흰색 픽셀을 그룹 (개체)으로 클러스터하고 싶습니다. 각 클러스터의 중심.C++ 및 OpenCV : 흰색 픽셀 클러스터링 알고리즘

Image

(보라색에 프레임) 클러스터링 방법은 결과 I를 제공 할 경우

내가 확인하고 싶습니다 :

나는에 일해야하는 예제 이미지 찾고 있는데, 그럴 가치가 있음을 알기 전에 알고리즘을 직접 구현하는 것을 피하려고합니다.
OpenCV에 내가 필요한 것을 할 수있는 방법이 있습니까?

답변

0

이미지의 클러스터 수를 알고있는 경우 OpenCV에 구현 된 K-Means algorithm을 사용할 수 있습니다.

그 외에도이 작업을위한 다른 쉬운 해결책을 모릅니다. 이 클러스터링을 구현하고 싶다면 this paper이 도움이 될 수 있습니다. 이는 고정 된 수의 클러스터가 없어야하는 k-means를 채택한 것입니다.

+0

클러스터의 수는 다를 수 있으며, 그들이 사전에 얼마나 많은 알 수있는 방법이 없습니다. 예, 직접 구현해야 할 것 같습니다. –

2

나는 이것이 꽤 오래된 것을 알고 있지만 어쩌면이 대답이 도움이 될 수 있습니다.


당신은 등가 클래스로 설정 요소를 분리 할, partition를 사용할 수 있습니다.

주어진 유클리드 거리 내의 모든 점 으로 등가 클래스를 정의 할 수 있습니다.. 이 함수는 람다 함수 (C++ 11) 또는 펑터 (코드의 두 예제 참조)가 될 수 있습니다.

enter image description here

당신은 모두 흰색 픽셀 것을 볼 수있다 : 내가 가진 (20)의 유클리드 거리를 사용하여

enter image description here

이 이미지에서 시작

(I 수동 보라색 테두리를 제거) 유클리드 거리 내에있는 것들은 동일한 클러스터 (같은 색)에 할당된다. 원은 각 클러스터의 중심을 나타냅니다.

코드 :

#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; 
}