2012-08-09 51 views
6

Estoy considerando utilizar la aplicación Kmeans de OpenCV ya que dice ser más rápido ...cv2.kmeans en Python

Ahora estoy usando CV2 paquete y función kmeans,

No puedo entender los parámetros "descripción en su referencia:

Python: cv2.kmeans(data, K, criteria, attempts, flags[, bestLabels[, centers]]) → retval, bestLabels, centers 
samples – Floating-point matrix of input samples, one row per sample. 
clusterCount – Number of clusters to split the set by. 
labels – Input/output integer array that stores the cluster indices for every sample. 
criteria – The algorithm termination criteria, that is, the maximum number of iterations and/or the desired accuracy. The accuracy is specified as criteria.epsilon. As soon as each of the cluster centers moves by less than criteria.epsilon on some iteration, the algorithm stops. 
attempts – Flag to specify the number of times the algorithm is executed using different initial labelings. The algorithm returns the labels that yield the best compactness (see the last function parameter). 
flags – 
Flag that can take the following values: 
KMEANS_RANDOM_CENTERS Select random initial centers in each attempt. 
KMEANS_PP_CENTERS Use kmeans++ center initialization by Arthur and Vassilvitskii [Arthur2007]. 
KMEANS_USE_INITIAL_LABELS During the first (and possibly the only) attempt, use the user-supplied labels instead of computing them from the initial centers. For the second and further attempts, use the random or semi-random centers. Use one of KMEANS_*_CENTERS flag to specify the exact method. 
centers – Output matrix of the cluster centers, one row per each cluster center. 

cuál es el argumento flags[, bestLabels[, centers]]) significa? y que hay de él: → retval, bestLabels, centers?

Aquí está mi código:

import cv, cv2 
import scipy.io 
import numpy 

# read data from .mat file 
mat = scipy.io.loadmat('...') 
keys = mat.keys() 
values = mat.viewvalues() 

data_1 = mat[keys[0]] 
nRows = data_1.shape[1] 
nCols = data_1.shape[0] 
samples = cv.CreateMat(nRows, nCols, cv.CV_32FC1) 
labels = cv.CreateMat(nRows, 1, cv.CV_32SC1) 
centers = cv.CreateMat(nRows, 100, cv.CV_32FC1) 
#centers = numpy. 

for i in range(0, nCols): 
    for j in range(0, nRows): 
     samples[j, i] = data_1[i, j] 


cv2.kmeans(data_1.transpose, 
           100, 
           criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_MAX_ITER, 0.1, 10), 
           attempts=cv2.KMEANS_PP_CENTERS, 
           flags=cv2.KMEANS_PP_CENTERS, 
) 

Y me encuentro con dicho error:

flags=cv2.KMEANS_PP_CENTERS, 
TypeError: <unknown> is not a numpy array 

¿Cómo debo entender la lista de parámetros y el uso de cv2.kmeans? Gracias

Respuesta

13

la documentación sobre esta función es casi imposible de encontrar. Escribí el siguiente código de Python con un poco de prisa, pero funciona en mi máquina. Genera dos distribuciones Gaussianas multivariadas con diferentes medios y luego las clasifica usando cv2.kmeans(). Puede consultar this blog post para tener una idea de los parámetros.

importaciones de la manija:

import cv 
import cv2 
import numpy as np 
import numpy.random as r 

generar algunos puntos al azar y forma de manera apropiada:

samples = cv.CreateMat(50, 2, cv.CV_32FC1) 
random_points = r.multivariate_normal((100,100), np.array([[150,400],[150,150]]), size=(25)) 
random_points_2 = r.multivariate_normal((300,300), np.array([[150,400],[150,150]]), size=(25)) 
samples_list = np.append(random_points, random_points_2).reshape(50,2) 
random_points_list = np.array(samples_list, np.float32) 
samples = cv.fromarray(random_points_list) 

representar los puntos antes y después de la clasificación:

blank_image = np.zeros((400,400,3)) 
blank_image_classified = np.zeros((400,400,3)) 

for point in random_points_list: 
    cv2.circle(blank_image, (int(point[0]),int(point[1])), 1, (0,255,0),-1) 

temp, classified_points, means = cv2.kmeans(data=np.asarray(samples), K=2, bestLabels=None, 
criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_MAX_ITER, 1, 10), attempts=1, 
flags=cv2.KMEANS_RANDOM_CENTERS) #Let OpenCV choose random centers for the clusters 

for point, allocation in zip(random_points_list, classified_points): 
    if allocation == 0: 
     color = (255,0,0) 
    elif allocation == 1: 
     color = (0,0,255) 
    cv2.circle(blank_image_classified, (int(point[0]),int(point[1])), 1, color,-1) 

cv2.imshow("Points", blank_image) 
cv2.imshow("Points Classified", blank_image_classified) 
cv2.waitKey() 

Aquí se puede ver la puntos originales:

Points before classification

Éstos son los puntos después de que hayan sido clasificados: Points after classification

espero que esta respuesta puede ayudarle, no es una guía completa de k-medias, pero por lo menos le muestran cómo pasar los parámetros a OpenCV.

+0

vale la pena señalar que este ejemplo parece funcionar mejor que los ejemplos pitón proporcionados dentro de la Documentación de OpenCV – Chris

1

El problema aquí es data_1.transpose no es una matriz numpy.

OpenCV 2.3.1 y versiones posteriores de python no toman nada excepto numpy array como parámetros de imagen/matriz. entonces, data_1.transpose tiene que ser una matriz numpy.

En general, todos los puntos en OpenCV son de tipo numpy.ndarray

por ejemplo.

array([[[100., 433.]], 
     [[157., 377.]], 
     . 
     . 
     [[147., 247.]], dtype=float32) 

donde cada elemento de la matriz es

array([[100., 433.]], dtype=float32) 

y el elemento de esa matriz es

array([100., 433.], dtype=float32) 
Cuestiones relacionadas