kmeans实现图像像素分类

代码

import tkinter as tkfrom tkinter import filedialogfrom PIL import Image, ImageTkimport numpy as np
import random
import mathclass Cluster(object):def __init__(self):# pixels是像素的意思,这里定义一个像素组用来存放像素的值self.pixels = []# 创建一个中心点self.centroid = Nonedef addPoint(self, pixels):# 将像素值存放到这个空的pixels数组当中self.pixels.append(pixels)def setNewCentroid(self):# 这里通道R在像素点中进行轮寻R就会得到一个数组,里面是所有像素点R通道的像素值R = [colour[0] for colour in self.pixels]G = [colour[1] for colour in self.pixels]B = [colour[2] for colour in self.pixels]# 求R,G,B所有像素点的平均值R = sum(R) / len(R)R= round(R)G = sum(G) / len(G)G = round(G)B = sum(B) / len(B)B = round(B)self.centroid = (R,G,B)return self.centroid
class Kmeans(object):# 初始化k个簇,最大迭代次数,阈值用来判断中心点与上一代中心点的误差,小于就结束,图片大小def __init__(self, k=10, max_iteration=10, min_distance=5.0, size=200):self.k = kself.max_iterations = max_iterationself.min_distance = min_distanceself.size = (size, size)def run(self, image):self.image = image#将图像缩放到指定大小self.sizeself.image.thumbnail(self.size)# 将image转化为数组self.p = np.array(image)# 打印出来的是每个像素的数值[113, 110,  75]这是一个像素点RGB值self.pixels = np.array(image.getdata(), dtype=np.uint8)# return self.pixels,self.p# 创建了一个长度为 self.k 的列表,其中每个元素都被初始化为 None。这里,self.k 是一个类的属性,代表了你想要创建的簇(clusters)的数量。self.clusters = [None for i in range(self.k)]self.oldClusters = None#  self.pixels 数组中随机选择 self.k 个像素点,并将这些像素点的值存储到 randomPixels 列表中randomPixels = random.sample(list(self.pixels), self.k)# 这里循环每个簇for idx in range(self.k):self.clusters[idx] = Cluster()self.clusters[idx].centroid = randomPixels[idx]iterations = 0while self.shouldExit(iterations) is False:self.oldClusters = [cluster.centroid for cluster in self.clusters]for pixel in self.pixels:self.assignClusters(pixel)for cluster in self.clusters:cluster.setNewCentroid()iterations += 1return [cluster.centroid for cluster in self.clusters]#分配簇,将像素分配到簇def assignClusters(self, pixel):# 可能是用来比较的shortest = float('Inf')这是设定距离为无穷大shortest = float('Inf')for cluster in self.clusters:distance = self.calcDistance(cluster.centroid, pixel)if distance < shortest:shortest = distancenearest = clusternearest.addPoint(pixel)# 计算像素到中心点的欧式距离def calcDistance(self, a, b):# 计算欧氏距离result = math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2)# result = np.sqrt(sum((a-b) ** 2))return result# 迭代结束def shouldExit(self, iterations):if self.oldClusters is None:return Falsefor idx in range(self.k):dist = self.calcDistance(np.array(self.clusters[idx].centroid),np.array(self.oldClusters[idx]))if dist <self.min_distance:return Trueif iterations <= self.max_iterations:return Falsereturn True# 显示原图像def showImage(self):self.image.show()# 显示每个200*200的图像,颜色是每个聚类中心像素def showCentroidColours(self):# 创建cluster * 200大小的图像total_width = len(self.clusters) * 200# 整体高度是200total_height = 200big_image = Image.new("RGB", (total_width, total_height), "white")# 计算每个小图片在大图上的位置x_offset = 0y_offset = 0for cluster in self.clusters:image = Image.new("RGB", (200, 200), cluster.centroid)# 将小图片粘贴到大图上big_image.paste(image, (x_offset, y_offset))# 更新 x 偏移量以准备下一个图片的位置x_offset += 200# new_width = 1000# new_height = 400# new_image = Image.new('RGB', (new_width, new_height), 'white')## big_image = np.array(big_image)# image = np.concatenate((self.p, big_image), axis=0)# image = np.vstack((image, big_image))# big_image.show()big_image = big_image.resize((500, 30))return big_image# y_offset = 0# for img in zip([image, big_image]):#     new_image.paste(img, (0, y_offset))#     y_offset = y_offset + 1# new_image.show()# new_image.show()# 颜色图像显示def showClustering(self):# 创建一个与localPixels相同长度的localPixels =[None] * len(self.image.getdata())for idx, pixel in enumerate(self.image.getdata()):shortest = float('Inf')for cluster in self.clusters:distance =self.calcDistance(cluster.centroid, pixel)if distance < shortest:shortest = distancenearest = clusterlocalPixels[idx] = nearest.centroidw,h = self.image.size# 将localPixel转换为一个大小为(h, w, 3)的图像localPixels = np.asarray(localPixels)\.astype('uint8')\.reshape((h, w, 3))# 颜色图像显示colourMap = Image.fromarray(localPixels)colourMap = colourMap.resize((200, 200))return colourMap# colourMap.show()
# 初始化Tkinter窗口root = tk.Tk()root.title("图片处理GUI")# 全局变量用于存储图片和图片数据
image_path = Noneimage_data = Nonedef open_image():global image_path, image_data, image# 打开文件对话框,选择图片文件file_path = filedialog.askopenfilename(title="选择图片", filetypes=[("图像文件", "*.png;*.jpg;*.jpeg;*.bmp;*.gif")])if file_path:# 使用PIL打开图片image = Image.open(file_path)# 转换为Tkinter可以显示的格式image = image.resize((200, 200))tk_image = ImageTk.PhotoImage(image)# 展示图片label_image.config(image=tk_image)label_image.config(padx=10, pady=5)label_image.image = tk_image# 存储图片路径和图片数据(转换为numpy数组)image_path = file_pathimage_data = np.array(image)def apply_kmeans():global image_data, image_pathif image_data is not None:# 将图片数据重塑为二维数组,每行是一个像素,每列是RGB值image = Image.open(image_path)image = image.resize((200, 200))# 初始化自定义的Kmeans类并运行算法k = Kmeans()# k.showImage()k.run(image)segmented_image_pil = k.showCentroidColours()# 展示处理后的图片segmented_tk_image = ImageTk.PhotoImage(segmented_image_pil)label_segmented.config(image=segmented_tk_image)label_segmented.image = segmented_tk_imageelse:print("请先打开一张图片!")# 创建按钮来打开图片def apply_kmeans1():global image_data, image_pathif image_data is not None:# 将图片数据重塑为二维数组,每行是一个像素,每列是RGB值image = Image.open(image_path)image = image.resize((200, 200))# 初始化自定义的Kmeans类并运行算法k = Kmeans()# k.showImage()k.run(image)segmented_image_pil = k.showClustering()# 展示处理后的图片segmented_tk_image = ImageTk.PhotoImage(segmented_image_pil)label_segmented1.config(image=segmented_tk_image)label_segmented1.image = segmented_tk_imageelse:print("请先打开一张图片!")# 创建按钮来打开图片button_open = tk.Button(root, text="打开图片", command=open_image)
# 使用 grid 布局,并指定在第0行第0列
button_open.grid(row=0, column=0, sticky="ew")# 创建标签来展示原始图片label_image = tk.Label(root)
# sticky="news" 表示填充所有方向
label_image.grid(row=1, column=0, sticky="news")# 创建按钮来应用K-means算法button_kmeans = tk.Button(root, text="应用K-means", command=apply_kmeans)button_kmeans.grid(row=0, column=1, sticky="ew")# 创建标签来展示K-means处理后的图片label_segmented = tk.Label(root)label_segmented.grid(row=1, column=1, sticky="news")button_kmeans1 = tk.Button(root, text="返回图像", command=apply_kmeans1)button_kmeans1.grid(row=0, column=2, sticky="ew")label_segmented1 = tk.Label(root)label_segmented1.grid(row=1, column=2, sticky="news")# 运行Tkinter事件循环
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.columnconfigure(2, weight=1)root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/828056.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HubSpot功能有哪些?

HubSpot是一个功能丰富的平台&#xff0c;主要涵盖市场营销、销售、客户服务和客户关系管理&#xff08;CRM&#xff09;等领域。以下是HubSpot的一些主要功能&#xff1a; 市场营销自动化&#xff1a;HubSpot允许用户制定和执行多渠道的市场营销活动&#xff0c;包括创建和管…

力扣HOT100 - 105. 从前序与中序遍历序列构造二叉树

解题思路&#xff1a; 分治 以中序遍历为参照&#xff0c;用前序遍历的节点构建二叉树。 root 1 index - left表示前序遍历右子树的开始节点&#xff0c;即当前节点的下一个节点左子树长度。 class Solution {int[] preorder;HashMap<Integer, Integer> map new Ha…

C#基础:WPF中常见控件的布局基础

一、用ViewBox实现放缩控件不变 二、布局代码 <Window x:Class"WpfApp1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"Title"MainWindow"…

小瓶清洗桶抗酸碱耐高温PFA清洗器半导体实验清洗用

PFA清洗桶&#xff0c;也叫PFA清洗器、PFA小瓶清洗桶&#xff0c;主要用于清洗浸泡实验室小型PFA溶样罐和烧杯等&#xff0c;带有密封螺纹盖&#xff0c;可以用于摇晃&#xff0c;高纯耐高温材质可放置电热板上加热使用。 特点&#xff1a;可拆卸倒酸口&#xff0c;可安全倒出酸…

ctfshow菜狗杯 web 无算力以及easyPytHon_P

web签到题 error_reporting(0); highlight_file(__FILE__);eval($_REQUEST[$_GET[$_POST[$_COOKIE[CTFshow-QQ群:]]]][6][0][7][5][8][0][9][4][4]);套娃传参 中文要编码 Cookies &#xff1a;CTFshow-QQ%E7%BE%A4:a POST:ab GET:?bc&c[6][0][7][5][8][0][9][4][4]syste…

干货收藏:CRM系统帮助中心设计教程

CRM系统&#xff0c;也就是客户关系管理系统&#xff0c;是企业运营中的得力助手&#xff0c;但太复杂的CRM系统有时候用起来也挺让人头疼的。所以&#xff0c;一个好用、易懂的帮助中心就显得尤为重要啦&#xff01;今天我来跟大家分享一下关于CRM系统帮助中心的设计教程。 1.…

09 MySQL--操作真题

1. not in 用一条 SQL 语句&#xff0c;查询出每门课程都大于 80 分的人。 分析&#xff1a; 去重查询出存在课程小于 80 分的人&#xff0c;设为集合A查询不在集合 A 中的人 # 第一步&#xff1a;找小于等于80分的学员姓名 select distinct name from t_student where fens…

Transformer - 特征预处理

Transformer - 特征预处理 flyfish 原始数据 train_data.values [[ 5.827 2.009 1.599 0.462 4.203 1.34 30.531][ 5.76 2.076 1.492 0.426 4.264 1.401 30.46 ][ 5.76 1.942 1.492 0.391 4.234 1.31 30.038][ 5.76 1.942 1.492 0.426 4.234 1.31…

Linux命令超详细介绍

目录 安装 Linux的目录结构&#xff1a; Linux命令入门&#xff1a; Linux命令的基础格式&#xff1a; 例子&#xff1a; ls 参数 选项 注意&#xff1a; 目录切换命令&#xff1a;cd/pwd cd: pwd: 相对路径和绝对路径&#xff1a; mkdir 不用参数&#xff1a; …

【Node.js工程师养成计划】之打造自己的脚手架工具

一、创建全局的自定义命令 1、打开一个空文件夹&#xff0c;新建一个bin文件夹&#xff0c;在bin文件夹下新建cli.js文件&#xff0c;js文件可以命名为cli.js&#xff08;您随意&#xff09; 2、在cli.js文件中的开头&#xff08;&#xff01;&#xff01;&#xff09;写下面这…

NeRF in the Wild: Neural Radiance Fields for Unconstrained Photo Collections

NeRF in the Wild: Neural Radiance Fields for Unconstrained Photo Collections(野外的 NERF: 用于无约束照片采集的神经辐射场&#xff09; Abstract 我们提出了一种基于学习的方法来合成新的视图的复杂场景使用只有非结构化的收集野生照片。我们建立在神经辐射场(neRF)的…

对于地理空间数据,PostGIS扩展如何在PostgreSQL中存储和查询地理信息?

文章目录 一、PostGIS扩展简介二、PostGIS存储地理空间数据1. 创建空间数据表2. 插入空间数据 三、PostGIS查询地理空间数据1. 查询指定范围内的地理空间数据2. 计算地理空间数据之间的距离3. 对地理空间数据进行缓冲区分析 四、总结 地理空间数据是指描述地球表面物体位置、形…

11、【桥接模式】让将抽象和实现分离,使得它们可以独立地变化

你好&#xff0c;我是程序员雪球。 今天我们来聊聊 23 种设计模式中&#xff0c;一种常见的结构型模式&#xff0c;桥接模式。聊聊它的设计思想、应用场景&#xff0c;以及如何使用。 一、设计思想 桥接模式&#xff08;Bridge Pattern&#xff09;是一种结构型设计模式&#…

Python slice切片

1. 切片简介 取一个str、list、tuple的部分元素是非常常见的操作 切片 译自英文单词slice,指的是一部分切片 根据 步长step 从原序列中取出一部分元素组成新序列切片适用于 字符串、列表、元组 2. 切片的格式 字符串[开始索引:结束索引:步长] 包含开始索引, 不包含结束索…

vue+springboot实验个人信息,修改密码,忘记密码功能实现

前端部分 新增Person&#xff08;个人页面&#xff09;&#xff0c;Password&#xff08;修改密码页面&#xff09;&#xff0c;还需要对Manager&#xff0c;login页面进行修改 router文件夹下的index.js&#xff1a; import Vue from vue import VueRouter from vue-router i…

在 vue3 中使用高德地图

前言&#xff1a;定位地图位置所需要的经纬度&#xff0c;可以通过 拾取坐标 获取。 一&#xff1a;快速上手 1. 安装依赖 npm install amap/amap-jsapi-loader # or pnpm add amap/amap-jsapi-loader # or yarn add amap/amap-jsapi-loader 2. 创建组件 src/components/Ma…

飞书小技巧:markdown导出

文章目录 下载Feishu2Md飞书应用配置配置feishu2md工具绑定应用导出markdown 下载Feishu2Md Feishu2Md 飞书应用配置 进入飞书开发者后台 https://open.feishu.cn/app。 点击“创建企业自建应用”&#xff0c;并填写应用名称等信息。而后点击创建。 PS: 此处作者创建应用名…

C++ | Leetcode C++题解之第42题接雨水

题目&#xff1a; 题解&#xff1a; class Solution { public:int trap(vector<int>& height) {int n height.size();if (n 0) {return 0;}vector<int> leftMax(n);leftMax[0] height[0];for (int i 1; i < n; i) {leftMax[i] max(leftMax[i - 1], he…

【Linux系统编程】

Linux系统编程 一.文件编程1.常用API1.1 打开&#xff1a;open1.2 读写&#xff1a;write/read1.3 光标定位: lseek1.4 创建&#xff1a;creat1.4 关闭&#xff1a;close 2.文件的打开及创建3.文件的写入4.文件的读取5.文件描述符5.代码实现cp指令6.编程实现修改文件配置7.写一…

实现Node.js安装与配置。

一 、Node.js简介 Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;用于构建高性能、可扩展的网络应用程序。它发布于2009年5月&#xff0c;由Ryan Dahl开发&#xff0c;允许使用JavaScript进行服务器端编程&#xff0c;使开发者能够在前后端都使用同一种编程…