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

安装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(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)图像的读取和写入

你可能感兴趣的:(机器视觉,C++,opencv,k-means)