本文给大家带来的百面算法工程师是传统图像处理的面试总结,文章内总结了常见的提问问题,旨在为广大学子模拟出更贴合实际的面试问答场景。在这篇文章中,我们将总结一些几何变换和图像平滑处理,并提供参考的回答及其理论基础,以帮助求职者更好地准备面试。通过对这些问题的理解和回答,求职者可以展现出自己的传统图像处理领域的专业知识、解决问题的能力以及对实际应用场景的理解。同时,这也是为了帮助求职者更好地应对深度学习目标检测岗位的面试挑战,提升面试的成功率和竞争力。
目录
13.1 HSV色彩空间
13.2 swish激活函数
13.3 OpenCV——几何变换
13.3.1 缩放
13.3.2 翻转
13.3.3 仿射
13.3.4 透视
13.4 图像平滑处理
13.4.1 均值滤波
13.4.2 方框滤波
13.4.3 高斯滤波
13.4.4 中值滤波
13.4.5 双边滤波
13.4.6 横向对比
13.5 图像梯度
13.5.1 Sobel 理论基础、函数使用
13.5.2 Scharr 算子及函数使用
13.5.3 Laplacian 算子及函数使用
13.5.4 Canny边缘检测
13.5.5 横向对比
欢迎大家订阅我的专栏一起学习共同进步
祝大家早日拿到offer! let's go
🚀🚀🚀http://t.csdnimg.cn/dfcH3🚀🚀🚀
13.1 HSV色彩空间
RGB 是从硬件的角度提出的颜色模型,在与人眼匹配的过程中可能存在一定的差异,HSV 色彩空间是一种面向视觉感知的颜色模型。HSV 色彩空间从心理学和视觉的角度出发,指出人 眼的色彩知觉主要包含三要素:色调(Hue,也称为色相)、饱和度(Saturation)、亮度(Value), 色调指光的颜色,饱和度是指色彩的深浅程度,亮度指人眼感受到的光的明暗程度。
- 色调:色调与混合光谱中的主要光波长相关,例如“赤橙黄绿青蓝紫”分别表示不同的 色调。如果从波长的角度考虑,不同波长的光表现为不同的颜色,实际上它们体现的是 色调的差异。
- 饱和度:指相对纯净度,或一种颜色混合白光的数量。纯谱色是全饱和的,像深红色(红 加白)和淡紫色(紫加白)这样的彩色是欠饱和的,饱和度与所加白光的数量成反比。
- 亮度:反映的是人眼感受到的光的明暗程度,该指标与物体的反射度有关。对于色彩来 讲,如果在其中掺入的白色越多,则其亮度越高;如果在其中掺入的黑色越多,则其亮 度越低。
Caution
在 OpenCV 内,我们使用 cv2.cvtColor()函数实现色彩空间的变换。该函数能够实现多个色 彩空间之间的转换。其语法格式为:
dst = cv2.cvtColor( src, code [, dstCn] )
- dst 表示输出图像,与原始输入图像具有同样的数据类型和深度。
- src 表示原始输入图像。可以是 8 位无符号图像、16 位无符号图像,或者单精度浮点数等。
- code 是色彩空间转换码
- dstCn 是目标图像的通道数。如果参数为默认的 0,则通道数自动通过原始输入图像和 code 得到。
当图像由 RGB 色彩空间转换到 GRAY 色彩空间时,其处理方式如下: Gray = 0.299 · 𝑅 + 0.587 · 𝐺 + 0.114 · B
13.2 swish激活函数
Swish(x) = x*sigmoid(ßx)
其中,ß 为可学习参数。Swish可以比ReLU激活函数更好,因为它在0附近提供了更平滑的转换,这可以带来更好的优化。
13.3 OpenCV——几何变换
13.3.1 缩放
dst = cv2.resize( src, dsize[, fx[, fy[, interpolation]]] )
# interpolation 代表插值方式, 默认是双线性插值(cv2.INTER_LINEAR)
# 在 cv2.resize()函数中,目标图像的大小可以通过“参数 dsize”或者“参数 fx 和 fy”二者之一来指定
当缩小图像时,使用区域插值方式(INTER_AREA)能够得到最好的效果;当放大图像时, 使用三次样条插值(INTER_CUBIC)方式和双线性插值(INTER_LINEAR)方式都能够取得 较好的效果。三次样条插值方式速度较慢,双线性插值方式速度相对较快且效果并不逊色。
13.3.2 翻转
dst = cv2.flip( src, flipCode )
# flipCode 代表旋转类型。
filpCode
为0,绕着x轴旋转
为正,绕着y轴旋转
为负,绕着x,y轴同时翻转
13.3.3 仿射
仿射变换是指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。该变换能够 保持图像的平直性和平行性。平直性是指图像经过仿射变换后,直线仍然是直线;平行性是指 图像在完成仿射变换后,平行线仍然是平行线。
OpenCV 中的仿射函数为 cv2.warpAffine(),其通过一个变换矩阵(映射矩阵)M 实现变换,具体为:
dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)
dst = cv2.warpAffine( src, M, dsize[, flags[, borderMode[, borderValue]]])
# flags 代表插值方法,默认为 INTER_LINEAR。
# borderMode 代表边类型, 默认为 BORDER_CONSTANT。
在 OpenCV 中使用函数 cv2.warpAffine()实现仿射变换,忽略其可选参数后的语法格式为:
dst = cv2.warpAffine( src , M , dsize)
其通过转换矩阵 M 将原始图像 src 转换为目标图像 dst:
dst(𝑥, 𝑦) = src(𝑀11𝑥 + 𝑀12𝑦 + 𝑀13, 𝑀21𝑥 + 𝑀22𝑦 + 𝑀23)
通过此函数可以实现平移旋转和更加复杂的仿射变换
13.3.4 透视
仿射变换可以将矩形映射为任意平行四边形,透视变换则可以将矩形映射为任意四边形。
透视变换通过函数 cv2.warpPerspective()实现,该函数的语法是:
dst = cv2.warpPerspective( src, M, dsize[, flags[, borderMode[, borderValue]]])
与仿射变换一样,同样可以使用一个函数来生成函数 cv2.warpPerspective()所使用的转换矩阵。该函数是 cv2.getPerspectiveTransform(),其语法格式为:
retval = cv2.getPerspectiveTransform(src, dst)
# src 代表输入图像的四个顶点的坐标。
# dst 代表输出图像的四个顶点的坐标。
Caution
src 参数和 dst 参数是包含四个点的数组,与仿射变换函数 cv2.getAffineTransform()中的三个点是不同的。
13.4 图像平滑处理
13.4.1 均值滤波
在进行均值滤波时,首先要考虑需要对周围多少个像素点取平均值。通常情况下,我们会 以当前像素点为中心,对行数和列数相等的一块区域内的所有像素点的像素值求平均。可以以当前像素点为中心,对周围 3×3 区域内所有像素点的像素值求平均,也可 以对周围 5×5 区域内所有像素点的像素值求平均。
Caution
针对边缘像素点,可以只取图像内存在的周围邻域点的像素值均值。如下图所示,计算 左上角的均值滤波结果时,仅取图中灰色背景的 3×3 邻域内的像素值的平均值。
除此以外,还可以扩展当前图像的周围像素点。例如,将当前 9×7 大小的图像扩展为 13×11 大小的图像
dst = cv2.blur( src, ksize, anchor, borderType )
# anchor 是锚点,其默认值是(-1, -1),表示当前计算均值的点位于核的中心点位置。该值使用默认值即可,在特殊情况下可以指定不同的点作为锚点。
卷积核越大,参与到均值运算中的像素就会越多,即当前点计算的是更多点的像素值的平 均值。因此,卷积核越大,去噪效果越好,当然花费的计算时间也会越长,同时让图像失真越 严重。在实际处理中,要在失真和去噪效果之间取得平衡,选取合适大小的卷积核。
13.4.2 方框滤波
与均值滤波的不同在于,方框滤波不会计算像素均值。 在均值滤波中,滤波结果的像素值是任意一个点的邻域平均值,等于各邻域像素值之和除以邻 域面积。而在方框滤波中,可以自由选择是否对均值滤波的结果进行归一化,即可以自由选择 滤波结果是邻域像素值之和的平均值,还是邻域像素值之和。
在进行方框滤波时,如果计算的是邻域像素值的均值
在进行方框滤波时,如果计算的是邻域像素值之和
dst = cv2.boxFilter( src, ddepth, ksize, anchor, normalize, borderType )
normalize 表示在滤波时是否进行归一化(这里指将计算结果规范化为当前像素值范围 内的值)处理,该参数是一个逻辑值,可能为真(值为 1)或假(值为 0)。 【normalize 为默认值 True】
- 当参数 normalize=1 时,表示要进行归一化处理,要用邻域像素值的和除以面积。
- 当参数 normalize=0 时,表示不需要进行归一化处理,直接使用邻域像素值的和。
13.4.3 高斯滤波
在进行均值滤波和方框滤波时,其邻域内每个像素的权重是相等的。在高斯滤波中,会将 中心点的权重值加大,远离中心点的权重值减小,在此基础上计算邻域内各个像素值不同权重的和。
实际使用时往往需要进行归一化。严格来讲,使用没有进行归一化 处理的卷积核进行滤波,得到的结果往往是错误的。
dst = cv2.GaussianBlur( src, ksize, sigmaX, sigmaY, borderType )
# sigmaX 是卷积核在水平方向上(X 轴方向)的标准差,其控制的是权重比例。
# sigmaY 是卷积核在垂直方向上(Y 轴方向)的标准差。如果将该值设置为 0,则只采用sigmaX 的值;如果 sigmaX 和 sigmaY 都是 0,则通过 ksize.width 和 ksize.height 计算得到。
13.4.4 中值滤波
中值滤波与前面介绍的滤波方式不同,不再采用加权求均值的方式计算滤波结果。它用邻 域内所有像素值的中间值来替代当前像素点的像素值。
中值滤波会取当前像素点及其周围临近像素点(一共有奇数个像素点)的像素值,将这些 像素值排序,然后将位于中间位置的像素值作为当前像素点的像素值。
dst = cv2.medianBlur( src, ksize)
在中值滤波处理中,噪声成分很难被选上,所以可以在几乎不影响原有图像的情 况下去除全部噪声。但是由于需要进行排序等操作,中值滤波需要的运算量较大。
Note
在均值滤波、方框滤波、高斯滤波中,都会计算边缘上各个像素点的加权平均值,从而模 糊边缘信息。
13.4.5 双边滤波
双边滤波是综合考虑空间信息和色彩信息的滤波方式,在滤波过程中能够有效地保护图像 内的边缘信息。双边滤波在计算某一个像素点的新值时,不仅考虑距离信息(距离越远,权重越小),还 考虑色彩信息(色彩差别越大,权重越小)。双边滤波综合考虑距离和色彩的权重结果,既能 够有效地去除噪声,又能够较好地保护边缘信息。
在双边滤波中,当处在边缘时,与当前点色彩相近的像素点(颜色距离很近)会被给予较 大的权重值;而与当前色彩差别较大的像素点(颜色距离很远)会被给予较小的权重值(极端 情况下权重可能为 0,直接忽略该点),这样就保护了边缘信息。
dst = cv2.bilateralFilter( src, d, sigmaColor, sigmaSpace, borderType )
13.4.6 横向对比
平滑处理 | 特点 | 优点 | 缺点 |
均值滤波 | 使用邻域内像素的平均值来替换中心像素的值。 | 实现简单,计算速度快。 | 对较大的噪声有限制,可能导致图像细节丢失。 |
方框滤波 | 使用邻域内像素的均值来替换中心像素的值,但是相对于均值滤波,方框滤波使用加权均值。 | 相比均值滤波,对噪声有更好的抑制效果。 | 对较大的噪声有限制,可能导致图像细节丢失。 |
高斯滤波 | 使用高斯核对邻域内像素进行加权平均,使得距离中心像素越近的像素具有更高的权重。 | 能够平滑图像并保留边缘信息。 | 计算量较大,对性能要求较高。 |
中值滤波 | 将邻域内像素的值按照大小排序,然后选择中间值来替换中心像素的值。 | 能够有效地去除椒盐噪声等类型的噪声。 | 对于高斯噪声等连续性噪声的效果可能不如其他方法。 |
双边滤波 | 结合了空间域和灰度值域的信息,保留了图像的边缘信息的同时平滑图像。 | 能够平滑图像并保留边缘信息。 | 计算量大,对性能要求较高。 |
13.5 图像梯度
13.5.1 Sobel 理论基础、函数使用
Sobel 算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。
dst = cv2.Sobel( src, ddepth, dx, dy[,ksize[, scale[, delta[, borderType]]]] )
- dst 代表目标图像。
- src 代表原始图像。
- ddepth 代表输出图像的深度。
- dx 代表 x 方向上的求导阶数。
- dy 代表 y 方向上的求导阶数。
- ksize 代表 Sobel 核的大小。该值为-1 时,则会使用 Scharr 算子进行运算。
- scale 代表计算导数值时所采用的缩放因子,默认情况下该值是 1,是没有缩放的。
- delta 代表加在目标图像 dst 上的值,该值是可选的,默认为 0。
- borderType 代表边界样式。
13.5.2 Scharr 算子及函数使用
在离散的空间上,有很多方法可以用来计算近似导数,在使用 3×3 的 Sobel 算子时,可能 计算结果并不太精准。OpenCV 提供了 Scharr 算子,该算子具有和 Sobel 算子同样的速度,且 精度更高。可以将 Scharr 算子看作对 Sobel 算子的改进,其核通常为:
dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )
- dst 代表输出图像。
- src 代表原始图像。
- ddepth 代表输出图像深度。该值与函数 cv2.Sobel()中的参数 ddepth 的含义相同。
- dx 代表 x 方向上的导数阶数。
- dy 代表 y 方向上的导数阶数。
- scale 代表计算导数值时的缩放因子,该项是可选项,默认值是 1,表示没有缩放。
- delta 代表加到目标图像上的亮度值,该项是可选项,默认值为 0。
- borderType 代表边界样式。
13.5.3 Laplacian 算子及函数使用
Laplacian(拉普拉斯)算子是一种二阶导数算子,其具有旋转不变性,可以满足不同方向 的图像边缘锐化(边缘检测)的要求。通常情况下,其算子的系数之和需要为零。
Laplacian 算子类似二阶 Sobel 导数,需要计算两个方向的梯度值。
dst = cv2.Laplacian( src, ddepth[, ksize[, scale[, delta[, borderType]]]] )
- dst 代表目标图像。
- src 代表原始图像。
- ddepth 代表目标图像的深度。
- ksize 代表用于计算二阶导数的核尺寸大小。该值必须是正的奇数。
- scale 代表计算 Laplacian 值的缩放比例因子,该参数是可选的。默认情况下,该值为 1, 表示不进行缩放。
- delta 代表加到目标图像上的可选值,默认为 0。
- borderType 代表边界样式。
13.5.4 Canny边缘检测
Canny 边缘检测是一种使用多级边缘检测算法检测边缘的方法。1986 年,John F. Canny 发 表了著名的论文 A Computational Approach to Edge Detection,在该论文中详述了如何进行边缘 检测。 OpenCV 提供了函数 cv2.Canny()实现 Canny 边缘检测。
左图显示的是三个边缘信息,右图是对边缘信息进行分类的示意图,具体 划分如下:
- A 点的梯度值值大于 maxVal,因此 A 是强边缘。
- B 和 C 点的梯度值介于 maxVal 和 minVal 之间,因此 B、C 是虚边缘。
- D 点的梯度值小于 minVal,因此 D 被抑制(抛弃)。
edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
13.5.5 横向对比
算子 | 类型 | 用途 | 特点 |
Sobel算子 | 梯度算子 | 边缘检测 | 1. Sobel算子是一种离散型梯度算子,通常用于边缘检测和图像处理中的梯度计算。它基于卷积操作,可以计算出图像中每个像素点的梯度值,从而识别出图像中的边缘。 |
Scharr算子 | 梯度算子 | 边缘检测 | 1. Scharr算子与Sobel算子类似,也是一种离散型梯度算子,用于边缘检测。它相对于Sobel算子而言更加敏感,对噪声有更好的抑制能力。 |
Laplacian算子 | 二阶导数算子 | 边缘检测 | 1. Laplacian算子是一种二阶导数算子,用于在图像中检测边缘和提取特征。它通过计算图像中像素值的二阶导数来寻找像素值的突变点,从而定位边缘。 |
Canny算子 | 多阶段算子 | 边缘检测 | 1. Canny边缘检测算法是一种经典的多阶段边缘检测算法,包括多个步骤:噪声抑制、边缘强度计算、边缘细化和边缘连接。 |