金山办公CV算法岗笔试复盘:从图像处理到深度学习全解析
发布时间:2026/9/1 12:29:54 作者:尧图编辑部 阅读量:1,286

金山办公2020校园招聘的计算机视觉算法工程师笔试我印象很深。它和网上那种刷题App里的通用AI岗笔试题很不一样题目刻意往“产品落地”方向靠基础算法和数据结构占一部分传统图像处理也有不少篇幅深度学习基础知识是重头戏最后还会来一道类似“拍一张歪斜的身份证照片你怎么把它还原成规整的扫描件”这样的综合设计题。这种风格其实非常符合金山办公的实际情况WPS里大量功能比如文档扫描、OCR识别、图片转表格、证件照处理背后都是计算机视觉团队在支撑。如果你也在准备计算机视觉方向的校招笔试或者对这类岗位的考察重点好奇这篇复盘应该能帮到你。1. 先聊这套笔试题的“性格”不是竞赛题是产品题1.1 笔试题结构与题量分布我记得整套题大概分四个部分选择题或判断题、编程题、简答题、综合设计题。题量不小大概两个小时内要完成时间非常紧张。选择题重点考数学基础、机器学习基础、图像处理概念偶尔会夹一两道概率统计的简单计算。编程题一般是两道到三道难度从LeetCode简单到中等不等重点考察字符串、动态规划、二叉树这类经典内容很少出现特别偏门的数据结构题。简答题通常是针对深度学习模型原理进行描述比如“为什么ResNet能训练得更深”“BN层的作用”这类。整场笔试里最特别的是最后那道综合设计题会给你一个具体场景让你从图像采集、预处理、算法选型、模型部署到异常处理完整讲一遍你的方案。这个题目没有标准答案考察的是你有没有做过真实项目是否具备从0到1搭建系统的能力。1.2 和纯算法岗相比金山办公更看重什么我当时在牛客网上看过不少人分享面经发现金山办公的CV岗有个特点业务导向极强。他们不指望你发过顶会论文但期望你熟悉OpenCV、PyTorch/TensorFlow理解OCR和图像处理流程知道模型怎么压缩怎么上端。WPS的“拍照扫描”功能是核心卖点用户拿手机随便一拍系统要自动裁剪、矫正、增强、识别这对视觉算法的要求非常实务。因此笔试里的题目也延续了这个风格像“图像的直方图均衡化”“透视变换参数怎么算”“卷积层的感受野怎么计”这类问题背后都有具体应用场景。如果你只是背过概念做题时容易卡壳如果你实际动手处理过图像很多题一眼就能看穿。这是这类笔试最明显的特性。2. 开场编程题热身字符串、DP和边界条件的基层操作笔试的前半段通常会有算法题热身两到三道编程题主要考察基本功。不是让你做那种4小时AC的难题而是看你能不能快速写出健壮、规范的代码。这里我把当时考到的题型和类似变体整理出来你可以直接拿去做练习。2.1 字符串匹配与KMPnext数组到底考了几层字符串匹配在图像算法里其实很少直接用但它作为基础题出现频率极高。笔试里有一道题大概是这样的给定一个主串和一个模式串如果是普通字符串匹配直接暴力也能过但题目会要求你输出模式串的next数组再用KMP算法实现匹配。我记得当时有个很容易搞混的点模式串p abacaba求它的next数组。很多人会背KMP模板但一让手推next就乱了。这里有个小技巧next数组存的是最长相同前后缀的长度有的写法还会把next[0]设为-1。你需要先明确自己用的是哪套定义再按定义推。以abacaba为例按“前缀等于后缀的最长长度”这个定义来推next[0]长度为1的子串是a没有真前后缀记0。next[1]子串ab前缀a、后缀b不相等等于0。next[2]子串aba前缀a、后缀a相等长度为1前缀ab、后缀ba不相等所以取1。next[3]子串abac最长相同前后缀是0。next[4]子串abaca最长相同前后缀是1a。next[5]子串abacab最长相同前后缀是2ab。next[6]子串abacaba最长相同前后缀是3aba。最后得到的next数组是[0, 0, 1, 0, 1, 2, 3]。注意不同教程next数组的偏移不一样有的把next[0]定成-1有的整体前移一位答题时最好先写清楚自己的定义。这道题真正想考察的不是你能不能默写而是你有没有理解“失配时模式串应该跳到哪个位置”这件事背后的逻辑。2.2 一道变体动态规划编辑距离与最长公共子序列编程题里还常考动态规划。我记得有一版题目是“计算两个字符串的编辑距离”LeetCode 72题。但在笔试场景下很多人会卡在初始化表和边界条件上所以如果平时没专门练过现场很容易写崩。编辑距离的状态转移其实很直观设dp[i][j]表示字符串A的前i个字符转换成字符串B的前j个字符的最少操作数。初始化的时候dp[i][0] i因为要从长度为i的字符串变成空串只能逐个删除dp[0][j] j同理是逐个插入。当A[i-1] B[j-1]时dp[i][j] dp[i-1][j-1]否则取三种操作的最小值加1。def edit_distance(a: str, b: str) - int: m, n len(a), len(b) dp [[0] * (n 1) for _ in range(m 1)] for i in range(1, m 1): dp[i][0] i for j in range(1, n 1): dp[0][j] j for i in range(1, m 1): for j in range(1, n 1): if a[i - 1] b[j - 1]: dp[i][j] dp[i - 1][j - 1] else: dp[i][j] min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) 1 return dp[m][n]这类题还会派生出最长公共子序列、最长回文子序列等变体本质都是二维DP。我当时给的建议是考场上一旦看到两个序列相关的题优先往编辑距离和LCS上想先把状态定义写清楚再推转移方程。2.3 栈和队列在图像遍历中的影子还有一题印象比较深和二叉树层次遍历有关。原本是一道普通题目但当时考场上有人卡了很久因为没反应过来可以用队列做层序遍历。后来我看这次笔试题感觉它其实是想借算法题考察你“能不能把数据结构用在合适的场景”因为图像处理里的连通域分析、BFS自适应阈值这些操作本质也是队列和栈的应用。例如用队列做二叉树层序遍历from collections import deque def level_order(root): if not root: return [] res, q [], deque([root]) while q: level [] for _ in range(len(q)): node q.popleft() level.append(node.val) if node.left: q.append(node.left) if node.right: q.append(node.right) res.append(level) return res如果你做过图像连通域标记会发现它和BFS在二维网格上的遍历思路一模一样。这种题不会直接挂在图像概念上但它考察的思维方式和视觉算法里的区域生长、边缘追踪是相通的。3. 图像处理与特征工程笔试里的传统CV弹药库金山办公的CV笔试对传统图像处理内容的考察比例不小尤其是滤波、边缘检测、色彩空间这些基础。它们不算难但概念很碎如果平时只跑深度学习模型没做过图像预处理很容易答混。这里挑几类高频题展开讲。3.1 图像去噪与锐化各种滤波算子怎么选有一类选择题会问“高斯滤波和均值滤波的区别是什么”“中值滤波适合处理什么噪声”。这类题看似简单但隐含了实际产品选择。高斯滤波是加权平均保留更多图像整体结构适合处理高斯噪声均值滤波简单粗暴但容易让边缘变模糊中值滤波对椒盐噪声效果极好因为它取邻域中值能直接滤掉孤立噪点。我记得有一道题给了一小段像素矩阵让手动计算3×3窗口中值滤波的结果。这种题没有什么捷径就是把窗口内的像素排序取中间值。平时你用OpenCV一行cv2.medianBlur就完事但笔试就是要你把这个过程展开考察你到底懂不懂背后的含义。至于图像锐化通常会考拉普拉斯算子。公式是output original α * Laplacian(original)本质是提取高频分量再加回去。在WPS文档扫描场景里拍出来的文档经常发灰文字边缘不清晰做锐化能显著提升后续OCR的准确率。笔试里可能会让你写拉普拉斯算子的卷积核一般来说是0 1 0 1 -4 1 0 1 0也有些变体在对角线方向再加权重。你只要记住“中心为负、周围为正、所有系数和为0”这个特点就能快速判断一个卷积核是不是拉普拉斯算子。3.2 边缘检测与特征点从Sobel到SIFT边缘检测几乎是必考的。Sobel算子、Canny边缘检测、Laplacian算子的区别要能讲清楚。Sobel是基于一阶导数的近似有水平核和垂直核水平方向 Gx -1 0 1 -2 0 2 -1 0 1 垂直方向 Gy -1 -2 -1 0 0 0 1 2 1Canny不是一个算子而是一整套流程高斯模糊去噪Sobel求梯度幅值和方向非极大值抑制双阈值检测边缘连接。笔试里如果问“Canny比Sobel好在哪”答案的核心就是Canny做了抑制和滞后阈值边缘更连续、更细、更干净。SIFT这类特征点检测题在笔试里偏概念化比如“SIFT特征对哪些变换具有不变性”“描述子的维度是多少”。SIFT特征对尺度缩放、旋转、亮度变化具有较好的不变性描述子维度是128维。虽然现在深度学习特征已经很强但传统特征在图像配准、拼接场景里依然有它的价值尤其是计算资源受限的时候。3.3 颜色空间与直方图均衡化的计算题色彩空间转换也是高频考点。RGB转灰度最常用的是加权平均公式Gray 0.299 * R 0.587 * G 0.114 * B这个权重不是随便定的它考虑了人眼对绿色最敏感、对蓝色最不敏感的特性。有的题会给你一个像素的RGB值让你算灰度值或是反过来问YUV、HSV中的某个分量代表什么。直方图均衡化是一道经典计算题它就是把灰度分布拉伸到更均匀提升对比度。笔试里可能会有这样的题给出一张4×4图像的灰度值让你计算均衡化后的灰度映射关系。你需要先统计每个灰度级出现的概率再计算累积分布函数最后映射到新的灰度级。有一次我把相机对着过曝的白纸拍整张图灰蒙蒙OCR识别率非常低。后来在预处理里加了直方图均衡化文字的边缘信息一下子清晰了很多。这类题目不是单纯靠记忆而是希望你在实际图像上体会过这些操作的效果。所以准备笔试前我建议你打开OpenCV把每个常见操作都在真实图片上跑一遍比单纯背公式有用得多。4. 深度学习基础题从感受野到模型轻量化深度学习是视觉算法工程师笔试题的重头戏占比最高。这部分考的不是最新的论文细节而是那些“你以为自己会但一写就错”的基础概念。我整理几个高频必考点每一个都值得认真过一遍。4.1 卷积层感受野、参数量与计算量“一个5×5卷积核经过两层3×3卷积后感受野是多少”这题在笔试里出了好多次答案不是5×5就是7×7很多人会记混。实际上第一层3×3卷积后输出的每个像素对应原图3×3区域第二层3×3卷积后对应区域向外各扩1个像素也就是5×5。如果再叠一层3×3卷积感受野会变成7×7。所以用两层3×3卷积替换一个5×5卷积感受野相同但参数量更小。两层3×3的参数量是2 * 3 * 3 * C * C 18C²一个5×5卷积是25C²明显减少。这就是为什么VGG和ResNet都爱叠小卷积核。参数量计算也是必考。一个卷积层的参数量公式是参数量 输入通道数 × 输出通道数 × 卷积核高 × 卷积核宽 输出通道数偏置比如输入是3通道输出是64通道卷积核是3×3那参数量就是3 * 64 * 3 * 3 64 1792。这类题只要把公式记牢固基本就是送分题。4.2 激活函数、BN与损失函数的坑笔试题里会问“ReLU为什么能缓解梯度消失”“Sigmoid和Tanh的缺点是什么”。ReLU在正区间梯度恒为1解决了深层网络梯度连乘导致的梯度消失问题但负数区间梯度为0可能导致神经元死亡。所以后来有LeakyReLU、PReLU这些变体。BN层是简答题常客。BN把每个batch的特征归一化为均值0、方差1再通过可学习的缩放和平移参数恢复表达能力。它解决了内部协变量偏移问题让网络训练更稳定还可以允许使用更大的学习率。实际使用中要注意推理阶段用的是滑动平均统计量而不是测试时的batch统计量否则batch size1时会出大问题。损失函数方面人脸识别和OCR场景喜欢用ArcFace、Focal Loss这类进阶损失。笔试里如果考Focal Loss核心考点是它如何解决正负样本不平衡通过调制因子(1-p_t)^γ降低易分类样本的权重把训练重心放在难样本上。γ通常取2。4.3 模型压缩与端侧部署金山办公的产品场景集中在手机端模型压缩是必须懂的部分。笔试简答题可能会问“模型剪枝和量化的区别”。剪枝是把不重要的权重或通道置零或删除减少计算量量化则是把FP32的权重变成INT8或更低精度用更少的bit表示参数。实际经验是在OCR和文档识别场景里把模型从FP32量化到INT8准确率下降通常在1%以内但推理速度能提升2到3倍显存占用也大幅减少。量化训练和训练后量化是两种常见方式训练后量化简单但容易掉点量化感知训练效果更好但需要额外的训练时间。还有一个容易被忽视的知识蒸馏题。用一个大模型当老师教一个小模型学生让学生的软化输出逼近老师的输出。在移动端做文档分类或图像矫正方向时知识蒸馏是我经常用的方案因为它能在几乎不损失精度的情况下大幅缩小模型体积。5. 综合设计题一张歪斜的身份证照片如何救回来这套笔试题最让人津津乐道的是最后那道综合设计题大致场景是手机随意拍了一张身份证照片背景杂乱、存在透视变形、光照不均、还有反光要求你设计一套完整方案输出一张清晰规整、可用于OCR识别的身份证扫描效果图。这种题没有标准答案拼的就是你的项目积累。5.1 需求拆解与方案选型拿到这个题不能直接说“用深度学习”。要先做需求拆解输入是一张随意拍摄的照片输出是规整的身份证正反面图像。这中间要解决的问题有四个找目标、调角度、清干扰、提文字。方案选型上可以走传统CV流程也可以走深度学习方法但通常要组合使用。我的思路是目标检测阶段先在整图中检测身份证区域。轻量场景下用SSD或YOLO如果环境可控也可以用基于轮廓的传统方法。图像矫正阶段检测身份证的四个角点用透视变换把倾斜区域矫正为矩形。图像增强阶段做去阴影、去反光、对比度增强、锐化。文字识别阶段用OCR模型识别身份证号码和姓名最后做结构化输出。5.2 关键步骤的完整链路目标检测阶段如果场景背景复杂纯靠边缘检测很容易失败。用目标检测网络先框出一个大致区域比传统方法更稳。但笔试里如果你只说“用YOLO”就太单薄了更完整的回答是第一帧很难用网络直接定位身份证因为身份证可能是倾斜的、部分被遮挡的可以先做图像金字塔多尺度检测或者用旋转目标检测的思路把带角度的候选框也输出出来。拿到候选框后关键一步是角点定位。实际中最稳的方式是先用边缘检测和霍夫直线检测找到四条边再求交点得到四个角点。但也有个坑身份证圆角会让直线检测不够准。实操技巧是先把图像二值化再用cv2.findContours找最大轮廓然后用cv2.approxPolyDP逼近四边形。如果轮廓不够准确可以结合传统特征点匹配比如SURF或ORB匹配模板身份证的四个角点位置。透视变换的公式核心是计算单应性矩阵用cv2.getPerspectiveTransform(src, dst)得到变换矩阵再用cv2.warpPerspective输出矫正后的图像。注意目标矩形的宽高比要按身份证的真实比例设置一般是85.6mm × 54mm不是随便设置的否则识别结果会比例失调。图像增强阶段我一般先用灰度化、高斯滤波去掉传感器噪声再做对比度受限的自适应直方图均衡化CLAHE对局部光照不均匀的情况特别有效。反光区域可以用阈值分割找亮点然后对反光区域做区域填充或图像修复。最后是OCR识别。这一块金山办公用的是自研OCR系统所以笔试时你最好提到如何用检测模型定位文本行、如何用识别模型做字符识别以及如何处理姓名、住址这种长文本的版面结构。还可以提一句身份证号码这一块因为格式固定用正则加校验位校验做后处理能显著提高准确率。5.3 边界情况与部署细节综合设计题里如果只写正常流程充其量算及格。想拿高分必须提到边界情况。比如摄像头离得太近身份证超出画面程序要给出提示。拍摄角度过大透视矫正后图像边缘信息缺失要判断矫正后的四个角点是否都在有效范围内。阴天或背光环境下身份证颜色偏暗需要先做亮度均衡化。身份证反光导致某个区域完全过曝简单直方图均衡化救不回来要考虑多帧融合让用户稍微移动手机后自动取多张图合成。部署方面还要提一下性能。手机上跑OCR全流程耗时不能太高一般会拆成轻量化模型和重模型两级轻量模型负责目标检测和粗筛关键帧再进入更重的超分或文本识别模型。这种级联设计是金山办公这类真实产品场景里很常见的思路。6. 考完复盘我的作答顺序与踩坑清单笔试结束后我复盘了很久也发现了一些可以提前避开的坑。这里把我个人总结的作答顺序和细节检查要点写出来希望你能少走弯路。6.1 时间分配与作答策略整套题时间紧张合理的顺序非常关键。我当时先把选择题和简单概念题快速扫完控制在30分钟内因为这类题会就是会不会纠结也没用。编程题留了40分钟先把最有把握的那道写完整再去啃另一道。综合设计题大概需要25到30分钟因为它要写的内容多但不需要太多调试只要逻辑清晰就能拿分。简答题最好放在编程题之前写因为编程题容易卡壳一旦陷进去后面简答题就没时间了。我当时是先写简答题再写编程题避免因为思维切换产生焦虑。6.2 代码书写和细节检查编程题最容易丢分的地方不是算法不对而是边界条件没考虑。比如输入字符串可能为空、数组长度可能为0、可能出现负数。这些极端情况平时刷LeetCode可能不会太在意但笔试的测试用例一般都会包含你不处理就会直接影响通过率。还有一个细节是输入输出格式。笔试环境里有些题要求你处理多组测试用例有些题的输入样例里可能有空格和换行的干扰。如果你用的是PyCharm和LeetCode的思路来做在线笔试特别容易忽略模板代码默认给的if __name__ __main__部分。提前熟悉目标公司的笔试环境能省下不少时间。另外代码写完后一定要回头检查一遍变量命名和函数返回值。卷面整洁、逻辑清晰也很重要因为有些公司的笔试会让人工再看一遍关键题的思路代码太乱容易吃亏。6.3 给下一届学弟学妹的备战建议如果你准备投金山办公或类似做文档类产品的视觉算法岗我的建议是把精力放在这几件事上把OpenCV常用的图像处理函数亲手实现一遍而不是只调用API。把经典CNN模型结构梳理成一张知识图包括VGG、ResNet、MobileNet以及它们各自的瓶颈和适用场景。亲手从0训练一个小型OCR模型跑通“检测-矫正-识别-后处理”全流程哪怕只在简单的印刷体数据集上做也能让你对整套系统有体感。多看WPS、扫描全能王这类App的体验反馈想想用户的痛点到底是什么因为笔试里的综合设计题多半来自现实场景。我个人的真实体会是这套笔试题并不难难的是“时间有限心态紧张基础不牢”这三件事叠加在一起。如果能把高频考点复习到位按自己熟悉的节奏安排作答顺序通过笔试的机会非常大。计算机视觉算法工程师这个岗位本质上是“用算法解决真实产品问题”笔试只是第一道门槛真正决定你是否胜任的还是你是否真的理解图像从输入到输出的每一条路径。