一面

15号的比较早,9:30左右,等了一会,叫号,过去面试,自我介绍完,先拿出来了笔试时候的题目让复盘一下,我用的还是投实习时候过的,正式批就没有笔试,简单看下,大致说出了思路。

然后说重点讲三个项目,我就讲一个实习+两个项目了。

开始问实习,也是介绍完之后问细节,具体也问了不少,然后讲第一个和第二个项目,讲完让手撕个题目,题目是一段01的比特流字符串,给一个target是0或者1,然后比特流只能变一位,求最多多少个连续的target,想了几分钟双指针写了出来。总体来说,一面还是比较友好的。

二面

等了一会就二面了,二面过去自我介绍完,我讲完实习,就问了几个套路性的常用问题,大概不到十分钟,然后就给一个手撕题目,场景题,用卷积算二阶导,对图像做边缘检测。这个没怎么见过,没想出来,要用题目给定的方法做,大致写了下,然后就结束了,写的应该不太对。面试官直接说今天面试结束了可以回去了,然后就短信通知今天的结束了,进入系统一看,果然挂了。

这种手撕场景题不太好准备,没得办法,二面都没怎么问,手撕g就g了,这题真没见过,太难了,全程都没问八股,二面一堆项目都没问,实习问的比一面还浅,没办法。

我回头问了我我同学们,还没有见过有二面挂的,他们题目都可以三选一,而且基本都是力扣,还都不是很难的那种,出这个题他们也都不会,让面试官给提示也不给,只报还剩下多少时间。毕竟连项目和八股都不问的面试我还是第一次见,一面的面试官就好的多。

3d0afaab4a49212c06ee3d91bc12e82

我回去复盘了一下,这个题大致应该是这样的,总体来说也不能算完全的hard,但是难就难在开始这部分,如何用[1,-1]和$[1,-1]^T$计算拉普拉斯算子,后面的就很容易了。

20241017224856

ChatGPT给的答案是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
def edge_detection_laplacian(image):
# 获取图像尺寸
rows, cols = len(image), len(image[0])

# 定义Laplacian卷积核g
g = [[0, -1, 0],
[-1, 4, -1],
[0, -1, 0]]

# 添加padding, 初始化f为图像+2边框的0矩阵
f = [[0 for _ in range(cols + 2)] for _ in range(rows + 2)]

# 将原始图像数据填充到f的中心部分
for i in range(rows):
for j in range(cols):
f[i + 1][j + 1] = image[i][j]

# 创建结果矩阵,用于存储边缘检测的结果
result = [[0 for _ in range(cols)] for _ in range(rows)]

# 主卷积循环,遍历图像中的每一个像素
for i in range(1, rows + 1):
for j in range(1, cols + 1):
# 进行卷积操作
conv_sum = 0
for m in range(3):
for n in range(3):
conv_sum += f[i + m - 1][j + n - 1] * g[m][n]

# 将卷积结果存入结果矩阵
result[i - 1][j - 1] = conv_sum

return result

# 示例输入
image = [
[1, 2, 1, 0],
[4, 5, 6, 1],
[7, 8, 9, 2],
[3, 4, 5, 6]
]

# 调用Laplacian边缘检测函数
edge_result = edge_detection_laplacian(image)

# 输出结果
for row in edge_result:
print(row)

但是他这个回答没有给出拉普拉斯算子怎么算的,其实这个算子我也是知道,也会用,其实早在投实习的时候一面就问了这个算子,我直接手写了出来,但是如果不给算子,而是用[1,-1]和$[1,-1]^T$计算拉普拉斯算子,再算的话,就不太容易了。我当时只算了水平的,没有算垂直的,水平垂直的叠加其实就可以了,有算子之后后面就容易了。

chatgpt给出了推导过程:

1. 一阶导数的离散化

在连续情况下,函数 f(x) 的一阶导数是:

$$
f’(x) = \frac{d}{dx}f(x)
$$

在离散情况下,我们用差分来近似一阶导数。在离散网格上,假设 f(x) 是一组离散的数值表示(如图像中的像素值),我们可以用向前差分向后差分来近似一阶导数。

向前差分表示为:

$$
f’(x) \approx f(x+1) - f(x)
$$

这相当于卷积核 [1, -1],它计算当前点与下一个点的差值。

向后差分表示为:

$$
f’(x) \approx f(x) - f(x-1)
$$

这相当于卷积核 [-1, 1]

如果我们想取中间值(中心差分),可以将这两个差分的平均值作为一阶导数的离散近似:

$$
f’(x) \approx \frac{f(x+1) - f(x-1)}{2}
$$

这一中心差分可以表示为卷积核 [1, 0, -1],它计算左右相邻点的差异。

2. 二阶导数的离散化

二阶导数表示的是函数变化的变化率。二阶导数是通过对一阶导数再次求导数得到的。在连续情况下,二阶导数是:

$$
f’’(x) = \frac{d^2}{dx^2}f(x)
$$

对于离散网格,我们可以用差分的形式来近似二阶导数。

3. 从一阶导数推导二阶导数

假设我们已经知道一阶导数的离散近似表示为 f'(x) = f(x+1) - f(x),那么二阶导数可以通过对一阶导数再次取差分来计算:

$$
f’’(x) \approx f’(x+1) - f’(x)
$$

将一阶导数的表达式代入:

$$
f’’(x) \approx (f(x+2) - f(x+1)) - (f(x+1) - f(x))
$$

展开后得到:

$$
f’’(x) \approx f(x+2) - 2f(x+1) + f(x)
$$

这就是二阶导数的离散近似形式。其卷积核为 [1, -2, 1],它计算当前像素值及其左右两个像素值的加权和,能够检测到亮度变化的速率,也就是图像中的曲率。

4. 解读 [1, -2, 1]

  • 1:代表距离当前像素一个单位距离的前后像素值的贡献。
  • -2:代表当前像素的值,权重大,表示它与左右两个像素的关系。
  • 1:再次代表左右相邻像素的贡献。

这个差分算子 [1, -2, 1] 通过结合当前像素与其左右像素的值,近似计算二阶导数,检测出图像中变化最剧烈的部分(例如边缘或轮廓)。

5. 二维情况:Laplacian 算子

在二维图像处理的场景下,类似的二阶导数可以推广到多个方向。我们可以分别对 x 方向和 y 方向应用上述 [1, -2, 1] 的差分算子,得到图像在这两个方向的二阶导数。然后通过将两个方向的二阶导数合并,我们得到 Laplacian 算子,其标准形式是:

$$
g = \begin{bmatrix} 0 & -1 & 0 \ -1 & 4 & -1 \ 0 & -1 & 0 \end{bmatrix}
$$

其中:

  • 中心位置的 4 对应着当前像素值的权重。
  • -1 表示与上下左右像素的二阶差分贡献。

这一卷积核检测的是像素与其邻域的二阶亮度变化,从而可以用于边缘检测。

总结

总之,这个题不算拉普拉斯的推导就是easy,但是算上的话,就不太容易,我当时算出来了水平的梯度了$[-1,2,-1]$,垂直的应该也是一样的,但是把垂直的和水平的合并就不会了,合并了就是拉普拉斯算子了,后面就没啥了。

血亏