作爲替代手動重塑輸入矩陣,可以使用的OpenCV reshape函數來實現類似的結果用更少的代碼。下面是降低顏色與K-means法(在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的讀取圖像到二維,3信道矩陣。首先撥打reshape
- img.reshape(1, img.rows() * img.cols());
- 實質上將3個通道展開爲列。在結果矩陣中,一行對應於輸入圖像的一個像素,而3列對應於RGB分量。
後K-means算法完成其工作,並且顏色映射得到了應用,我們再次呼籲reshape
- imgMapped.reshape(3, img.rows())
,但現在滾動體列回通道,減少行數爲原始圖像的行數,從而找回了原始矩陣格式,但只有減少的顏色。
我想知道你在循環之前在clusterCount變量聲明中所做的事情,以及你在kmeans之後的for循環結尾所做的事情。你認爲用這些信息更新答案是可能的嗎?謝謝! – 2013-02-11 19:17:27
第一個循環將來自圖像的數據從(行,列,3)矩陣重新排列到(rows * cols,3)矩陣(每個像素一行)。最後的循環將圖像中的每個像素替換爲相應的聚類中心以進行可視化。 – sietschie 2013-02-12 09:25:07
是否可以使用'Mat :: reshape()'而不是嵌套for循環? – Jayesh 2016-10-26 13:41:16