OpenCV面试题
opencv面试复习1 OpenCV 中cv::Mat的深拷贝和浅拷贝问题cv::Mat默认赋值和拷贝构造是浅拷贝只复制矩阵头信息底层像素数据共享OpenCV 通过引用计数管理内存。这样可以减少大图像复制带来的性能开销。如果需要真正复制图像数据需要使用clone()或copyTo()实现深拷贝。2 OpenCV 中 RGB2GRAY 是怎么实现的RGB 转灰度本质是把三通道彩色图像转换为单通道亮度图像。不是简单求平均而是按照人眼对不同颜色的敏感程度进行加权求和。常用公式是Gray 0.299R 0.587G 0.114B。在 OpenCV 中由于默认通道顺序是 BGR所以通常使用cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY)完成转换。3 连续图像转化为数字图像需要进行哪些操作连续图像转换为数字图像主要包括采样和量化两个过程。采样是把连续空间坐标离散成有限个像素点决定图像的空间分辨率量化是把连续的灰度值或颜色值离散成有限等级比如 8 位图像中像素值范围是 0 到 255。之后再按照一定图像格式进行编码和存储比如 JPG、PNG 或 BMP。4 数字图像中有哪些基本特征数字图像的基本特征包括颜色特征、灰度特征、边缘特征、纹理特征、形状特征和局部特征。颜色特征描述图像的颜色分布灰度特征描述亮度变化边缘特征反映物体边界纹理特征反映局部重复结构形状特征描述目标几何轮廓局部特征如 SIFT、ORB 可用于图像匹配和目标识别。5 图像边缘检测中常用的边缘检测算子有哪些边缘检测本质上是在找灰度变化剧烈的位置而噪声点也会造成灰度突变。如果不先滤波噪声也可能被误检测为边缘。使用高斯滤波可以平滑图像减少噪声干扰让边缘检测结果更稳定。尤其是 Laplacian 和Canny一般都会先进行高斯滤波。常用边缘检测算子主要有 Roberts、Prewitt、Sobel、Scharr、Laplacian、LoG 和 Canny。Roberts 和 Prewitt 属于比较基础的一阶梯度算子计算简单但抗噪能力一般。Sobel 是比较常用的一阶梯度算子通过 x 和 y 方向模板计算灰度梯度能检测水平和垂直边缘并且具有一定平滑效果。Scharr 可以看作 Sobel 的改进在 3×3 卷积核下梯度精度更高。Laplacian 是二阶导数算子可以检测各个方向的边缘但对噪声敏感所以通常会先进行高斯滤波。LoG 就是先高斯滤波再做 Laplacian用来提高抗噪能力。6 canny边缘检测的流程Canny 边缘检测一般包括五个步骤。首先将图像转为灰度图然后通过高斯滤波去除噪声。接着计算图像的梯度幅值和梯度方向用来判断灰度变化剧烈的位置。然后进行非极大值抑制只保留梯度方向上的局部最大值使边缘变细。最后使用双阈值检测区分强边缘、弱边缘和非边缘并通过边缘连接保留与强边缘相连的弱边缘得到最终边缘图。所以 Canny 得到的边缘通常更细、更连续抗噪能力也更好但计算过程比 Sobel 更复杂参数选择也更重要。灰度图 → 高斯滤波 → 计算梯度 → 非极大值抑制 → 双阈值检测与边缘连接#includeopencv2/opencv.hpp#includeiostreamintmain(){// 1. 读取原始图像// imread 默认以 BGR 三通道格式读取图片cv::Mat srccv::imread(road.jpg);// 判断图片是否读取成功if(src.empty()){std::cout读取图片失败std::endl;return-1;}// gray灰度图// edgesCanny 边缘检测结果图cv::Mat gray;cv::Mat edges;// 2. 将彩色图像转换为灰度图// 霍夫直线检测通常基于边缘图而边缘检测一般先在灰度图上进行cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);// 3. 高斯滤波降低噪声// 噪声可能会被 Canny 误检测为边缘所以先进行平滑处理// Size(5, 5)高斯核大小// 1.5标准差控制模糊程度cv::GaussianBlur(gray,gray,cv::Size(5,5),1.5);// 4. Canny 边缘检测// 50低阈值// 150高阈值// Canny 内部会完成梯度计算、非极大值抑制、双阈值检测和边缘连接cv::Canny(gray,edges,50,150);// 5. 用于保存检测到的直线// Vec4i 中保存一条线段的两个端点// line[0], line[1] 表示起点坐标 x1, y1// line[2], line[3] 表示终点坐标 x2, y2std::vectorcv::Vec4ilines;// 6. 概率霍夫直线检测// 输入必须是边缘图一般使用 Canny 的输出结果cv::HoughLinesP(edges,// 输入边缘图lines,// 输出检测到的线段1,// rho 分辨率单位为像素CV_PI/180,// theta 分辨率单位为弧度这里表示 1 度80,// 投票阈值越大检测出的直线越少50,// 最小线段长度小于该长度的线段会被过滤10// 最大线段间隔小于该间隔的线段会被合并);// 7. 遍历检测到的所有直线并画到原图上for(constautoline:lines){cv::line(src,// 要绘制的目标图像cv::Point(line[0],line[1]),// 线段起点cv::Point(line[2],line[3]),// 线段终点cv::Scalar(0,0,255),// 线条颜色BGR 格式这里是红色2// 线条宽度);}// 8. 显示 Canny 边缘检测结果cv::imshow(edges,edges);// 9. 显示绘制霍夫直线后的结果图cv::imshow(lines,src);// 10. 等待按键否则窗口会一闪而过cv::waitKey(0);return0;}7 OpenCV 中图像加法 cv::add() 与图像融合 cv::addWeighted() 有何区别cv::add() 是图像加法直接对两张图对应位置的像素进行相加结果超过 255 会进行饱和截断所以容易出现过曝。cv::addWeighted() 是加权融合计算公式是 dst src1 * alpha src2 * beta gamma可以通过 alpha 和 beta 控制两张图的融合比例常用于透明叠加、水印、图像融合和检测结果可视化。二者都要求输入图像的尺寸、通道数和数据类型一致。如果不一致需要先进行 resize() 或颜色空间转换。