计算机视觉算法工程师面试核心考点精讲
1. 传统图像处理核心考点
传统图像处理是计算机视觉的基础,掌握这些算法能让你在面试中展现出扎实的功底。我当年面试时被问得最多的就是边缘检测,面试官特别喜欢让候选人对比不同算子的特点。
1.1 边缘检测算法精要
Canny算子绝对是面试中的高频考点,它的五步流程需要烂熟于心:
- 高斯滤波去噪(σ=1.4的5x5核)
- Sobel算子计算梯度(建议手写Sobel的x/y方向卷积核)
- 非极大值抑制(NMS)细化边缘
- 双阈值检测(典型高低阈值比3:1)
- 边缘连接(DFS或BFS实现)
# OpenCV实现示例 import cv2 img = cv2.imread('test.jpg', 0) edges = cv2.Canny(img, 50, 150) # 阈值设置很关键Sobel与Prewitt的区别在于卷积核权重:
- Sobel的x方向核:[[-1,0,1], [-2,0,2], [-1,0,1]]
- Prewitt更均匀:[[-1,0,1], [-1,0,1], [-1,0,1]]
Laplacian算子是二阶微分算子,对噪声敏感但能检测细边缘。有个经典面试题:为什么LoG(Laplacian of Gaussian)要先高斯模糊?答案是为了抑制噪声干扰。
1.2 图像滤波实战技巧
中值滤波去除椒盐噪声效果最好,但要注意:
- 窗口大小取奇数(3x3, 5x5)
- 时间复杂度O(n²k²),大图需要优化
// 手写中值滤波核心代码 uchar medianFilter(Mat src, int x, int y, int ksize) { vector<uchar> pixels; for(int i=-ksize/2; i<=ksize/2; ++i) for(int j=-ksize/2; j<=ksize/2; ++j) pixels.push_back(src.at<uchar>(y+i,x+j)); sort(pixels.begin(), pixels.end()); return pixels[pixels.size()/2]; }高斯滤波的σ值决定平滑程度,σ越大核越大。实际工程中常用可分性优化,将二维卷积拆分为两次一维卷积,计算量从O(k²)降到O(2k)。
1.3 形态学操作本质
膨胀和腐蚀是形态学基础,面试常考开闭运算:
- 开运算(先腐蚀后膨胀)去小噪点
- 闭运算(先膨胀后腐蚀)填小孔洞
结构元素选择有讲究:
- 矩形核适合直角边缘
- 圆形核各向同性
- 十字形核适合细长结构
2. 特征提取与描述子
2.1 SIFT算法详解
SIFT的四大步骤是必考题:
- 尺度空间构建(高斯金字塔+DoG)
- 关键点定位(泰勒展开修正位置)
- 方向分配(36bin梯度直方图)
- 描述子生成(4x4x8=128维向量)
面试陷阱:为什么SIFT具有尺度不变性?因为通过DoG极值检测找到了特征尺度。
2.2 ORB特征高效实现
ORB=FAST关键点+BRIEF描述子+方向补偿:
- FAST检测速度快但噪声敏感
- BRIEF用256bit二进制串,汉明距离计算快
- 用灰度质心法计算方向提升旋转鲁棒性
# ORB特征匹配示例 orb = cv2.ORB_create() kp1, des1 = orb.detectAndCompute(img1, None) bf = cv2.BFMatcher(cv2.NORM_HAMMING) matches = bf.match(des1, des2)2.3 HOG特征工程细节
HOG用于行人检测的经典实现:
- 图像归一化(Gamma+颜色归一化)
- 计算梯度([-1,0,1]核)
- 8x8细胞单元统计9bin直方图
- 16x16块归一化(L2-Hys)
- 串联所有块特征
注意:HOG对局部几何变化敏感,但对光照变化鲁棒。
3. 深度学习核心模型
3.1 CNN架构演进脉络
从LeNet到EfficientNet的进化路线:
- LeNet5(1998):首个成功CNN,2卷积+3全连接
- AlexNet(2012):ReLU+Dropout+数据增强
- VGG(2014):小卷积堆叠,感受野等效大卷积
- ResNet(2015):残差连接解决梯度消失
- MobileNet(2017):深度可分离卷积降参数量
面试高频题:为什么ResNet有效?残差学习让梯度直接回传,缓解了深度网络退化问题。
3.2 目标检测算法对比
Two-stage vs One-stage本质区别:
- Faster R-CNN:RPN生成候选框+ROI Pooling
- YOLOv3:网格预测bbox+置信度+类别
- SSD:多尺度特征图预测,平衡速度精度
# YOLOv3输出解析示例 def process_output(output, conf_thresh): boxes = output[..., :4] # xywh conf = output[..., 4:5] cls_probs = output[..., 5:] scores = conf * cls_probs keep = scores > conf_thresh return boxes[keep], scores[keep]3.3 语义分割关键技术
FCN开创端到端分割,关键改进:
- 全卷积替换全连接
- 反卷积上采样
- 跳跃连接融合深浅特征
U-Net的编码器-解码器结构:
- 下采样路径捕获上下文
- 上采样路径精确定位
- 跨层连接恢复空间信息
4. 模型优化与部署
4.1 过拟合解决方案
实际项目中我用过的组合拳:
- 数据增强(旋转/翻转/色彩抖动)
- L2正则化(λ=0.001)
- Dropout(p=0.5)
- Early Stopping(验证集loss不降即停)
- Label Smoothing(ε=0.1)
注意:BN层也有轻微正则化效果,但不要依赖它来防止过拟合。
4.2 模型量化实战
TensorRT量化步骤:
- 校准:用代表性数据统计激活分布
- 量化:FP32转INT8(饱和量化)
- 部署:加载量化后的引擎推理
// TensorRT构建器配置 builder->setMaxBatchSize(1); config->setFlag(BuilderFlag::kINT8); config->setInt8Calibrator(calibrator);4.3 部署优化技巧
我优化YOLOv5部署的经验:
- 使用NMS优化(Merge NMS)
- 半精度推理(FP16)
- 图优化(层融合、常量折叠)
- 内存池复用减少分配开销
在Jetson上实测,经过优化后推理速度从15FPS提升到45FPS,内存占用减少40%。
