图像处理
写在博客前面
图像处理的内容没有任何头绪,只能借助材料学习,把链接放在下面,同学们可以共同学习。
https://www.cnblogs.com/zyp4614/p/6917943.html
https://blog.csdn.net/jemenchen/article/details/52658476
https://479001499.iteye.com/blog/2078110
首先了解图像结构
要讲图片格式还先得从图像的基本数据结构说起。在计算机中, 图像是由一个个像素点组成,像素点就是颜色点,而颜色最简单的方式就是用RGB或RGBA表示, 如图所示
R,G,B每个分量一般是用一个字节来表示,所以图中每个像素大小就是24位图。
同样有R,G,B,A四个分量,每个像素位为32位图
需要注意的是
一、图像y方向正立或倒立
图像是二维数据,数据在内存中只能一维存储,二维转一维有不同的对应方式。比较常见的只有两种方式: 按像素“行排列”从上往下或者从下往上。
按照我的理解如上图:从上往下为123456789,从下往上读取为789456123
这两种的区别在于取得坐标轴不同,两者可以进行互相转换。
y2 = height-1-y1 y1,y2分别为像素在两个坐标系中的y坐标,height为图像的高度。
二、RGB排列顺序
不同图形库中每个像素点中RGBA的排序顺序可能不一样。上面说过像素一般会有RGB,或RGBA四个分量,那么在内存中RGB的排列就有6种情况
这个排列组合很好理解,
BMP格式
bmp格式没有压缩像素格式,存储在文件中时先有文件头、再图像头、后面就都是像素数据了,上下颠倒存储。
用windows自带的mspaint工具保存bmp格式时,可以发现有四种bmp可供选择:
单色: 一个像素只占一位,要么是0,要么是1,所以只能存储黑白信息
16色位图: 一个像素4位,有16种颜色可选
256色位图: 一个像素8位,有256种颜色可选
24位位图: 颜色可有2^24种可选,对于人眼来说完全足够
代码
# -*- coding: UTF-8 -*-
from struct import unpack
# 读取并存储 bmp 文件
class ReadBMPFile :
def __init__(self, filePath) :
file = open(filePath, "rb")
# 读取 bmp 文件的文件头 14 字节
self.bfType = unpack("<h", file.read(2))[0] # 0x4d42 对应BM 表示这是Windows支持的位图格式
self.bfSize = unpack("<i", file.read(4))[0] # 位图文件大小
self.bfReserved1 = unpack("<h", file.read(2))[0] # 保留字段 必须设为 0
self.bfReserved2 = unpack("<h", file.read(2))[0] # 保留字段 必须设为 0
self.bfOffBits = unpack("<i", file.read(4))[0] # 偏移量 从文件头到位图数据需偏移多少字节(位图信息头、调色板长度等不是固定的,这时就需要这个参数了)
# 读取 bmp 文件的位图信息头 40 字节
self.biSize = unpack("<i", file.read(4))[0] # 所需要的字节数
self.biWidth = unpack("<i", file.read(4))[0] # 图像的宽度 单位 像素
self.biHeight = unpack("<i", file.read(4))[0] # 图像的高度 单位 像素
self.biPlanes = unpack("<h", file.read(2))[0] # 说明颜色平面数 总设为 1
self.biBitCount = unpack("<h", file.read(2))[0] # 说明比特数
self.biCompression = unpack("<i", file.read(4))[0] # 图像压缩的数据类型
self.biSizeImage = unpack("<i", file.read(4))[0] # 图像大小
self.biXPelsPerMeter = unpack("<i", file.read(4))[0]# 水平分辨率
self.biYPelsPerMeter = unpack("<i", file.read(4))[0]# 垂直分辨率
self.biClrUsed = unpack("<i", file.read(4))[0] # 实际使用的彩色表中的颜色索引数
self.biClrImportant = unpack("<i", file.read(4))[0] # 对图像显示有重要影响的颜色索引的数目
self.bmp_data = []
if self.biBitCount != 24 :
print("输入的图片比特值为 :" + str(self.biBitCount) + "\t 与程序不匹配")
for height in range(self.biHeight) :
bmp_data_row = []
# 四字节填充位检测
count = 0
for width in range(self.biWidth) :
bmp_data_row.append([unpack("<B", file.read(1))[0], unpack("<B", file.read(1))[0], unpack("<B", file.read(1))[0]])
count = count + 3
# bmp 四字节对齐原则
while count % 4 != 0 :
file.read(1)
count = count + 1
self.bmp_data.append(bmp_data_row)
self.bmp_data.reverse()
file.close()
# R, G, B 三个通道
self.R = []
self.G = []
self.B = []
for row in range(self.biHeight) :
R_row = []
G_row = []
B_row = []
for col in range(self.biWidth) :
B_row.append(self.bmp_data[row][col][0])
G_row.append(self.bmp_data[row][col][1])
R_row.append(self.bmp_data[row][col][2])
self.B.append(B_row)
self.G.append(G_row)
self.R.append(R_row)