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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录一次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<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)图像的读取和写入


以上是关于记录一次c++实现图片颜色聚类的小需求的主要内容,如果未能解决你的问题,请参考以下文章

K 均值聚类:更新每个聚类的质心并选择颜色的功能

如何加快openCV中的颜色聚类?

Python图像处理丨基于K-Means聚类的图像区域分割

如何根据颜色值聚类彩色图像? [关闭]

机器学习应用:颜色量化实现示例

sklearn聚类算法用于图片压缩与图片颜色直方图分类