当前位置: 首页 > news >正文

毕业设计 基于Kmeans的图像分割算法软件设计

文章目录

  • 0 简介
  • 1 Kmeans聚类算法基本原理
  • 2 基于Kmeans图像分割算法流程
  • 4 代码运行结果及评价
  • 5 最后

0 简介

今天学长向大家分享一个毕业设计项目

毕业设计 基于Kmeans的图像分割算法软件设计

项目运行效果:

毕业设计 基于kmean的图像分割

🧿 项目分享:见文末!

1 Kmeans聚类算法基本原理

K-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。

以彩色图像为例:基于彩色图像的RGB三通道为xyz轴建立空间直角坐标系,那么一副图像上的每个像素点与该空间直角坐标系建立了一 一映射(双射)的关系。

从空间直角坐标系中随机取 k 个点,作为 k个簇的各自的中心。计算所有像素点到k个簇心的距离,并将所有像素点划分至与其距离最小的簇类。自此聚类完成。其中,距离定义为欧氏距离:

其中r,g,b分别表示红绿蓝三通道,r1,g1,b1为彩色图片中某像素点;r0,g0,b0表示某簇类的簇心。

2 基于Kmeans图像分割算法流程

Note:彩色图像的操作是基于一个三维空间
1、加载图像,获取图像的所有像素点并将其转换为样本数据。
2、开始迭代
a)、初始化簇心坐标。
a)、更新簇心坐标,遍历样本数据中的数据点并计算数据点与所有簇心的距离。对于某数据点计算得到的与所有簇类的欧氏距离中,取欧氏距离最小所对应的簇类作为该数据点对应的类。
c)、计算更新后的簇心坐标与更新前的簇心坐标的均方误差。若均方误差仍大于某阈值,则重复b),反之结束迭代。
Kmeans的详细算法流程参考博文:
https://www.cnblogs.com/pinard/p/6164214.html
三、代码主函数部分
1、加载图片

Mat src, dst; src = imread("J20.jpg"); namedWindow("输入图像", WINDOW_AUTOSIZE); imshow("输入图像", src);

2、初始化颜色(图像分割后需要上色)

Scalar colorTab[] = { Scalar(0,0,255), Scalar(0,255,0), Scalar(255,0,0), Scalar(0,255,255), Scalar(255,0,255), };

3、初始化簇类数,并将所有的像素点全部转换为样本数据

int sampleCount = width*height; int clusterCount = 5; Mat points(sampleCount, dims, CV_32F, Scalar(10)); //将彩色图像的像素点转换为样本数据 int index = 0; for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { index = row*width + col; Vec3b bgr = src.at<Vec3b>(row, col); points.at<float>(index, 0) = static_cast<int>(bgr[0]);//b points.at<float>(index, 1) = static_cast<int>(bgr[1]);//g points.at<float>(index, 2) = static_cast<int>(bgr[2]);//r } }

4、利用Kmeans算法对样本数据分类

centers, feature = Kmeans(points, clusterCount, sampleCount);

5、
显示图像分割后的结果

//显示图像分割结果 Mat result = Mat::zeros(src.size(), src.type()); int index1 = 0; for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { index1 = row*width + col; int label = feature.at<float>(index1, 3); result.at<Vec3b>(row, col)[0] = colorTab[label][0]; result.at<Vec3b>(row, col)[1] = colorTab[label][1]; result.at<Vec3b>(row, col)[2] = colorTab[label][2]; } } imshow("基于Kmeans聚类的图像分割", result);

四、代码子函数部分
1、初始化聚类中心

//初始化簇心 Mat centers = Mat::zeros(clusterCount, 1, CV_32FC3);//4行3列 centers.at<float>(0, 0) = 150; centers.at<float>(0, 1) = 180; centers.at<float>(0, 2) = 200; centers.at<float>(1, 0) = 20; centers.at<float>(1, 1) = 25; centers.at<float>(1, 2) = 37; centers.at<float>(2, 0) = 80; centers.at<float>(2, 1) = 100; centers.at<float>(2, 2) = 140; centers.at<float>(3, 0) = 226; centers.at<float>(3, 1) = 234; centers.at<float>(3, 2) = 235;

2、利用Kmeans算法进行迭代

Mat feature = Mat::zeros(sampleCount, 1, CV_32FC4); float *distance = new float[sampleCount]; int epoch = 0; while (true) { for (int row = 0; row < points.rows; row++) { for (int i = 0; i < centers.rows; i++) { distance[i] = pow((points.at<float>(row, 0) - centers.at<float>(i, 0)), 2) + pow((points.at<float>(row, 1) - centers.at<float>(i, 1)), 2) + pow((points.at<float>(row, 2) - centers.at<float>(i, 2)), 2); } float min = distance[0]; int flag = 0; for (int i = 0; i < clusterCount; i++) { if (min > distance[i]) { min = distance[i]; flag = i; } } feature.at<float>(row, 0) = points.at<float>(row, 0); feature.at<float>(row, 1) = points.at<float>(row, 1); feature.at<float>(row, 2) = points.at<float>(row, 2); feature.at<float>(row, 3) = flag; } float new_center_r = 0, new_center_g = 0, new_center_b = 0; float *temp = new float[clusterCount]; for (int i = 0; i < clusterCount; i++) { int num = 0; float sum_center_r = 0, sum_center_g = 0, sum_center_b = 0; for (int row = 0; row < sampleCount; row++) { if (feature.at<float>(row, 3) == i) { sum_center_b = sum_center_b + feature.at<float>(row, 0); sum_center_g = sum_center_g + feature.at<float>(row, 1); sum_center_r = sum_center_r + feature.at<float>(row, 2); num++; } } new_center_b = sum_center_b / num; new_center_g = sum_center_g / num; new_center_r = sum_center_r / num; temp[i] = pow((new_center_b - centers.at<float>(i, 0)), 2) + pow((new_center_g - centers.at<float>(i, 1)), 2) + pow((new_center_r - centers.at<float>(i, 2)), 2); centers.at<float>(i, 0) = new_center_b; centers.at<float>(i, 1) = new_center_g; centers.at<float>(i, 2) = new_center_r; } float total = 0; float mean_square_error = 0; for (int i = 0; i < clusterCount; i++) { total = total + temp[i]; } mean_square_error = total / 4; if (epoch % 1 == 0) cout << "epoch:" << epoch << "\terror of mean square:" << mean_square_error << endl; if (mean_square_error < 0.01) break; epoch++; }

4 代码运行结果及评价

输入图片:

2、迭代过程

3、聚类结果

如上图,从左至右分别为Blue、Green、Red通道;从上之下分别是五个簇心的坐标(像素值)。

4、图像分割结果

如上图,图像被清晰的分为了五个部分:背景为蓝色、歼20的迷彩涂装分为了红黄两色,颜色最暗的地方为紫色,颜色次暗的地方为绿色。
另外,对于大数据,经典的Kmeans算法显然处理速度太慢,但对于彩色图像,使用经典Kmeans算法对其进行分割,其所耗时长在可接受的范围内。
至此完全实现了基于Kmeans聚类算法的图像分割,经验证,其结果与利用OpenCV提供的API得到的效果完全一致!

5 最后

项目运行效果:


🧿 项目分享:见文末!

http://www.cnnetsun.cn/news/3841.html

相关文章:

  • Vue-ECharts:3分钟上手的数据可视化神器
  • SageAttention终极指南:量化注意力机制加速深度学习推理
  • 3步实现Buzz语音识别准确率突破性提升的实战方法
  • 鲸鱼图像分割与识别:使用Fovea R50 FPN模型在COCO数据集上的训练与评估
  • 终极指南:掌握brew reinstall,轻松解决软件包问题
  • 基于YOLO11-SEG的白蘑菇检测与识别系统_RVB
  • 广州企业如何找到真正靠谱的软件开发公司?
  • 降本增效真实录:一家中型纺织厂的AI验布技术引入之路
  • PHP + GraphQL 构建电商API的5大核心技巧(高手都在用)
  • PyScripter终极指南:轻量级Python IDE快速上手教程
  • Wan2.2-T2V-A14B能否生成老电影胶片噪点风格?怀旧滤镜
  • 杰理之添加一路AUX叠加播放【篇】
  • 科学记忆法助高中生高效学习
  • iCloud云端照片终极备份方案:3步快速下载完整指南
  • ChanlunX缠论插件:让技术分析从复杂到简单的革命性突破
  • 多参数水质监测站:集成式传感赋能水质监测
  • Kratos WordPress主题完整使用指南:专注阅读体验的终极解决方案
  • 2025建木DevOps工具完整指南:图形化编排CI/CD流程的实战手册
  • 游戏编程模式终极指南:重构你的游戏开发思维框架
  • AutoUnipus智能刷课助手:高效解决U校园学习难题的专业方案
  • 分布式系统5大痛点及其工作流解决方案
  • Wan2.2-T2V-A14B能否生成未来城市概念视频?
  • 换电脑数据如何迁移?掌握这几招,迁移效率翻倍!
  • 【.NET 9高性能编程秘籍】:从堆内存布局到分配器优化的实战策略
  • WABT工具链深度解析:从入门到精通的WebAssembly格式转换
  • 云电脑系列13:老师学生都方便:云电脑搭好标准化教学环境,零门槛上课实训
  • Python 包结构探测器:一键查看任意包的模块结构
  • 云电脑系列14:企业IT运维变简单:云电脑批量装软件、统一管安全、故障快恢复
  • z命令的智能记忆系统:.z文件如何让你的终端导航快如闪电
  • Layer弹层组件完整指南:5分钟快速上手Web弹层开发