2012-04-20 4 views
5

이 질문은 opencv에만 적용됩니다 : opencv 설명서에 제공된 kmeans 예제에는 2 채널 매트릭스가 있습니다.이 채널은 기능 벡터의 각 차원에 대해 하나의 채널입니다. 그러나 다른 예제 중 일부는 각 샘플에 대해 하나의 행이있는 열을 따라 기능이있는 하나의 채널 행렬이어야한다고 말합니다. 이 중 어느 것이 맞습니까?opencv kmeans 클러스터링 입력 행렬

cv::Mat inputSamples(numSamples, numFeatures, CV_32F) 

답변

28

정답 cv::Mat inputSamples(numSamples, numFeatures, CV_32F)이다 이것은 :

cv::Mat inputSamples(numSamples, 1, CV32FC(numFeatures)) 

또는 이와 I은 5 차원의 특징 벡터가있는 경우

, 어떻게 I가 사용하는 입력 행렬이어야 . OpenCV의 문서에 대한 kmeanssays :

샘플 - 입력 샘플들의 부동 소수점 행렬 샘플 당 하나의 행

그래서 같이 N 차원 플로트 부동 소수점 벡터가 아닌 다른 옵션. 어떤 예가 그러한 행동을 제안 했습니까?

kmeans의 사용법을 보여주는 나에게도 작은 예제가 있습니다. 이는 이미지의 픽셀 클러스터 및 결과를 표시 수동 입력 행렬을 재 형성에 대한 대안으로서, 적은 코드와 유사한 결과를 얻을 OpenCV의 reshape 기능을 사용할 수

#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 

using namespace cv; 

int main(int argc, char** argv) 
{ 
    Mat src = imread(argv[1], 1); 
    Mat samples(src.rows * src.cols, 3, CV_32F); 
    for(int y = 0; y < src.rows; y++) 
    for(int x = 0; x < src.cols; x++) 
     for(int z = 0; z < 3; z++) 
     samples.at<float>(y + x*src.rows, z) = src.at<Vec3b>(y,x)[z]; 


    int clusterCount = 15; 
    Mat labels; 
    int attempts = 5; 
    Mat centers; 
    kmeans(samples, clusterCount, labels, TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10000, 0.0001), attempts, KMEANS_PP_CENTERS, centers); 


    Mat new_image(src.size(), src.type()); 
    for(int y = 0; y < src.rows; y++) 
    for(int x = 0; x < src.cols; x++) 
    { 
     int cluster_idx = labels.at<int>(y + x*src.rows,0); 
     new_image.at<Vec3b>(y,x)[0] = centers.at<float>(cluster_idx, 0); 
     new_image.at<Vec3b>(y,x)[1] = centers.at<float>(cluster_idx, 1); 
     new_image.at<Vec3b>(y,x)[2] = centers.at<float>(cluster_idx, 2); 
    } 
    imshow("clustered image", new_image); 
    waitKey(0); 
} 
+0

나는 clusterCount 변수 선언 전에 루프에서 무엇을하고 있는지, 그리고 kmeans 후에 for의 끝에 무엇을하고 있는지 알고 싶습니다. 이 정보로 답변을 업데이트 할 수 있다고 생각하십니까? 감사! –

+0

첫 번째 루프는 (rows, cols, 3) 행렬에서 (rows * cols, 3) 행렬 (픽셀 당 하나의 행)까지 이미지의 데이터를 재정렬합니다. 끝에있는 루프는 이미지의 각 픽셀을 시각화를 위해 해당 클러스터 중심으로 대체합니다. – sietschie

+0

for 중첩 된 루프 대신'Mat :: reshape()'를 사용할 수 있습니까? – Jayesh

1

.

private final static int MAX_ITER = 10; 
private final static int CLUSTERS = 16; 

public static Mat colorMapKMeans(Mat img, int K, int maxIterations) { 

    Mat m = img.reshape(1, img.rows() * img.cols()); 
    m.convertTo(m, CvType.CV_32F); 

    Mat bestLabels = new Mat(m.rows(), 1, CvType.CV_8U); 
    Mat centroids = new Mat(K, 1, CvType.CV_32F); 
    Core.kmeans(m, K, bestLabels, 
       new TermCriteria(TermCriteria.COUNT | TermCriteria.EPS, maxIterations, 1E-5), 
       1, Core.KMEANS_RANDOM_CENTERS, centroids); 
    List<Integer> idx = new ArrayList<>(m.rows()); 
    Converters.Mat_to_vector_int(bestLabels, idx); 

    Mat imgMapped = new Mat(m.size(), m.type()); 
    for(int i = 0; i < idx.size(); i++) { 
     Mat row = imgMapped.row(i); 
     centroids.row(idx.get(i)).copyTo(row); 
    } 

    return imgMapped.reshape(3, img.rows()); 
} 

public static void main(String[] args) { 
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 
    Highgui.imwrite("result.png", 
     colorMapKMeans(Highgui.imread(args[0], Highgui.CV_LOAD_IMAGE_COLOR), 
      CLUSTERS, MAX_ITER)); 
} 

OpenCV의 2 차원, 3 채널 행렬로 화상을 판독 : 여기 색상 (자바) K-수단 방법 카운트 감소 내 작업의 구현이다. reshape - img.reshape(1, img.rows() * img.cols());으로 첫 번째 호출 - 본질적으로 3 개의 채널을 열로 푸십시오. 결과 매트릭스에서 한 행은 입력 이미지의 한 픽셀에 해당하고, 세 열은 RGB 구성 요소에 해당합니다.

K-수단 알고리즘은 작업을 완료, 색상 매핑은 우리가 다시 reshape 전화를 적용 한 후 - 따라서 다시 받고, imgMapped.reshape(3, img.rows())을,하지만 지금 채널로 다시 열을 압연하고, 원본 이미지의 행 번호에 행 번호를 감소 원본 매트릭스 형식이지만 색상 만 줄입니다.

+0

I clone ie를 사용하는 경우이 방법을 사용하기 전에 이미지가 먼저 연속적으로 처리되어야한다고 생각합니다. http://docs.opencv.org/2.4/modules/core/doc/basic_structures.html#mat-iscontinuous – ejectamenta

+0

img.clone()에서와 같이 clone을 사용합니다. reshape (1, img.rows() * img.cols()) 그러면 이미지가 연속적으로 표시됩니다 (원본 이미지는 변경되지 않음) – ejectamenta

관련 문제