记录一次c++实现图片颜色聚类的小需求

时间:2022-12-04 07:56:29


安装visual studio 2019

安装c++的IDE ​​Visual Studio 2019安装与使用​

配置opencv环境

​​VS配置OpenCV开发环境(c++):How & Why​​windows下OpenCV的安装配置部署详细教程

代码

python实现的核心代码(这里读取的是四图层图片)

def image_process(img, o_path, p):
# 图像二维像素转换为一维
# 转换成3列
data = img[:, :, :3].reshape((-1, 3))
data = np.float32(data)

# 定义终止条件 (type,max_iter,epsilon)
criteria = (cv2.TERM_CRITERIA_EPS +
cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)

# 设置初始中心的选择
# flags = cv2.KMEANS_RANDOM_CENTERS
flags = cv2.KMEANS_PP_CENTERS

# K-Means聚类 聚集成4类
compactness, labels, centers = cv2.kmeans(data, 9, None, criteria, 10, flags)

# 图像转换回uint8二维类型
# centers = np.uint8(centers)
# new_colour 对中心点做了变换,可以直接使用聚类的中心点结果
new_centers = new_colour(centers)
# print(centers)
# print(new_centers)
res = new_centers[labels.flatten()]
# res = centers[labels.flatten()]
dst = res.reshape(img[:, :, :3].shape)
dst = np.concatenate((dst, img[:, :, 3:]), axis=2)
cv2.imwrite(os.path.join(o_path, p), dst)

c++

Mat colourProcess(Mat& img, int nums) {
if (img.empty()) {
return img;
}

int width = img.cols;
int height = img.rows;
int dims = img.channels();

int sampleCount = width * height;
Mat points(sampleCount, dims, CV_32F, Scalar());
Mat labels;
Mat centers(nums, 1, points.type());

int index = 0;

for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
index = row * width + col;
Vec3b bgr = img.at<Vec3b>(row, col);
points.at<float>(index, 0) = static_cast<int>(bgr[0]);
points.at<float>(index, 1) = static_cast<int>(bgr[1]);
points.at<float>(index, 2) = static_cast<int>(bgr[2]);
}
}
TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1);
kmeans(points, nums, labels, criteria, 3, KMEANS_PP_CENTERS, centers);
//cout << centers.at<Vec3f>(0) << endl;
//cout << centers.rows << ' ' << centers.cols << endl;
//cout << centers << endl;
vector<int> vi = calNewCenters(centers, img);
for (auto i : vi) {
cout << colorTab[i] << endl;
}

Mat result = Mat::zeros(img.size(), img.type());
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
index = row * width + col;
int label = labels.at<int>(index, 0);
result.at<Vec3b>(row, col)[0] = colorTab[vi[label]][0];
result.at<Vec3b>(row, col)[1] = colorTab[vi[label]][1];
result.at<Vec3b>(row, col)[2] = colorTab[vi[label]][2];
}
}
return result;
}

参考
​​Opencv之是什么东东​​python OpenCV 中 Kmeans 函数详解
opencv kmeans聚类 图像色彩量化为例
opencv KMeans 图像分割实例
OpenCV如何实现透明(alpha channel)图像的读取和写入