Như thay thế cho định hình lại ma trận đầu vào bằng tay, bạn có thể sử dụng OpenCV reshape chức năng để đạt được kết quả tương tự với mã ít hơn. Đây là triển khai làm việc của tôi về việc giảm số lượng màu với phương pháp K-Means (trong 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 đọc hình ảnh thành ma trận 2 chiều, 3 kênh. Cuộc gọi đầu tiên đến reshape
- img.reshape(1, img.rows() * img.cols());
- về cơ bản sẽ hủy 3 kênh thành các cột. Trong kết quả ma trận một hàng tương ứng với một điểm ảnh của hình ảnh đầu vào, và 3 cột tương ứng với các thành phần RGB.
Sau khi thuật toán K-Means kết thúc công việc và ánh xạ màu đã được áp dụng, chúng tôi gọi reshape
lần nữa - imgMapped.reshape(3, img.rows())
, nhưng bây giờ quay trở lại kênh và giảm số hàng thành số hàng ảnh gốc, định dạng ma trận ban đầu, nhưng chỉ với màu sắc giảm.
Tôi muốn biết những gì bạn đang làm trong vòng lặp trước khi khai báo biến clusterCount và cũng là những gì bạn đang làm ở cuối cho sau khi kmeans. Bạn có nghĩ rằng có thể cập nhật câu trả lời với thông tin này không? Cảm ơn! –
Vòng lặp đầu tiên sắp xếp lại dữ liệu từ hình ảnh từ ma trận (hàng, cols, 3) sang ma trận (hàng * cols, 3) (một hàng trên mỗi pixel). Vòng lặp ở cuối thay thế từng pixel trong hình ảnh bằng trung tâm cụm tương ứng để hiển thị. – sietschie
Có thể sử dụng 'Mat :: reshape()' thay vì lồng nhau cho vòng lặp? – Jayesh