人工智能 — 数字图像

一、图像

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值