Como alternativa a la remodelación de la matriz de entrada manual, puede utilizar la función de OpenCV reshape para lograr resultado similar con menos código. Aquí está mi aplicación trabaja de Reducción del número de colores con el método de K-medias (en Java):
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 lee la imagen en 2, matriz de 3 dimensiones del canal. Primera llamada al reshape
- img.reshape(1, img.rows() * img.cols());
- esencialmente desenrolla 3 canales en columnas. En la matriz resultante, una fila corresponde a un píxel de la imagen de entrada, y 3 columnas corresponden a componentes RGB.
Después de K-medias algoritmo terminó su trabajo, y la asignación de colores se ha aplicado, que llamamos reshape
nuevo - imgMapped.reshape(3, img.rows())
, pero ahora rodando columnas de nuevo en los canales, y la reducción de los números de fila para el número de fila imagen original, consiguiendo de este modo recuperar el formato de matriz original, pero solo con colores reducidos.
Me gustaría saber qué está haciendo en el ciclo antes de la declaración de la variable clusterCount y también lo que está haciendo al final en el para después de los kmeans. ¿Crees que es posible actualizar la respuesta con esta información? ¡Gracias! –
El primer ciclo reordena los datos de la imagen desde una matriz (rows, cols, 3) a una matriz (rows * cols, 3) (una fila por píxel). El bucle al final reemplaza cada píxel en la imagen con el centro del clúster correspondiente para la visualización. – sietschie
¿Es posible usar 'Mat :: reshape()' en lugar de anidados para bucles? – Jayesh