一、图像
1、像素
像素是分辨率的单位。
像素是构成位图图像最基本的单元,每个像素都有自己的颜色。
2、图像分辨率
图像分辨率就是单位英寸内的像素点数。
- 单位为 PPI(Pixels Per Inch),通常叫做像素每英寸。
- PPI 表示的是每英寸对角线上所拥有的的像素数目。
P P I = ( 水平分辨率 ) 2 + ( 垂直分辨率 ) 2 对角线尺寸 PPI = \frac{\sqrt{(\text{水平分辨率})^2 + (\text{垂直分辨率})^2}}{\text{对角线尺寸}} PPI=对角线尺寸(水平分辨率)2+(垂直分辨率)2
- 屏幕尺寸指的是对角线长度。
3、RGB 模型
色彩三原色(CMYK):品红、黄、青
光学三原色(RGB):红、绿、蓝
RGB 颜色模型是三维直角坐标颜色系统中的一个单位正方体。
在正方体的主对角线上,各原色的量相等,产生由暗到亮的白色,即灰度。
正方体的其它6个角点分别为红、黄、绿、青、蓝和品红。
4、灰度
表示图像像素明暗程度的数值,也就是黑白图像中点的颜色深度。
范围一般为0-255。白色为255,黑色为0。
5、通道
把图像分解成一个或多个颜色成分。
-
单通道:一个像素点只需一个数值表示,只能表示灰度,0为黑色。(二值图&灰度图)
-
三通道:RGB 模式,把图像分为红绿蓝三个通道,可以表示彩色,全0表示黑色。
-
四通道:RGBA 模式,在 RGB 基础上加上 alpha 通道,表示透明度,alpha=0 表示全透明。
6、对比度
指不同颜色之间的差别。
对比度 = 最大灰度值/最小灰度值
7、RGB 转化为 Gray
- 浮点算法:Gray = R3.0+G0.59+B0.11
- 整数算法:Gray = (R30+G59+B11)/100
- 移位算法:Gray = (R76+G151+B28)>>8
- 平均算法:Gray = (R+G+B)/3
- 仅取绿色:Gray = G
为什么很多图像识别将彩色图像灰度化?
对颜色不敏感的需求将彩色图像灰度化可以降低计算成本,减少复杂性,节省存储空间。
8、RGB 值转化为浮点数
浮点数运算结果更精确,整数运算中会因丢弃小数部分可能导致颜色值严重失真,计算过程越多越失真。
将 RGB 值转化为0-1的浮点数:x/255 即可。
9、二值化
将图像转换为只包含两个像素值的过程。
10、常用视觉库
opencv:安装使用 pip install opencv-python,使用时用 import cv2
matplotlib:安装使用 pip install matplotlib,使用时用 import matplotlib.pyplot as plt
skimage:安装使用 pip install scikit-image,使用时用 import skimage
注意:
opencv 对于读进来的图片的通道排列是 BGR,而不是主流的 RGB!
opencv 读入的矩阵是 BGR,转为 RGB 方法:
img = cv2.imread(‘1.jpg’)
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
代码实现
- 图片灰度化(方式一)
import cv2 # 导入 OpenCV 库,用于图像处理
import numpy as np # 导入 NumPy 库,用于数组操作
# 读取图片
img = cv2.imread("img/lenna.png")
# 获取图片的 high 和 wide
h, w = img.shape[:2]
# 创建一张和当前图片大小一样的单通道图片
img_gray = np.zeros([h, w], img.dtype)
# 遍历图片的每一个像素
for i in range(h):
for j in range(w):
# 取出当前 high 和 wide 中的 BGR 坐标
m = img[i, j]
# 将 BGR 坐标转化为 gray 坐标并赋值给新图像
img_gray[i, j] = int(m[0] * 0.11 + m[1] * 0.59 + m[2] * 0.3)
# 打印灰度图像的值
print(img_gray)
# [[162 162 162 ... 169 155 128]
# [162 162 162 ... 169 155 128]
# [162 162 162 ... 169 155 128]
# ...
# [ 42 42 49 ... 104 100 98]
# [ 43 43 54 ... 103 105 108]
# [ 43 43 54 ... 103 105 108]]
# 在窗口中显示灰度图像
cv2.imshow("image show gray", img_gray)
# 0 表示一直等待,直到按下任意键
cv2.waitKey(0)
# 关闭所有窗口
cv2.destroyAllWindows()
- 图片灰度化(方式二)
import matplotlib.pyplot as plt # 导入 Matplotlib 库,用于绘制图表
from skimage.color import rgb2gray # 从 skimage.color 模块中导入 rgb2gray 函数
# import cv2 # 导入 OpenCV 库,用于图像处理
# 在2x2的图表中,选中第1个子图
plt.subplot(221)
# 读取图片并将其存储在变量 img 中
img = plt.imread("img/lenna.png")
# 也可以使用 OpenCV 库读取图片
# img = cv2.imread("img/lenna.png", False)
# 在当前选中的子图中显示图片
plt.imshow(img)
# 打印提示信息
print("---image lenna----")
# 打印图像的数值表示
print(img)
# [[[0.8862745 0.5372549 0.49019608]
# [0.8862745 0.5372549 0.49019608]
# [0.8745098 0.5372549 0.52156866]
# ...
# [0.9019608 0.5803922 0.47843137]
# [0.8666667 0.50980395 0.43137255]
# [0.78431374 0.3882353 0.3529412 ]]
#
# [[0.8862745 0.5372549 0.49019608]
# [0.8862745 0.5372549 0.49019608]
# [0.8745098 0.5372549 0.52156866]
# ...
# [0.9019608 0.5803922 0.47843137]
# [0.8666667 0.50980395 0.43137255]
# [0.78431374 0.3882353 0.3529412 ]]
#
# [[0.8862745 0.5372549 0.49019608]
# [0.8862745 0.5372549 0.49019608]
# [0.8745098 0.5372549 0.52156866]
# ...
# [0.9019608 0.5803922 0.47843137]
# [0.8666667 0.50980395 0.43137255]
# [0.78431374 0.3882353 0.3529412 ]]
#
# ...
#
# [[0.32941177 0.07058824 0.23529412]
# [0.32941177 0.07058824 0.23529412]
# [0.36078432 0.10588235 0.22745098]
# ...
# [0.6784314 0.28627452 0.32941177]
# [0.6745098 0.26666668 0.29803923]
# [0.69411767 0.24313726 0.30980393]]
#
# [[0.32156864 0.08627451 0.22352941]
# [0.32156864 0.08627451 0.22352941]
# [0.3764706 0.1254902 0.24313726]
# ...
# [0.7019608 0.27450982 0.30980393]
# [0.70980394 0.2784314 0.31764707]
# [0.7254902 0.2901961 0.31764707]]
#
# [[0.32156864 0.08627451 0.22352941]
# [0.32156864 0.08627451 0.22352941]
# [0.3764706 0.1254902 0.24313726]
# ...
# [0.7019608 0.27450982 0.30980393]
# [0.70980394 0.2784314 0.31764707]
# [0.7254902 0.2901961 0.31764707]]]
# 将彩色图像转换为灰度图像
img_gray = rgb2gray(img)
# 也可以使用 OpenCV 库的函数实现灰度转换
# img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 或者直接使用原始图像(未经灰度转换)
# img_gray = img
# 在2x2的图表中,选中第2个子图
plt.subplot(222)
# 在当前选中的子图中显示灰度图像,使用灰度的颜色映射(cmap)为 'gray'
plt.imshow(img_gray, cmap='gray')
# 打印提示信息
print("---image gray----")
# 打印灰度图像的数值表示
print(img_gray)
# [[0.60802865 0.60802865 0.60779065 ... 0.6413741 0.57998234 0.46985728]
# [0.60802865 0.60802865 0.60779065 ... 0.6413741 0.57998234 0.46985728]
# [0.60802865 0.60802865 0.60779065 ... 0.6413741 0.57998234 0.46985728]
# ...
# [0.13746354 0.13746354 0.16881412 ... 0.37271804 0.35559532 0.34377727]
# [0.14617059 0.14617059 0.1873059 ... 0.36788785 0.3729255 0.3846753 ]
# [0.14617059 0.14617059 0.1873059 ... 0.36788785 0.3729255 0.3846753 ]]
# 显示 Matplotlib 的图表
plt.show()
- 图片二值化
from skimage.color import rgb2gray # 从 skimage.color 模块中导入 rgb2gray 函数
import numpy as np # 导入 NumPy 库,用于数组操作
import matplotlib.pyplot as plt # 导入 Matplotlib 库,用于绘制图表
# 在2x2的图表中,选中第1个子图
plt.subplot(221)
# 读取图片
img = plt.imread("img/lenna.png")
# 也可以使用 OpenCV 库读取图像
# img = cv2.imread("img/lenna.png", False)
# 在当前选中的子图中显示图片
plt.imshow(img)
# 打印提示信息
print("---image lenna----")
# 打印图像的数值表示
print(img)
# [[[0.8862745 0.5372549 0.49019608]
# [0.8862745 0.5372549 0.49019608]
# [0.8745098 0.5372549 0.52156866]
# ...
# [0.9019608 0.5803922 0.47843137]
# [0.8666667 0.50980395 0.43137255]
# [0.78431374 0.3882353 0.3529412 ]]
#
# [[0.8862745 0.5372549 0.49019608]
# [0.8862745 0.5372549 0.49019608]
# [0.8745098 0.5372549 0.52156866]
# ...
# [0.9019608 0.5803922 0.47843137]
# [0.8666667 0.50980395 0.43137255]
# [0.78431374 0.3882353 0.3529412 ]]
#
# [[0.8862745 0.5372549 0.49019608]
# [0.8862745 0.5372549 0.49019608]
# [0.8745098 0.5372549 0.52156866]
# ...
# [0.9019608 0.5803922 0.47843137]
# [0.8666667 0.50980395 0.43137255]
# [0.78431374 0.3882353 0.3529412 ]]
#
# ...
#
# [[0.32941177 0.07058824 0.23529412]
# [0.32941177 0.07058824 0.23529412]
# [0.36078432 0.10588235 0.22745098]
# ...
# [0.6784314 0.28627452 0.32941177]
# [0.6745098 0.26666668 0.29803923]
# [0.69411767 0.24313726 0.30980393]]
#
# [[0.32156864 0.08627451 0.22352941]
# [0.32156864 0.08627451 0.22352941]
# [0.3764706 0.1254902 0.24313726]
# ...
# [0.7019608 0.27450982 0.30980393]
# [0.70980394 0.2784314 0.31764707]
# [0.7254902 0.2901961 0.31764707]]
#
# [[0.32156864 0.08627451 0.22352941]
# [0.32156864 0.08627451 0.22352941]
# [0.3764706 0.1254902 0.24313726]
# ...
# [0.7019608 0.27450982 0.30980393]
# [0.70980394 0.2784314 0.31764707]
# [0.7254902 0.2901961 0.31764707]]]
# 使用 rgb2gray 函数将彩色图像转换为灰度图像
img_gray = rgb2gray(img)
# rows, cols = img_gray.shape # 获取灰度图的行数和列数
# for i in range(rows): # 遍历灰度图的每一行
# for j in range(cols): # 遍历灰度图的每一列
# if (img_gray[i, j] <= 0.5): # 如果当前像素值小于等于0.5
# img_gray[i, j] = 0 # 将像素值设为0
# else:
# img_gray[i, j] = 1 # 否则将像素值设为1
# 使用 NumPy 的 where 函数实现二值化,大于等于0.5的像素值设为1,小于0.5的像素值设为0
img_binary = np.where(img_gray >= 0.5, 1, 0)
# 打印提示信息
print("-----imge_binary------")
# 打印二值化后的图像数组
print(img_binary)
# [[1 1 1 ... 1 1 0]
# [1 1 1 ... 1 1 0]
# [1 1 1 ... 1 1 0]
# ...
# [0 0 0 ... 0 0 0]
# [0 0 0 ... 0 0 0]
# [0 0 0 ... 0 0 0]]
# 打印二值化后的图像形状
print(img_binary.shape)
# (512, 512)
# 在2x2的图表中,选中第2个子图
plt.subplot(222)
# 在当前选中的子图中显示二值化后的图像,使用灰度的颜色映射(cmap)为 'gray'
plt.imshow(img_binary, cmap='gray')
# 显示 Matplotlib 的图表
plt.show()
11、频率
灰度值变化剧烈程度的指标,是灰度在平面空间上的梯度(高频、低频)。
12、幅值
幅值是在一个周期内,交流电瞬时出现的最大绝对值,也是一个正弦波,波峰到波谷的距离的一半。
二、图像的取样与量化
1、数字图像
计算机保存的图像都是一个一个的像素点,称为数字图像。
图像数字化过程由图像的取样与量化来完成。
2、取样
就是要用多少点来描述一幅图像,取样结果质量的高低就是用图像的分辨率来衡量的。
3、量化
是指要使用多大范围的数值来表示图像采样之后的一个点。
数字化坐标值称为取样,
数字化幅度值称为量化。
在取样时,若横向的像素数(列数)为 M ,纵向的像素数(行数)为 N,则图像总像素数为 M*N 个像素。
尺寸一致的情况下,像素点越多,图像越精致,像素点越少,图像越粗糙。
三、上采样与下采样
1、上采样(upsampling)
放大图像(或称为图像插值(interpolating))的主要目的是放大原图像,从而可以显示在更高分辨率的显示设备上。
原理:内插值
2、下采样(subsampled)
缩小图像(或称为降采样(downsampled))的主要目的有两个:1、使得图像符合显示区域的大小。2、生成对应图像的缩略图。
原理:(M/s)*(N/s)
3、插值方法
本质是求一个不存在的像素点的像素值,不一定是加或者减。
1、最邻近插值
(i,j),(i+1,j),(i,j+1),(i+1,j+1) 为原始图像上的四个像素点,如果想在这四个像素点中间插入一个像素点,插入的像素点落在 A,B,C,D 哪个区域内,那么,插入的像素点的像素值就等同于离得最近的那个像素点的像素值。
import cv2 # 导入 OpenCV 库,用于图像处理
import numpy as np # 导入 NumPy 库,用于数组操作
def function(img):
# 获取图像的高度、宽度和通道数
height, width, channels = img.shape
# 创建一个空白图像,尺寸为(800, 800),通道数与原图一致
emptyImage = np.zeros((800, 800, channels), np.uint8)
# 计算高度的缩放比例
sh = 800 / height
# 计算宽度的缩放比例
sw = 800 / width
# 遍历图片的每一个像素
for i in range(800):
for j in range(800):
# 计算新图像中的横坐标 x,使用最近邻插值,int() 转为整型,+0.5 是为了实现向最近的整数四舍五入
x = int(i / sh + 0.5)
# 计算新图像中的纵坐标 y,使用最近邻插值,int() 转为整型,+0.5 是为了实现向最近的整数四舍五入
y = int(j / sw + 0.5)
# 对新图像进行像素赋值
emptyImage[i, j] = img[x, y]
# 返回缩放后的图像
return emptyImage
# 读取图像
img = cv2.imread("img/lenna.png")
# 调用缩放函数进行图像缩放
zoom = function(img)
# 打印缩放后的图像数组
print(zoom)
# [[[125 137 226]
# [125 137 226]
# [125 137 226]
# ...
# [110 130 221]
# [ 90 99 200]
# [ 90 99 200]]
#
# [[125 137 226]
# [125 137 226]
# [125 137 226]
# ...
# [110 130 221]
# [ 90 99 200]
# [ 90 99 200]]
#
# [[125 137 226]
# [125 137 226]
# [125 137 226]
# ...
# [110 130 221]
# [ 90 99 200]
# [ 90 99 200]]
#
# ...
#
# [[ 57 22 82]
# [ 57 22 82]
# [ 57 22 82]
# ...
# [ 81 71 181]
# [ 81 74 185]
# [ 81 74 185]]
#
# [[ 57 22 82]
# [ 57 22 82]
# [ 57 22 82]
# ...
# [ 81 71 181]
# [ 81 74 185]
# [ 81 74 185]]
#
# [[ 57 22 82]
# [ 57 22 82]
# [ 57 22 82]
# ...
# [ 81 71 181]
# [ 81 74 185]
# [ 81 74 185]]]
# 打印缩放后的图像形状
print(zoom.shape)
# (800, 800, 3)
# 在窗口中显示缩放后的图像(最近邻插值)
cv2.imshow("nearest interp", zoom)
# 在窗口中显示原始图像
cv2.imshow("image", img)
# 等待按键事件
cv2.waitKey(0)
优点:简单粗暴易用。
缺点:精度不高。
对精度要求不高时可以使用。
2、 双线性插值
f(i+u, j+v) = (1-u) * (1-v) * f(i, j) + (1-u) * v * f(i, j+1) + u * (1-v) * f(i+1, j) + u * v * f(i+1, j+1)
- 在两点之间插值
- 在四点之间插值(双线性插值)
由于图像双线性插值只会用相邻的4个点,因此上述公式的分母都是1。
- 存在的问题
要通过双线性插值的方法算出目标图像(dst)中的每一个像素点的像素值,是通过目标图像(dst)像素点的坐标对应到源图像(src)图像当中的坐标,然后通过双线性插值的方法算出源图像(src)中相应坐标的像素值。
按比例对应
SrcX =(dstX)*(srcWidth/dstWidth)
SrcY =(dstY)*(srcHeight/dstHeight)
如果源图像和目标图像的原点(0,0)均选择左上角,然后根据插值公式计算目标图像每点像素。
假设需要将一幅 5 * 5 的图像缩小成 3 * 3 的图像,那么源图像和目标图像各个像素点之间的对应关系如下:
这样会使右下角的图片信息缺失,所以,最好的方法就是,两个图像的几何中心重合,并且目标图像的每个像素之间都是等间隔的,都和两边有一定的边距。
SrcX + 0.5 =(dstX + 0.5)*(srcWidth/dstWidth)
SrcY + 0.5 =(dstY + 0.5)*(srcHeight/dstHeight)
证明几何中心对称重合为什么要加0.5
源图像有 M × M 个像素点,目标图像有 N × N 个像素点 目标图像在源图像坐标系位置为 ( x , y ) 源图像坐标为 ( x m , y m ) m = 0 , 1 , . . . , M − 1 几何中心点为 ( x M − 1 2 , y M − 1 2 ) 目标图像坐标为 ( x n , y n ) n = 0 , 1 , . . . , N − 1 几何中心点为 ( x N − 1 2 , y N − 1 2 ) x = n M N ⇒ 使几何中心相同 M − 1 2 + z = ( N − 1 2 + z ) M N z = 1 2 源图像有 M × M 个像素点,目标图像有 N × N 个像素点\\ 目标图像在源图像坐标系位置为(x,y)\\ 源图像坐标为(x_m,y_m)\quad m=0,1,...,M-1\quad几何中心点为(x_\frac{M-1}{2},y_\frac{M-1}{2})\\ 目标图像坐标为(x_n,y_n)\quad n=0,1,...,N-1\quad几何中心点为(x_\frac{N-1}{2},y_\frac{N-1}{2})\\ x=n\frac{M}{N} \Rightarrow 使几何中心相同\\ \frac{M-1}{2}+z=(\frac{N-1}{2}+z)\frac{M}{N}\\ z=\frac{1}{2} 源图像有M