技术标签: python
今天学长向大家分享一个毕业设计项目
毕业设计 基于Kmeans的图像分割算法软件设计
项目运行效果:
毕业设计 基于kmean的图像分割
项目获取:
https://gitee.com/sinonfin/algorithm-sharing
K-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。
以彩色图像为例:基于彩色图像的RGB三通道为xyz轴建立空间直角坐标系,那么一副图像上的每个像素点与该空间直角坐标系建立了一 一映射(双射)的关系。
从空间直角坐标系中随机取 k 个点,作为 k个簇的各自的中心。计算所有像素点到k个簇心的距离,并将所有像素点划分至与其距离最小的簇类。自此聚类完成。其中,距离定义为欧氏距离:
其中r,g,b分别表示红绿蓝三通道,r1,g1,b1为彩色图片中某像素点;r0,g0,b0表示某簇类的簇心。
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++;
}
输入图片:
2、迭代过程
3、聚类结果
如上图,从左至右分别为Blue、Green、Red通道;从上之下分别是五个簇心的坐标(像素值)。
4、图像分割结果
如上图,图像被清晰的分为了五个部分:背景为蓝色、歼20的迷彩涂装分为了红黄两色,颜色最暗的地方为紫色,颜色次暗的地方为绿色。
另外,对于大数据,经典的Kmeans算法显然处理速度太慢,但对于彩色图像,使用经典Kmeans算法对其进行分割,其所耗时长在可接受的范围内。
至此完全实现了基于Kmeans聚类算法的图像分割,经验证,其结果与利用OpenCV提供的API得到的效果完全一致!
项目运行效果:
项目获取:
文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文
文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作 导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释: cwy_init/init_123..._达梦数据库导入导出
文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js
文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6
文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输
文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...
文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure
文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割
文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答
文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。
文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入
文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf