03、K-means聚类实现步骤与基于K-means聚类的图像压缩(2)

03、K-means聚类实现步骤与基于K-means聚类的图像压缩(2)

工程下载:K-means聚类实现步骤与基于K-means聚类的图像压缩

其他:
03、K-means聚类实现步骤与基于K-means聚类的图像压缩(1)
03、K-means聚类实现步骤与基于K-means聚类的图像压缩(2)

K-means聚类的图像压缩

开始学习机器学习啦,已经把吴恩达的课全部刷完了,现在开始熟悉一下复现代码。对这个手写数字实部比较感兴趣,作为入门的素材非常合适。

1、K-means聚类图像压缩基本思路

我的想法是:这副图像存在许多很大一块区域的颜色相近,既然相近,我们就用一种颜色替代一大块区域中的各色。我们可以人为的用8、16、24、32种颜色表示整幅图像的颜色,也即说明聚类的个数为8、16、24、32。

上述说法是不准确的,准确的说法是:这副图像虽然很大,但是其有些部分颜色相近,这些颜色相近的部分不论是否出自同一位置,我们都可以用一种颜色进行替代。我们可以使用8、16、24、32种颜色来代替原来图中的所有颜色。

在使用K-means聚类进行图像压缩时,聚类的对象仅仅是颜色而已,和颜色的所在位置是否相近无关,也就是说这种压缩不改变像素的大小,只改变色彩的鲜艳程度而已。具体来讲,聚类是在三维坐标下进行的,三个坐标轴分别为R G B 的具体数值。

下面简单介绍这种压缩算法的压缩效果。对于一张RGB888的彩色图像,假设其大小为1920 * 1080,那么其存储所需的大小为1920*1080 * 24(因为RGB分别用8位来表示,因此每个像素点有24位来表示其颜色)。

此处有24位来表示颜色,可表示的颜色个数为2^24种,假设此处使用K=16的K-means聚类算法对其进行压缩,则代表压缩后的图像只包含K种颜色。

那么对于每个像素点而言,则需要log2(K)=4位来进行表示,此外还需要K*24的空间来存储对应的24位RGB颜色,因此压缩后的总空间为1920 * 1080 * log2(K)+ K * 24。

对于一张1920 * 1080 的图像,压缩比例和K的对应关系如下所示:
在这里插入图片描述

2、K-means聚类图像压缩底层实现

此处从K-means聚类的底层原理进行实现,不调用库函数:

import numpy as np
from matplotlib import pyplot as plt# 随机初始化聚类初始优化点
def kMeans_init_centroids(X, K):# 随机重新排序样本的索引randidx = np.random.permutation(X.shape[0])# 取前K个样本作为聚类中心centroids = X[randidx[:K]]return centroidsdef find_closest_centroids(X, centroids):# 获取聚类中心的数量,也即K值K = centroids.shape[0]# 初始化一个数组用于存储每个样本所属的聚类中心的索引idx = np.zeros(X.shape[0], dtype=int)# 遍历数据集中的每个样本for i in range(X.shape[0]):# 初始化一个列表用于存储当前样本到每个聚类中心的距离distance = []# 计算当前样本到每个聚类中心的距离for j in range(centroids.shape[0]):# 使用欧几里得距离公式计算样本i与聚类中心j之间的距离norm_ij = np.linalg.norm(X[i] - centroids[j])distance.append(norm_ij)# 找出距离列表中的最小值,该最小值对应的索引就是当前样本所属的聚类中心idx[i] = np.argmin(distance)# 返回每个样本所属的聚类中心的索引数组return idxdef compute_centroids(X, idx, K):# 获取数据集X的行数m和列数n# m表示样本数量,n表示每个样本的特征数量m, n = X.shape# 初始化一个K x n的零矩阵,用于存储K个聚类中心# K表示聚类数量,n表示特征数量centroids = np.zeros((K, n))# 遍历每个聚类中心for k in range(K):# 从数据集X中选择属于当前聚类k的所有样本# idx是一个长度为m的数组,存储了每个样本所属的聚类中心的索引points = X[idx == k]# 计算属于当前聚类k的所有样本的平均值,得到聚类中心# axis=0表示按列计算平均值centroids[k] = np.mean(points, axis=0)# 返回计算得到的K个聚类中心return centroidsdef run_kMeans(X, initial_centroids, max_iters=10):# 获取数据集X的行数m和列数n# m表示样本数量,n表示每个样本的特征数量m, n = X.shape# 获取初始聚类中心的数量KK = initial_centroids.shape[0]# 将初始聚类中心赋值给centroids变量centroids = initial_centroids# 将初始聚类中心复制给previous_centroids变量,用于后续比较聚类中心是否发生变化previous_centroids = centroids# 初始化一个长度为m的零数组,用于存储每个样本所属的聚类中心的索引idx = np.zeros(m)# 开始运行K-means算法,最多迭代max_iters次for i in range(max_iters):# 输出当前迭代进度print("K-Means iteration %d/%d" % (i, max_iters - 1))# 调用find_closest_centroids函数,为数据集X中的每个样本找到最近的聚类中心,并返回索引数组idx = find_closest_centroids(X, centroids)# 调用compute_centroids函数,根据每个样本所属的聚类中心和索引数组,计算新的聚类中心centroids = compute_centroids(X, idx, K)# 返回最终的聚类中心和每个样本所属的聚类中心的索引return centroids, idx# Load an image of a bird
original_img = plt.imread('K_means_data/bird_small.png')
# Visualizing the image
plt.imshow(original_img)
plt.show()
print("Shape of original_img is:", original_img.shape)# Divide by 255 so that all values are in the range 0 - 1
# RGB各8位,将其归一化至0-1
original_img = original_img / 255
# Reshape the image into an m x 3 matrix where m = number of pixels
# 数组的内容是图像各个点的颜色,m x 3
X_img = np.reshape(original_img, (original_img.shape[0] * original_img.shape[1], 3))# K就是要使用几种颜色进行表达
K = 8
max_iters = 10# Using the function you have implemented above. 初始化的是rgb的数值,因此是包含三个元素的数组
initial_centroids = kMeans_init_centroids(X_img, K)# Run K-Means - this takes a couple of minutes
centroids, idx = run_kMeans(X_img, initial_centroids, max_iters)# Represent image in terms of indices
X_recovered = centroids[idx, :]# Reshape recovered image into proper dimensions
X_recovered = np.reshape(X_recovered, original_img.shape)# Display original image
fig, ax = plt.subplots(1, 2, figsize=(8, 8))
plt.axis('off')ax[0].imshow(original_img * 255)
ax[0].set_title('Original')
ax[0].set_axis_off()# Display compressed image
ax[1].imshow(X_recovered * 255)
ax[1].set_title('Compressed with %d colours' % K)
ax[1].set_axis_off()
plt.show()

3、K-means聚类图像压缩库函数实现

此处直接使用from sklearn.cluster import KMeans来进行K-means聚类,代码更加简洁了:

import matplotlib.pyplot as plt  # plt 用于显示图片
import matplotlib.image as mpimg  # mpimg 用于读取图片
from sklearn.cluster import KMeans
import numpy as nporiginal_pixel = mpimg.imread('K_means_data/bird_small.png')
pixel = original_pixel.reshape((128 * 128, 3))kmeans = KMeans(n_clusters=8, random_state=0).fit(pixel)newPixel = []
for i in kmeans.labels_:newPixel.append(list(kmeans.cluster_centers_[i, :]))newPixel = np.array(newPixel)
newPixel = newPixel.reshape((128, 128, 3))# Display original image
fig, ax = plt.subplots(1, 2, figsize=(8, 8))
plt.axis('off')
ax[0].imshow(original_pixel)
ax[0].set_title('Original')
ax[0].set_axis_off()# Display compressed image
ax[1].imshow(newPixel)
ax[1].set_title('Compressed with %d colours' % kmeans.n_clusters)
ax[1].set_axis_off()
plt.show()

4、小结

虽说写了那么多,但是实际上还是没有输出压缩后的图片文件。压缩后的图片的大小是1920 * 1080 * log2(K)的,此外还需要K * 24位来存储颜色表,或许没办法用普通png来表示了?那应该怎么生成文件嘞?
之后一定填坑。

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

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

相关文章

在easyswoole 中,配置文件如何加载外部配置

在一个项目中 目录结构是这样的 网站的公共配置,包括一些数据库连接配置,redis连接配置 /web/config/redis_config.php/web/config/mysql_config.php 下面是Easyswoole 项目目录 所有的配置均放在ES项目中的Config目录中 文件名且采用大驼峰命名。如…

深度学习神经网络加大batchsize训练速度降低的原因(GPT)

在深度学习中,批量大小(batch size)是指在每次参数更新时一次性输入到模型中的样本数量。通常情况下,增大批量大小可以提高训练过程中的计算效率,因为可以利用并行计算的优势。然而,当批量大小过大时&#…

Linux 命令ln

1什么是链接 ln在Linux中 ln 命令的功能是为某一个文件在另外一个位置建立一个同步的链接,当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录&#xff0…

SpringBoot监控Redis事件通知

Redis的事件通知 Redis事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发, 因此所有支持订阅与发布功能的客户端都可以在无须做任何修改的情况下, 使用键空间通知功能。 因为 Redis 目前的订阅与发布功能采取的是发送即忘&am…

记录一次内存泄漏排查历程

背景 通过在deinit方法内打印日志,发现某个ViewController的deinit方法没有执行,决定排查下具体的原因。 方案1,instruments排查 打开instruments,按照内存泄漏的流程进行检测,反复进入,退出目标ViewContr…

Python爬虫入门课: 如何实现数据抓取 <文字 图片 音频 视频 文档..>

嗨喽~大家好呀,这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 环境使用: Python 3.10 解释器 Pycharm 编辑器 模块使用: requests re csv pandas 爬虫实现第一步: 一. 抓包分析 找到对应数据链接地址 套用代码: 修改…

苹果企业签名在审核应用程序时是否存在技术问题

苹果企业签名在审核应用程序时也可能存在技术问题。苹果企业签名是一种信任机制,允许企业开发者在发布应用程序时使用企业证书进行签名。然而,苹果公司对使用企业证书签名的应用程序也有一定的审核要求,苹果企业签名以确保应用程序的安全性和…

Mybatis 源码搭建

文章目录 源码下载测试模块搭建学习博客 源码下载 首先下载mybatis-parent的源码:gitee地址 > https://gitee.com/callback_lab/mybatis-parent.git 然后下载mybatis的源码:gitee地址 > https://gitee.com/callback_lab/mybatis-src.git 带中文…

无人机遥控器方案定制_MTK平台无人设备手持遥控终端PCB板开发

随着科技的不断发展和无人机技术的逐步成熟,无人机越来越受到人们的关注。作为一种高新技术,无人机的应用范围不断拓展,包括农业、环境监测、城市规划、运输物流等领域。同时,无人机的飞行控制技术也得到了不断的优化和提升。 早…

KVM虚拟机的NAT网络模式原理及过程展示

NAT的方式及原理 NAT方式是KVM安装后的默认方式。 它支持主机与虚拟机的互访,同时也支持虚拟机访问互联网,但不支持外界访问虚拟机。 default是宿主机安装虚拟机支持模块的时候自动安装的。 其中 virbr0是由宿主机虚拟机支持模块安装时产生的虚拟网络接…

RWA+AI 叙事下的 ProsperEx,对 Web3 时代交易的重新定义

RWA(Real World Assets)即现实资产代币,其本质在于将现实世界中具有货币价值的东西转化为数字代币,使其可以在区块链上表现价值并进行交易。RWA 资产既可以包括有形资产,例如房产、珠宝、黄金等,也可以包无…

Linux C语言 30-套接字操作

Linux C语言 30-套接字操作 本节关键字:C语言 网络通信、套接字操作、TCP、UDP、服务端、客户端 相关C库函数:socket, bind, listen, accept, setsockopt, recv, send, recvfrom, sendto, close 什么是网络通信? 通信是人与人之间通过某种…

mysql多表重复数据只保留一行的思路

一、问题描述 假设有3个表,test_a,test_b,test_c; test_a和test_b中有些重复数据; 现在要把这2个表的数据同步到表c,但是重复数据只保留1行。 样例如下: 具体要求如下: 1.tes…

生产者和消费者的底层类

无论是生产者还是消费者,在底层都要和Broker打交道,进行消息收发。在源码层面,底层的功能被抽象成同一个类,负责和Broker打交道,下面详细介绍这个类的情况。 1 MQClientInstance类的创建规则 MQClientInstance是客户…

Java 简易版王者荣耀

所有包和类 GameFrame类 package newKingOfHonor;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayList;im…

视频没有字幕怎么办,怎么给视频增加字幕

文章目录 视频没有字幕怎么办,怎么给视频增加字幕前言软件准备制作字幕1. 导入视频2. 将视频拖拽到轨道3. 生成字幕4. 导出字幕 字幕实时翻译1. 播放视频2. 显示字幕设置3. 双语字幕显示 总结 视频没有字幕怎么办,怎么给视频增加字幕 前言 有时候下载的…

云原生系列Go语言篇-泛型Part 2

类型推导和泛型 就像在使用​​:​​时支持类型推导一样,在调用泛型函数时Go同样支持类型推导。可在上面对​​Map​​、​​Filter​​和​​Reduce​​调用中看出。有些场景无法进行类型推导(如类型参数仅用作返回值)。这时,必…

血的教训------入侵redis之利用python来破解redis密码

血的教训------入侵redis之利用python来破解redis密码 利用强大的python来进行redis的密码破解,过程不亦乐乎,当然也可以用shell脚本 本篇文章只供学习交流,请勿他用,谢谢。 其他相关联的文章 [1]VMware安装部署kail镜像服务器【…

ESP32-Web-Server编程-JS 基础 2

ESP32-Web-Server编程-JS 基础 2 概述 上节介绍了 JS 编程的基础。如前所述,在 HTML 中,可以通过下述 两种方式使用 JS 程序: 直接在 HTML 文件中通过 script 标签中嵌入 JavaScript 代码。通过 src 元素引入外部的 JavaScript 文件。 在…

C#-创建用于测试的父类StartupBase用于服务注入

当写完C#代码,需要对某个方法进行测试。 创建一个XXXTests.cs文件之后,发现需要注入某个服务怎么办? 再创建一个StartupBase.cs文件: public abstract class StartupBase {public IConfiguration Configuration { get; }public …