作为手动重塑输入矩阵的替代方法,您可以使用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将图像读入二维、三通道矩阵中。首次调用reshape
- img.reshape(1, img.rows() * img.cols());
- 实际上是将3个通道展开成列。在结果矩阵中,一行对应输入图像的一个像素,3列对应RGB分量。
在K-Means算法完成其工作并应用了颜色映射之后,我们再次调用reshape
- imgMapped.reshape(3, img.rows())
,但现在将列回滚到通道,并将行数减少到原始图像的行数,从而获得原始矩阵格式,但仅具有减少的颜色。
Mat::reshape()
代替嵌套的 for 循环? - Jayesh