人工智能 — 数字图像

news2024/11/24 20:06:06

目录

  • 一、图像
    • 1、像素
    • 2、图像分辨率
    • 3、RGB 模型
    • 4、灰度
    • 5、通道
    • 6、对比度
    • 7、RGB 转化为 Gray
    • 8、RGB 值转化为浮点数
    • 9、二值化
    • 10、常用视觉库
    • 11、频率
    • 12、幅值
  • 二、图像的取样与量化
    • 1、数字图像
    • 2、取样
    • 3、量化
  • 三、上采样与下采样
    • 1、上采样(upsampling)
    • 2、下采样(subsampled)
    • 3、插值方法
      • 1、最邻近插值
      • 2、 双线性插值
  • 四、直方图
    • 1、概念
    • 2、性质
    • 3、应用
    • 4、均衡化
      • 1、概念
      • 2、方法
      • 3、公式
  • 五、滤波和卷积
    • 1、概念
    • 2、滤波器/过滤器/卷积核/Kernel
    • 3、卷积
      • 1、步长/Stride
      • 2、填充/Pading
      • 3、多通道卷积

一、图像

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×M个像素点,目标图像有N×N个像素点目标图像在源图像坐标系位置为(x,y)源图像坐标为(xm,ym)m=0,1,...,M1几何中心点为(x2M1,y2M1)目标图像坐标为(xn,yn)n=0,1,...,N1几何中心点为(x2N1,y2N1)x=nNM使几何中心相同2M1+z=(2N1+z)NMz=21

import cv2  # 导入 OpenCV 库,用于图像处理
import numpy as np  # 导入 NumPy 库,用于数组操作

def bilinear_interpolation(img, out_dim):
    # 获取输入图像的高度、宽度和通道数
    src_h, src_w, channel = img.shape
    # 获取输出图像的高度和宽度
    dst_h, dst_w = out_dim[1], out_dim[0]
    # 打印输入图像的高度、宽度
    print("src_h, src_w = ", src_h, src_w)
    # src_h, src_w =  512 512
    # 打印输出图像的高度、宽度
    print("dst_h, dst_w = ", dst_h, dst_w)
    # dst_h, dst_w =  700 700

    # 如果输入图像和输出图像尺寸相同
    if src_h == dst_h and src_w == dst_w:
        # 则直接返回输入图像的副本
        return img.copy()

    # 创建一个空白的输出图像,尺寸为(dst_h, dst_w, 3)
    dst_img = np.zeros((dst_h, dst_w, 3), dtype=np.uint8)

    # 计算在水平和垂直方向上的缩放比例
    scale_x, scale_y = float(src_w) / dst_w, float(src_h) / dst_h

    # 对输出图像的每个通道进行插值
    for i in range(3):
        # 对输出图像的每个像素进行插值
        for dst_y in range(dst_h):
            for dst_x in range(dst_w):
                # 计算在输入图像中的对应位置
                src_x = (dst_x + 0.5) * scale_x - 0.5
                src_y = (dst_y + 0.5) * scale_y - 0.5

                # 计算在输入图像中的四个相邻像素的坐标
                src_x0 = int(np.floor(src_x))
                src_x1 = min(src_x0 + 1, src_w - 1)
                src_y0 = int(np.floor(src_y))
                src_y1 = min(src_y0 + 1, src_h - 1)

                # 使用双线性插值计算输出图像中当前像素的值
                temp0 = (src_x1 - src_x) * img[src_y0, src_x0, i] + (src_x - src_x0) * img[src_y0, src_x1, i]
                temp1 = (src_x1 - src_x) * img[src_y1, src_x0, i] + (src_x - src_x0) * img[src_y1, src_x1, i]
                dst_img[dst_y, dst_x, i] = int((src_y1 - src_y) * temp0 + (src_y - src_y0) * temp1)

    # 返回双线性插值后的输出图像
    return dst_img


if __name__ == '__main__':
    # 读取图像文件
    img = cv2.imread('img/lenna.png')
    # 对图像进行双线性插值,将尺寸调整为(700, 700)
    dst = bilinear_interpolation(img, (700, 700))
    # 显示双线性插值结果
    cv2.imshow('bilinear interp', dst)
    # 等待用户按任意键,如果没有这一句,窗口会立即关闭
    cv2.waitKey()

优点:精度高,图像看起来更光滑。

缺点:计算复杂,计算量较大。

四、直方图

1、概念

直方图是图像处理中一种用于描述图像像素值分布的工具。主要用于分析图像的亮度、对比度和颜色分布。包括颜色直方图、灰度直方图等。

灰度直方图

图像的灰度直方图就描述了图像中灰度分布情况,能够很直观的展示出图像中各个灰度级所占的多少。

图像的灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数。其中,横坐标是灰度级,纵坐标是该灰度级出现的频率。

2、性质

  • 直方图反映了图像中的灰度分布规律。它描述每个灰度级具有的像素个数,但不包含这些像素在图像中的位置信息。
  • 图像直方图不关心像素所处的空间位置,因此,不受图像旋转和平移变化的影响,可以作为图像的特征。
  • 任何一幅特定的图像都有唯一的直方图与之对应,但不同的图像可以有相同的直方图。
  • 如果一幅图像有两个不相连的区域组成,并且每个区域的直方图已知,则整幅图像的直方图是该两个区域的直方图之和。

3、应用

在这里插入图片描述

灰度图像的直方图

方法一:使用 Matplotlib 绘制直方图

import cv2  # 导入 OpenCV 库,用于图像处理
from matplotlib import pyplot as plt  # 从 Matplotlib 库导入绘图模块 plt

# 读取彩色图像
img = cv2.imread("img/lenna.png", 1)
# 将彩色图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 显示灰度图像
# cv2.imshow("image_gray", gray)

# 创建一个新的图像
plt.figure()
# 绘制直方图
plt.hist(gray.ravel(), 256)
# 显示直方图
plt.show()

在这里插入图片描述

方法二:使用 OpenCV 的 calcHist 函数绘制直方图

import cv2  # 导入 OpenCV 库,用于图像处理
from matplotlib import pyplot as plt  # 从 Matplotlib 库导入绘图模块 plt

'''
calcHist—计算图像直方图
函数原型:calcHist(images, channels, mask, histSize, ranges, hist=None, accumulate=None)
images:图像矩阵,例如:[image]
channels:通道数,例如:0
mask:掩膜,一般为:None
histSize:直方图大小,一般等于灰度级数
ranges:横轴范围
hist: 输出的直方图,默认为 None,创建一个空的直方图。如果传入一个已存在的直方图,会在已有的直方图上累积结果
accumulate: 默认为 None。如果设置为 True,函数会累积直方图的值。在处理多幅图像时,可以累积它们的直方图
'''

# 读取彩色图像
img = cv2.imread("img/lenna.png", 1)
# 将彩色图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 显示灰度图像
# cv2.imshow("image_gray", gray)

# 计算灰度图像的直方图
hist = cv2.calcHist([gray],[0],None,[256],[0,256])
# 创建一个新的图像
plt.figure()
# 设置图像标题
plt.title("Grayscale Histogram")
# 设置x轴标签
plt.xlabel("Bins")
# 设置y轴标签
plt.ylabel("# of Pixels")
# 绘制直方图
plt.plot(hist)
# 设置x轴范围
plt.xlim([0,256])
# 显示直方图
plt.show()

在这里插入图片描述

彩色图像的直方图

import cv2  # 导入 OpenCV 库,用于图像处理
from matplotlib import pyplot as plt  # 从 Matplotlib 库导入绘图模块 plt

# 读取彩色图像
image = cv2.imread("img/lenna.png")
# 显示原始彩色图像
cv2.imshow("Original",image)
# 等待用户按键
cv2.waitKey(0)

# 分离彩色图像的通道
chans = cv2.split(image)
colors = ("b","g","r")

# 创建一个新的图像
plt.figure()
# 设置图像标题
plt.title("Flattened Color Histogram")
# 设置x轴标签
plt.xlabel("Bins")
# 设置y轴标签
plt.ylabel("# of Pixels")

# 遍历彩色通道和对应颜色
for (chan,color) in zip(chans,colors):
    # 计算彩色通道的直方图
    hist = cv2.calcHist([chan],[0],None,[256],[0,256])
    # 绘制直方图
    plt.plot(hist,color = color)
    # 设置x轴范围
    plt.xlim([0,256])
# 显示直方图
plt.show()

在这里插入图片描述

4、均衡化

1、概念

直方图均衡化是将原图像的直方图通过变换函数变为均匀的直方图,然后按均匀直方图修改原图像,从而获得一幅灰度分布均匀的新图像。

直方图均衡化就是用一定的算法使直方图大致平和的方法。

直方图均衡化的作用图像增强

在这里插入图片描述

2、方法

为了将原图像的亮度范围进行扩展,需要一个映射函数,将原图像的像素值均衡映射到新直方图中,这个映射函数有两个条件:

1、为了不打乱原有的顺序,映射后亮、暗的大小关系不能改变。

2、映射后必须在原有的范围内,比如(0-255)。

步骤

1、依次扫描原始灰度图像的每一个像素,计算出图像的灰度直方图 H。

2、计算灰度直方图的累加直方图。

3、根据累加直方图和直方图均衡化原理得到输入与输出之间的映射关系。

4、最后根据映射关系得到结果:dst(x,y) = H’(src(x,y)) 进行图像变换。

3、公式

1、对于输入图像的任意一个像素 p, p∈[0,255], 总能在输出图像里有对应的像素 q, q∈[0,255] 使得下面等式成立(输入和输出的像素总量相等):

累加直方图公式 ∑ k = 0 p h i s t i n p u t ( k ) = ∑ k = 0 q h i s t i o u t ( k ) 累加直方图公式\\\sum_{k=0}^{p} hist_{input}(k) = \sum_{k=0}^{q} hist_{iout}(k) 累加直方图公式k=0phistinput(k)=k=0qhistiout(k)
2、其中,输出图像每个灰度级的个数:

h i s t i o u t ( k ) ≈ H × W 256 , k ∈ [ 0 , 255 ] hist_{iout}(k)\approx \frac{H \times W}{256} ,k \in [0,255] histiout(k)256H×W,k[0,255]
3、代入累加直方图公式:
∑ k = 0 p h i s t i n p u t ( k ) ≈ ( q + 1 ) H × W 256 ⇒ q ≈ ∑ k = 0 p h i s t i n p u t ( k ) H × W × 256 − 1 \sum_{k=0}^{p} hist_{input}(k)\approx (q+1)\frac{H \times W}{256}\Rightarrow q\approx\sum_{k=0}^{p}\frac{hist_{input}(k)}{H \times W}\times256-1 k=0phistinput(k)(q+1)256H×Wqk=0pH×Whistinput(k)×2561

在这里插入图片描述

灰度图像直方图均衡化

import cv2  # 导入 OpenCV 库,用于图像处理
import numpy as np  # 导入 NumPy 库,用于数组操作
from matplotlib import pyplot as plt  # 从 Matplotlib 库导入绘图模块 plt

'''
equalizeHist—直方图均衡化
函数原型: equalizeHist(src, dst=None)
src:图像矩阵(单通道图像)
dst:默认即可
'''

# 读取彩色图像
img = cv2.imread("img/lenna.png", 1)
# 将彩色图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 显示灰度图像
# cv2.imshow("image_gray", gray)

# 对灰度图像进行直方图均衡化
dst = cv2.equalizeHist(gray)

# 计算均衡化后图像的直方图
hist = cv2.calcHist([dst], [0], None, [256], [0, 256])

# 使用 Matplotlib 绘制均衡化后图像的直方图
plt.figure()
# 绘制直方图,ravel()将图像矩阵展平为一维数组
plt.hist(dst.ravel(), 256)
# 显示直方图
plt.show()

# 将原始灰度图像和均衡化后的图像水平拼接
combined_img = np.hstack([gray, dst])
# 显示均衡化后的图像和直方图拼接图像
cv2.imshow("Histogram Equalization", combined_img)
# 等待用户按键
cv2.waitKey(0)

在这里插入图片描述

在这里插入图片描述

彩色图像直方图均衡化

import cv2  # 导入 OpenCV 库,用于图像处理

'''
equalizeHist—直方图均衡化
函数原型: equalizeHist(src, dst=None)
src:图像矩阵(单通道图像)
dst:默认即可
'''

# 读取彩色图像
img = cv2.imread("img/lenna.png", 1)
# 显示原始彩色图像
cv2.imshow("src", img)

# 分离彩色图像的通道(蓝、绿、红)
(b, g, r) = cv2.split(img)
# 对每个通道进行直方图均衡化
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)

# 合并均衡化后的通道,得到最终的彩色图像
result = cv2.merge((bH, gH, rH))
# 显示均衡化后的彩色图像
cv2.imshow("dst_rgb", result)

# 等待用户按键
cv2.waitKey(0)

在这里插入图片描述

五、滤波和卷积

1、概念

滤波

滤波是一种信号处理技术,线性滤波可以说是图像处理最基本的方法,其目的是通过一定的操作来改变信号的频率特性或者减弱信号中的某些成分。

在图像处理中,滤波通常用于去除图像中的噪声、平滑图像、增强图像特定的特征等。滤波操作可以通过一系列数学运算来实现。

卷积

卷积是一种数学运算,常被用于信号处理和图像处理中。
( f ∗ g ) ( t ) = ∫ R f ( x ) g ( t − x )   d x (f * g)(t) = \int_{R} f(x)g(t-x) \, dx (fg)(t)=Rf(x)g(tx)dx

一般称 g 为作用在 f 上的 filter 或 kernel

在这里插入图片描述

2、滤波器/过滤器/卷积核/Kernel

对于滤波器规则要求:

  • 滤波器的大小应该是奇数,这样它才有中心和半径,例如 3x3,5x5 或者 7x7。5x5 大小的核的半径就是2。
  • 滤波器矩阵所有的元素之和应该要等于1,这是为了保证滤波前后图像的亮度保持不变。但这不是硬性要求。
  • 如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。
  • 对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,将它们直接截断到0和255之间即可。对于负数,也可以取绝对值。

在具体应用中,往往有多个卷积核,可以认为,每个卷积核代表了一种图像模式。

如果某个图像块与此卷积核卷积出的值大,则认为此图像块十分接近于此卷积核。

例如,如果设计了6个卷积核,可以理解为:我们认为这个图像上有6种底层纹理模式,也就是我们用6种基础模式就能描绘出一副图像。

下图为一张黑白相间的图片

在这里插入图片描述

有 Gx 和 Gy 两个卷积核

G x = 1 0 − 1 1 0 − 1 1 0 − 1 G y = 1 1 1 0 0 0 − 1 − 1 − 1 G_x = \begin{array}{|c|c|c|} \hline 1 & 0 & -1 \\ \hline 1 & 0 & -1 \\ \hline 1 & 0 & -1 \\ \hline \end{array}\quad G_y = \begin{array}{|c|c|c|} \hline 1 & 1 & 1 \\ \hline 0 & 0 & 0 \\ \hline -1 & -1 & -1 \\ \hline \end{array} Gx=111000111Gy=101101101
用 Gx 来卷积这张图的话,就会在纵向中间黑白边界处获得比较大的值,可以找到纵向的边界位置。

用 Gy 来卷积这张图的话,就会在横向中间黑白边界处获得比较大的值,可以找到横向的边界位置。

应用

1、一个没有任何效果的卷积
0 0 0 0 1 0 0 0 0 \begin{array}{|c|c|c|} \hline 0 & 0 & 0 \\ \hline 0 & 1 & 0 \\ \hline 0 & 0 & 0 \\ \hline \end{array} 000010000

将原像素中间像素值乘1,其余全部乘0。 显然像素值不会发生任何变化。

2、平滑均值滤波
1 9 1 9 1 9 1 9 1 9 1 9 1 9 1 9 1 9 \begin{array}{|c|c|c|} \hline \frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\ \hline \frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\ \hline \frac{1}{9} & \frac{1}{9} & \frac{1}{9} \\ \hline \end{array} 919191919191919191

取九个值的平均值代替中间像素值。起到平滑的效果。

3、高斯平滑
1 16 2 16 1 16 2 16 2 16 2 16 1 16 2 16 1 16 \begin{array}{|c|c|c|} \hline \frac{1}{16} & \frac{2}{16} & \frac{1}{16} \\ \hline \frac{2}{16} & \frac{2}{16} & \frac{2}{16} \\ \hline \frac{1}{16} & \frac{2}{16} & \frac{1}{16} \\ \hline \end{array} 161162161162162162161162161

高斯平滑水平和垂直方向呈现高斯分布,更突出了中心点在像素平滑后的权重,相比于均值滤波而言, 有着更好的平滑效果。

4、图像锐化
− 1 − 1 − 1 − 1 9 − 1 − 1 − 1 − 1 \begin{array}{|c|c|c|} \hline -1 & -1 & -1 \\ \hline -1 & 9 & -1 \\ \hline -1 & -1 & -1 \\ \hline \end{array} 111191111

0 − 1 0 − 1 5 − 1 0 − 1 0 \begin{array}{|c|c|c|} \hline 0 & -1 & 0 \\ \hline -1 & 5 & -1 \\ \hline 0 & -1 & 0 \\ \hline \end{array} 010151010

图像锐化使用的是拉普拉斯变换核函数。

5、Soble 边缘检测
水平梯度卷积核 − 1 0 1 − 2 0 2 − 1 0 1 水平梯度卷积核\\ \begin{array}{|c|c|c|} \hline -1 & 0 & 1 \\ \hline -2 & 0 & 2 \\ \hline -1 & 0 & 1 \\ \hline \end{array} 水平梯度卷积核121000121

垂直梯度卷积核 − 1 − 2 − 1 0 0 0 1 2 1 垂直梯度卷积核\\ \begin{array}{|c|c|c|} \hline -1 & -2 & -1 \\ \hline 0 & 0 & 0 \\ \hline 1 & 2 & 1 \\ \hline \end{array} 垂直梯度卷积核101202101

Soble 更强调了和边缘相邻的像素点对边缘的影响。

在这里插入图片描述

3、卷积

卷积负责提取图像中的局部特征

1、步长/Stride

如果用 (f, f) 的过滤器来卷积一张 (h, w) 大小的图片,每次移动一个像素的话,那么得出的结果就是 (h-f+1, w-f+1) 的输出结果。

f 是过滤器大小,h 和 w 分别是图片的高宽。 如果每次不止移动一个像素,而是 s 个像素,那么结果就会变为:
( h − f s + 1 , w − f s + 1 ) (\frac{h-f}{s}+1,\frac{w-f}{s}+1) (shf+1,swf+1)
这个 s 就叫做步长。

存在的问题:

只要是 f 或 s 的值比1要大的话,那么每次卷积之后结果的长宽,要比卷积前小一些。

丢失信息。

2、填充/Pading

在这里插入图片描述

有了填充之后,每次卷积之后的图像大小:

( h − f s + 1 , w − f s + 1 ) ⇒ ( h − f + 2 p s + 1 , w − f + 2 p s + 1 ) (\frac{h-f}{s}+1,\frac{w-f}{s}+1) \Rightarrow (\frac{h-f+2p}{s}+1,\frac{w-f+2p}{s}+1) (shf+1,swf+1)(shf+2p+1,swf+2p+1)
此时如果想让高(宽)不变:

h − f + 2 p s + 1 = h ⇒ p = s ( h − 1 ) − h + f 2 \frac{h-f+2p}{s}+1=h \Rightarrow p=\frac{s(h-1)-h+f}{2} shf+2p+1=hp=2s(h1)h+f
假设步长 s=1:

p = f − 1 2 p=\frac{f-1}{2} p=2f1

填充模式

橙色部分为 image, 蓝色部分为 filter。

  • full 模式

在这里插入图片描述

从 filter 和 image 刚相交开始做卷积。

  • same 模式

在这里插入图片描述

filter 中心 (K) 与 image 的边角重合时, 开始做卷积。

  • valid 模式

在这里插入图片描述

filter 全部在 image 里面时,进行卷积。

注意:

这里的 same 还有一个意思,卷积之后输出的 feature map 尺寸保持不变(相对于输入图片)。

当然,same 模式不代表完全输入输出尺寸一样,也跟卷积核的步长有关系。

same 模式也是最常见的模式,因为这种模式可以在卷积过程中让图的大小保持不变。

3、多通道卷积

在这里插入图片描述

  • 卷积核数量(W0、W1,一共2个卷积核)= 输出通道数

  • 每个卷积核代表一种特征,想要几种特征就设置几个卷积核

  • 每个卷积核的通道数(W0 和 W1 都分别有3个通道)= 输入通道数(已知)

  • Bias:偏置(可以理解为加快收敛速度的一个参数),y=kx+b(bias)

记录学习过程,欢迎讨论交流,尊重原创,转载请注明出处~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1465528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NOIP2018-J-4-对称二叉树的题解

原题描述&#xff1a; 题目描述 时间&#xff1a;1s 空间&#xff1a;256M 一棵有点权的有根树如果满足以下条件&#xff0c;则被轩轩称为对称二叉树&#xff1a; 1. 二叉树&#xff1b; 2. 将这棵树所有节点的左右子树交换&#xff0c;新树和原树对应位置的结构相同且…

【机器学习的基本术语和概念】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 简述概要知识图谱 简述概要 提示&#xff1a;简要描述文章内容&#xff0c;适合哪些人观看 知识图谱 样本&#xff08;Sample&#xff09;/实例&#xff08;Instance&#xff09;&#xff1a;在机器学习中&#xff0c;我…

vue-利用属性(v-if)控制表单(el-form-item)显示/隐藏

表单控制属性 v-if 示例&#xff1a; 通过switch组件作为开关&#xff0c;控制表单的显示与隐藏 <el-form-item label"创建数据集"><el-switch v-model"selectFormVisible"></el-switch></el-form-item><el-form-item label&…

AndroidStudio 2024-2-21 Win10/11最新安装配置(Kotlin快速构建配置,gradle镜像源)

AndroidStudio 2024 Win10/11最新安装配置 教程目的&#xff1a; (从安装到卸载) &#xff0c;针对Kotlin开发配置&#xff0c;gradle-8.2-src/bin下载慢&#xff0c;以及Kotlin构建慢的解决 好久没玩AS了,下载发现装个AS很麻烦,就觉得有必要出个教程了(就是记录一下:嘻嘻) 因…

❤ hexo主题+Gitee搭建个人博客

Hexo的基本使用 ​官网 官网地址&#xff1a;https://hexo.io/zh-cn/ Hexo是一个快速、简洁且高效的博客框架。Hexo 使用 Markdown&#xff08;或其他渲染引擎&#xff09;解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。即把用户的markdown文件…

开源LLMs导览:工作原理、顶级LLM列表对比

目录 一、开源 LLM 是什么意思&#xff1f;二、开源LLM如何工作&#xff1f;2.1 预训练2.2 代币化2.3 开源LLM的微调2.4 输入编码2.5 训练与优化2.6 推理 三、开源LLM对组织的好处3.1 增强的数据安全和隐私3.2 节约成本3.3 减少供应商依赖性3.4 代码透明度 四、哪种LLM模式最好…

AcrelEMS-HIM高速公路综合能效系统在高速公路的案例

摘 要&#xff1a;我国新型工业化、信息化、城镇化和农业现代化加快发展&#xff0c;经济结构加快转型&#xff0c;交通运输总量将保持较快增长态势&#xff0c;各项事业发展要求提高国家公路网的服务能力和水平。高速公路沿线的收费站、互通枢纽、服务区、隧道等配置的供配电、…

白令海峡的题解

目录 原题描述&#xff1a; 题目描述 输入格式 输出格式 样例输入 样例输出 样例解释 数据规模 主要思路&#xff1a; 小细节&#xff1a; 代码code: 原题描述&#xff1a; 时间限制: 1000ms 空间限制: 524288kB 题目描述 很久很久以前&#xff0c;一座大陆桥横…

云图极速版限时免费活动

产品介绍 云图极速版是针对拥有攻击面管理需求的用户打造的 SaaS 应用&#xff0c;致力于协助用户发现并管理互联网资产攻击面。 实战数据 (2023.11.6 - 2024.2.23) 云图极速版上线 3 个月以来&#xff0c;接入用户 3,563 家&#xff0c;扫描主体 19,961 个&#xff0c;累计发…

Atcoder ABC341 A-D题解

比赛链接:ABC341 Problem A: 先签个到。 #include <bits/stdc.h> using namespace std; int main() {int n;cin>>n;for(int i0;i<n;i)cout<<"10"<<endl;cout<<"1"<<endl;return 0; } Problem B: 继续签。 #i…

3D模型可视化引擎HOOPS Visualize V2024版全新发布:增强了大量点云数据集的处理,与HOOPS系列产品集合实现照片级渲染!

HOOPS Visualize是一款工业级3D渲染引擎&#xff0c;可以用于打造移动端和PC端工程应用程序&#xff0c;其灵活、分层的场景管理引擎&#xff0c;支持处理各种3D模型实体&#xff0c;其高性能图形和交互处理算法&#xff0c;支持大型模型可视化&#xff0c;现已帮助达索 SOLIDW…

这两招,让你轻松俘获客户心

面向政府的数字化解决方案作为睿鸿数字应用的一个分支&#xff0c;在充分借鉴政府项目中积累的丰富经验的基础上&#xff0c;积极开发更多领域通用的标准化产品。 2023年&#xff0c;睿鸿推出了一系列创新的数字应用产品&#xff0c;包括动态表单系统、统一集成门户、统一通信中…

你听说过柔性数组吗?

目录 1. 柔性数组的概念 2. 柔性数组的特点 3. 柔性数组的使用 4. 柔性数组的优势 5.完结散花 悟已往之不谏&#xff0c;知来者犹可追 创作不易&#xff0c;宝子们&#xff01;如果这篇文章对你们有帮助的话&#…

动态SLAM:基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法)

基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法) 写上篇文章时测试过程比较乱&#xff0c;写的时候有些地方有点失误&#xff0c;所以重新写了这篇 本文内容均在RGB-D环境下进行程序测试 本文涉及到的动态特征点剔除速度均是以https://cvg.cit.tum.de/data/datasets/rgbd-dat…

RF 框架实现企业级 UI 自动化测试

RobotFramework 框架可以作为公司要做自动化 但是又不会代码的一种临时和紧急情况的替代方案&#xff0c;上手简单。 前言 现在大家去找工作&#xff0c;反馈回来的基本上自动化测试都是刚需&#xff01;没有自动化测试技能&#xff0c;纯手工测试基本没有什么市场。 但是很多…

【动态规划】【回文】【字符串】1147. 段式回文

作者推荐 【广度优先搜索】【网格】【割点】【 推荐】1263. 推箱子 本文涉及知识点 动态规划汇总 LeetCode1147段式回文 你会得到一个字符串 text 。你应该把它分成 k 个子字符串 (subtext1, subtext2&#xff0c;…&#xff0c; subtextk) &#xff0c;要求满足: subtext…

如何将QQ音乐的歌单导出到excel

一、提前准备 1.选择你需要导出的音乐歌单 2.得到你的歌单ID 1、首先打开QQ音乐&#xff0c;找到想要查看的歌单&#xff0c;点击歌单右上角的更多按钮。 2、其次在弹出的菜单中选择分享&#xff0c;在分享页面中&#xff0c;选择歌单分享。 3、最后在分享页面中&#xff0c…

kafka和ZK的关系

zk相当于是kafka的一个基础设施 Kafka是一种高吞吐量、可扩展的分布式发布订阅消息系统&#xff0c;ZooKeeper是一个分布式协调服务&#xff0c;用于管理和协调分布式系统中的各种资源 Zookeeper&#xff1a;管理broker&#xff0c;consumer 创建broker后&#xff0c;向zk注册…

Leetcoder Day18| 二叉树 part07

语言&#xff1a;Java/Go 今天做了一个小决定&#xff0c;如果时间不够的话&#xff0c;可以先看go去找实习&#xff0c;所以现在加上用go去刷题 530.二叉搜索树的最小绝对差 给你一棵所有节点为非负值的二叉搜索树&#xff0c;请你计算树中任意两节点的差的绝对值的最小值。…

Stable Diffusion 绘画入门教程(webui)-ControlNet(深度Depth)

上篇文章介绍了线稿约束&#xff0c;这篇文章介绍下深度Depth 文章目录 一、选大模型二、写提示词三、基础参数设置四、启用ControlNet 顾名思义&#xff0c;就是把原图预处理为深度图&#xff0c;而深度图可以区分出图像中各元素的远近关系&#xff0c;那么啥事深度图&#xf…