文章目录
一、位图
1.1 位图简介
位图图像(bitmap),亦称为点阵图像或栅格图像,是由称作像素(图片元素)的单个点组成的。这些点可以进行不同的排列和染色以构成图样。当放大位图时,可以看见赖以构成整个图像的无数单个方块。扩大位图尺寸的效果是增大单个像素,从而使线条和形状显得参差不齐。然而,如果从稍远的位置观看它,位图图像的颜色和形状又显得是连续的。用数码相机拍摄的照片、扫描仪扫描的图片以及计算机截屏图等都属于位图。位图的特点是可以表现色彩的变化和颜色的细微过渡,产生逼真的效果,缺点是在保存时需要记录每一个像素的位置和颜色值,占用较大的存储空间。常用的位图处理软件有Photoshop(同时也包含矢量功能)、Painter和Windows系统自带的画图工具等,Adobe Illustrator则是矢量图软件。
1.2 BMP位图文件
常见的图像文件格式有:BMP、JPG(JPE,JPEG)、GIF等。
BMP图像文件(Bitmap-File)格式是Windows采用的图像文件存储格式,在Windows环境下运行的所有图像处理软件都支持这种格式。Windows 3.0以后的BMP文件都是指设备无关位图(DIB,device-independent bitmap)。BMP位图文件默认的文件扩展名是.BMP,有时它也会以.DIB或.RLE作扩展名。
1.3 BMP文件结构
BMP文件总体上由4部分组成,分别是位图文件头、位图信息头、调色板和图像数据
位图文件头:
二、图片处理
2.1 BMP分析
以皮卡丘原图为例(用电脑自带画板打开):
分别保存为 24位彩色和256色、16色、单色的位图(BMP)文件
文件大小比较:
24位位图文件大小:136KB
256色位图文件大小:46.4KB
16色位图文件大小:22.8KB
单色位图大小:5.73KB
用UltraEdit查看:
24位位图:
Windows的数据是倒着念的,这是PC电脑的特色。如果一段数据为50 1A 25 3C,倒着念就是3C 25 1A50,即0x3C251A50。
bfType:424Dh=’BM’,表示是Windows支持的BMP格式。
bfSize: 00 02 20 B6h整个文件的大小,000220B6h=139446。上面图片文件大小不包含文件头为136KB(139264B)。
bfReserved1、bfReserved2: 00 00 00 00必须设置为0。
bfOffBits: 36 00 00 00文件开始到位图数据之间的偏移量。
256色位图:
16色位图:
单色位图:
根据上面数据发现几张图片的文件头bfType、bfReserved1、bfReserved2是一样的,而 bfSize和bfOffBits有区别
2.2 不同图片格式的压缩比
1.将图片分别保存为BMP、JPG、GIF、PNG格式
因为BMP不是压缩的,所以以它为基准计算压缩比
BMP图片大小:136KB
图片格式 | 图片大小 | 压缩比 |
PNG | 15.7KB | 88% |
JPG | 16.5KB | 87% |
PNG | 80.2KB | 41% |
三、图片处理编程
3.1 奇异函数分解(SDV)
代码:
import numpy as np
import os
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib as mpl
from pprint import pprint
def restore1(sigma, u, v, K): # 奇异值、左特征向量、右特征向量
m = len(u)
n = len(v[0])
a = np.zeros((m, n))
for k in range(K):
uk = u[:, k].reshape(m, 1)
vk = v[k].reshape(1, n)
a += sigma[k] * np.dot(uk, vk)
a[a < 0] = 0
a[a > 255] = 255
# a = a.clip(0, 255)
return np.rint(a).astype('uint8')
def restore2(sigma, u, v, K): # 奇异值、左特征向量、右特征向量
m = len(u)
n = len(v[0])
a = np.zeros((m, n))
for k in range(K+1):
for i in range(m):
a[i] += sigma[k] * u[i][k] * v[k]
a[a < 0] = 0
a[a > 255] = 255
return np.rint(a).astype('uint8')
if __name__ == "__main__":
A = Image.open("皮卡丘.jpg", 'r')
print(A)
output_path = r'./SVD_Output'
if not os.path.exists(output_path):
os.mkdir(output_path)
a = np.array(A)
print(a.shape)
K = 50
u_r, sigma_r, v_r = np.linalg.svd(a[:, :, 0])
u_g, sigma_g, v_g = np.linalg.svd(a[:, :, 1])
u_b, sigma_b, v_b = np.linalg.svd(a[:, :, 2])
plt.figure(figsize=(11, 9), facecolor='w')
mpl.rcParams['font.sans-serif'] = ['simHei']
mpl.rcParams['axes.unicode_minus'] = False
for k in range(1, K+1):
print(k)
R = restore1(sigma_r, u_r, v_r, k)
G = restore1(sigma_g, u_g, v_g, k)
B = restore1(sigma_b, u_b, v_b, k)
I = np.stack((R, G, B), axis=2)
Image.fromarray(I).save('%s\\svd_%d.png' % (output_path, k))
if k <= 12:
plt.subplot(3, 4, k)
plt.imshow(I)
plt.axis('off')
plt.title('奇异值个数:%d' % k)
plt.suptitle('SVD与图像分解', fontsize=20)
plt.tight_layout()
# plt.subplots_adjust(top=0.9)
plt.show()
结果:
观察发现随着奇异值的减少,图片变得越来越模糊
3.2 用图像的开闭运算(腐蚀-膨胀),检测出2个样本图像中硬币、细胞的个数
代码:
import cv2
import numpy as np
def stackImages(scale, imgArray):
"""
将多张图像压入同一个窗口显示
:param scale:float类型,输出图像显示百分比,控制缩放比例,0.5=图像分辨率缩小一半
:param imgArray:元组嵌套列表,需要排列的图像矩阵
:return:输出图像
"""
rows = len(imgArray)
cols = len(imgArray[0])
rowsAvailable = isinstance(imgArray[0], list)
width = imgArray[0]