一、怎么用数据表示图像?

首先,要对一张图像进行压缩处理,那么应该知道怎么用数据来表示一张具体的图像。

我们选择用Python中的第三方工具库的Pillow来读取一张样例照片,观察参数信息。

以下是一张lenna.jpg

需要提前安装第三方库pillow

pip install pillow

安装好之后,将图片放在源文件所在路径下,我们先来读取一下图片信息:

import numpy as np
from PIL import ImageoriginalImage = Image.open(r'lenna.jpg', 'r')
imageArray = np.array(originalImage)print(imageArray.shape)
print(imageArray)
(600, 601, 3)
[[[186 102  68][191 107  73][190 106  72]...[ 49  35  35][ 54  40  40][ 53  39  39]][[192 108  74][191 107  73][191 107  73]...[ 54  40  40][ 50  36  36][ 49  35  35]][[192 108  74][190 106  72][190 106  72]...[ 52  38  37][ 52  38  37][ 50  36  35]]...[[237 199 186][237 199 186][239 201 190]...[168 106  93][166 104  91][169 105  93]][[242 204 191][241 203 190][241 201 191]...[170 108  95][178 116 103][174 110  98]][[237 199 186][240 202 189][242 202 192]...[161  99  86][171 109  96][170 106  94]]]Process finished with exit code 0

我们从结果可以看到,这张图被表示为一个三维的ndarray数组对象:imageArray。

数组的维度是 600 x 601 x 3 。我们称为3D张量。这个3D张量由图片的三个维度信息组成,

分别为:高度信息、宽度信息、颜色通道信息。

程序的结果可以看出:这张图片是高度X宽度为600 x 601 的像素点阵,而颜色通道的具体取值用来对应的描述每个像素点的颜色信息,明确每个位置上的像素点颜色。由此通过整个彩色像素点阵,最终可以构建出完整的彩色图像。

我们在样例上用的是一张JPG格式的图片,从程序结果看到,JPG格式图片的颜色通道维数是三维的,依次分别对应R、G、B 3个通道的实际取值,每个通道都是使用8位无符号整形数来进行表示,取值范围0-255。

这三个通道的含义分别表示:红色、绿色、蓝色三个颜色通道,通过对不同取值3个通道进行数据叠加,从而可以最终产生各种所需要的颜色。另外,除了R、G、B三个通道,还有一个A通道,代表不透明度,A取值越大不透明度越高,反之亦然。如果A通道取值255表示这张图片是完全不透明的,如果取值为0表示图像完全透明。

样例图片没有用到A通道。

二、灰度图像处理

灰度图片的压缩过程比较简单、直观。灰度图片就是我们说的黑白图。这种情况颜色通道只用一维就足够了,通过0-255范围内的不同取值,用来表示白-灰-黑的深浅程度。

这种情况就比较简单,原来3D张量退化为一个简单的矩阵,我们称之为image矩阵,image矩阵的形状就是用图像的高 X 宽来进行描述,而矩阵的元素值就是对应像素的灰度值。

得到用来表示灰度图的image矩阵之后,接下来的过程就是对image矩阵进行奇异值分解(SVD),获取  , 三个核心矩阵要素,按照压缩的实际需要,取前k个奇异值机相对应的左、右特征向量,就能够按照下面的公式完成图像的压缩重建过程。

三、彩色图像压缩的具体思路

实际情况没有灰度图处理那么简单。JPG格式的彩色图片不同于灰度图,它有3个颜色通道。

所以,我们有以下具体解决思路:

第一步:通道分离

对于JPG格式的彩色图片,拥有3个颜色通道,R、G、B,那么可以尝试将每个颜色通道进行分离,产生3个形状均为图像高 x 宽 的单通道剧展,即imageR,imageG,imageB。

第二步:矩阵压缩

对每个单通道矩阵进行奇异值分解,按照压缩的实际需要取前k个奇异值,进行3个单通道的矩阵的压缩近似,各自的处理过程同灰度图的处理过程完全一样。最后分别形成3个压缩后的矩阵:imageRC,imageGC,imageBC。

第三步:图像重建

将3个压缩后的单通道矩阵合并形成表示JPG格式的3D张量,通过该3D张量重构出压缩后的彩色图像。

第一步:通道分离的实现过程

首先进行通道分离,将imageArray数组中的每个通道分别单独取出来,得到3个高 x 宽的二维数组。这3个二维数组中每个位置上的取值就是对应像素的某个颜色通道的取值。

import numpy as np
from PIL import ImageoriginalImage = Image.open(r'lenna.jpg', 'r')
imageArray = np.array(originalImage)
R = imageArray[:, :, 0]
G = imageArray[:, :, 1]
B = imageArray[:, :, 2]
print(R)
print(G)
print(B)

[[186 191 190 ...  49  54  53][192 191 191 ...  54  50  49][192 190 190 ...  52  52  50]...[237 237 239 ... 168 166 169][242 241 241 ... 170 178 174][237 240 242 ... 161 171 170]]
[[102 107 106 ...  35  40  39][108 107 107 ...  40  36  35][108 106 106 ...  38  38  36]...[199 199 201 ... 106 104 105][204 203 201 ... 108 116 110][199 202 202 ...  99 109 106]]
[[ 68  73  72 ...  35  40  39][ 74  73  73 ...  40  36  35][ 74  72  72 ...  37  37  35]...[186 186 190 ...  93  91  93][191 190 191 ...  95 103  98][186 189 192 ...  86  96  94]]

从程序的运行结果来看,我们成功得到了3个二维ndarray数组,将R、G、B三个通道成功进行了分离。

第二步:矩阵压缩的具体实现:

利用奇异值分解压缩各个通道矩阵。

def imgCompress(channel,percent):
# channel表示需要进行压缩处理的单个颜色通道矩阵
# percent表示利用SVD进行矩阵重建过程保留奇异值的百分比U,sigma,V_T = np.linalg.svd(channel)#对通道矩阵进行奇异值分解m = U.shape[0]n = V_T.shape[0]reChannel = np.zeros((m,n))# 初始化mxn大小的全零矩阵reChannelfor k in range (len(sigma)):reChannel = reChannel + sigma[k] * np.dot(U[:,k].reshape(m,1),V_T[k,:].reshape(1,n))#依照percent参数值,取前k个奇异值#依照近似公式重建经过压缩处理的通道矩阵reChannelif float(k) / len(sigma) > percent:reChannel[reChannel < 0] = 0reChannel[reChannel > 255] = 255#需要把处理后的数据约束在0-255范围内breakreturn np.rint(reChannel).astype("unit8")#对数值进行取整,类型为8位无符号整型

第三步:通道重建的具体实现

最后完成通道的重建工作,将经过奇异值分解处理的3个单通道矩阵合并成表示RGB3通道的完整3D张量,在此基础上观察不同奇异值个数比例下的图像压缩效果。

    for p in [0.001, 0.005, 0.01, 0.02, 0.03, 0.04, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]:#p表示取所有奇异值的前多少比例reR = imgCompress(R,p)reG = imgCompress(G,p)reB = imgCompress(B,p)reI = np.stack((reR,reG,reB),2)Image.fromarray(reI).save("{}".format(p)+"img.png")

四、源代码

import numpy as np
from PIL import Imagedef imgCompress(channel,percent):U, sigma, V_T = np.linalg.svd(channel)m = U.shape[0]n = V_T.shape[0]reChannel = np.zeros((m,n))for k in range(len(sigma)):reChannel = reChannel + sigma[k]* np.dot(U[:,k].reshape(m,1),V_T[k,:].reshape(1,n))if float(k)/len(sigma) > percent:reChannel[reChannel < 0] = 0reChannel[reChannel > 255] = 255breakreturn np.rint(reChannel).astype("uint8")oriImage = Image.open(r'lenna.jpg', 'r')
imgArray = np.array(oriImage)R = imgArray[:, :, 0]
G = imgArray[:, :, 1]
B = imgArray[:, :, 2]
# A = imgArray[:, :, 3]for p in [0.001,0.005,0.01,0.02,0.03,0.04,0.05,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]:reR = imgCompress(R, p)reG = imgCompress(G, p)reB = imgCompress(B, p)# reA = imgCompress(A, p)reI = np.stack((reR, reG, reB), 2)Image.fromarray(reI).save("{}".format(p)+"img.png")

五、查看结果

从最后的结果图可以看见:

取前0.05%奇异值重建的图像是一个非常模糊的,只能看到基本的轮廓。

取前0.1%奇异值亦是如此。

取前1%奇异值基本能看到眼睛、鼻子、嘴巴的轮廓,进本可以看出是一个人像。

取前2%,3%,4%,5%,10%,20%奇异值越来越清晰。除了还有一些噪点。

当取前30%奇异值的时候,已经基本和原图一致了。

利用奇异值分解(SVD)进行彩色图片压缩相关推荐

  1. 【机器学习线性代数】17 利用SVD进行彩色图片压缩

    这一节,我们再来介绍一个奇异值分解的实际案例:即如何基于SVD的主成分分析方法,来对一张彩色图像进行压缩处理. 1.图像的数据表示 很明显,如果要对一张图像进行压缩,首先我们得知道应该如何用数据的形式 ...

  2. 机器学习笔记(二)矩阵和线性代数 例:用Python实现SVD分解进行图片压缩

    线性代数基本只要是理工科,都是必修的一门课.当时学习的时候总是有一个疑惑,这个东西到底是干嘛用的?为什么数学家发明出这么一套方法呢,感觉除了解方程没发现有什么大用啊!但随着学习的深入,慢慢发现矩阵的应 ...

  3. 基于奇异值分解(SVD)的图片压缩实践

    文章目录 1. 前言 2. 原理简介 2.1 SVD定义 3. 实践代码 4. 参考文献 1. 前言 数字图片在计算机中是以矩阵形式存储的.所以可以通过矩阵理论和矩阵算法对数字图像进行分析和处理.本文 ...

  4. lrz实现原理_利用lrz.bundle.js实现图片压缩上传

    html部分: js部分: 下载 //图片上传压缩方法 function compressImg(fileDom,form,callback){ var that = fileDom; lrz(tha ...

  5. 矩阵分析:基于SVD的彩色图像压缩技术

    题目:基于SVD的彩色图片压缩技术 摘要:本文首先研究图片的构成原理,结合矩阵分析,将图片分解为三种颜色矩阵,然后通过矩阵的奇异值分解将原本的颜色矩阵分解为两个酉矩阵和一个对角矩阵的乘积,然后通过选择 ...

  6. matlab-利用SVD(奇异值分解)来进行图片压缩

    参考博客 参考博客1(大致上的理论理解):https://www.cnblogs.com/MrLJC/p/4158818.html?utm_source=tuicool 参考博客2(压缩率):http ...

  7. 一个极致优秀的在线图片压缩网站☞TinyPNG

    一个极致优秀的在线图片压缩网站☞TinyPNG 有没有觉得这个小熊猫很可爱,它可是我们的国宝啊!从认识它的那一天开始,我就已经离不开它了.TinyPNG能够对png和jpg格式的图片进行压缩,压缩后的 ...

  8. 如何将彩色图片改成黑白色?

    我们都知道,现在不管是手机还是相机拍摄出来的照片都是彩色的,有时候一些摄影从业者,或者自媒体从业者,为了让图片展示不一样的效果,需要将图片变成黑白色的,这样看起来更震撼.如果你会使用PS,就可以利用它 ...

  9. 用SVD压缩彩色图片(MATLAB代码)

    Write a MATLAB program to perform color image compression using singular value decomposition (SVD). ...

  10. 奇异值分解图片压缩_通俗易懂的讲解奇异值分解(SVD)和主成分分析(PCA)

    图片来自Unsplash上的Dave 0.本教程包含以下内容 特征分解 对称矩阵的特征分解 奇异值分解(The Singular Value Decomposition,SVD) 主成分分析(Prin ...

最新文章

  1. Verilog 中输入输出信号的类型?
  2. python使用方法-python-tkinter使用方法——转载(一)
  3. 行为模式之Mediator模式
  4. VisualStudioCode 中设置中文语言【图文教程】
  5. 【iOS】iOS 调试快速定位程序在哪崩溃
  6. 朴素贝叶斯算法详解及python代码实现
  7. linux给指定用户分配文件夹权限
  8. Android应用内存泄漏的定位、分析与解决策略
  9. 南昊网上阅卷系统服务器地址,南昊网上阅卷系统全攻略
  10. SQLite3:对SQLite3加密
  11. 骗子、假先知们一夜暴富背后:区块链是回归互联网本来意义的唯一希望|深度
  12. 腾讯云tca认证题库
  13. 信号与系统2-连续离散系统时域分析
  14. 电子基础篇5---三极管
  15. 你的网站安全吗?ZAP应用实例
  16. Linux系统下,绑定USB串口设备号,解决上电USBID随机情况
  17. 如何通过Excel数据批量生成DM码
  18. 冰焰V8显示无法连接服务器,冰焰V8怎样用 天龙8部冰焰V8脚本运用指南
  19. 百人计划 美术 1.1.3 角色设计精要
  20. pg怎么判断视图是否存在_一张表帮你判断孩子语言发展是否存在问题,速速收藏...

热门文章

  1. redhat官网关于生成rpm包的文章
  2. Javaweb项目在线学习平台系统(Spring+SpringMVC+MyBatis)
  3. 关于VS2008 SP1和 VS2010备忘
  4. 【免费分享】全新DHPST分销系统/YEP分销/云主机分销系统源码
  5. 如何保持格式拆分工作表?
  6. 基于OneNET物联网平台和GPRS网络继电器SAC07GSA的共享经济方案简介
  7. AdminLTE-2.4.10源码包
  8. 鸿蒙系统的软件怎么下载,鸿蒙系统官网下载软件电脑版
  9. java虚拟机jvm下载_Java虚拟机(JVM)简介
  10. Rails笔记《一》Routing