可视化建站网站源码,做IT的需要别人打开网站吗,下载应用市场,wordpress媒体库难用文章目录 0.引言1. 原始代码分析1.1 存在的问题 2. 优化方案3. 优化后的代码4. 代码详细解读4.1. 输入检查4.2. 图像预处理4.3. 高斯模糊4.4. 梯度计算4.5. 计算梯度幅值和方向4.6. 边缘检测4.7. 计算边缘密度4.8. 估计遮挡程度4.9. 限定结果范围4.10. 返回结果 0.引言
视频质… 文章目录 0.引言1. 原始代码分析1.1 存在的问题 2. 优化方案3. 优化后的代码4. 代码详细解读4.1. 输入检查4.2. 图像预处理4.3. 高斯模糊4.4. 梯度计算4.5. 计算梯度幅值和方向4.6. 边缘检测4.7. 计算边缘密度4.8. 估计遮挡程度4.9. 限定结果范围4.10. 返回结果 0.引言
视频质量遮挡检测已在C基于opencv4的视频质量检测中有所介绍本文将详细介绍其优化版本。
1. 原始代码分析
首先我们来看遮挡检测的原始代码
#include opencv2/opencv.hpp
#include vector/*** brief 检测图像中的遮挡情况。* param [in] srcImg 输入的图像* return 返回一个double类型的数值范围为0到1。数值越接近1表示图像中的遮挡程度越高。*/
double blockDetect(const cv::Mat srcImg) {if (srcImg.empty()) {return -1.0; // 如果输入图像为空返回-1表示错误}cv::Mat grayImg, edges;cv::cvtColor(srcImg, grayImg, cv::COLOR_BGR2GRAY);cv::GaussianBlur(grayImg, grayImg, cv::Size(3, 3), 0);cv::Canny(grayImg, edges, 0, 0);std::vectorstd::vectorcv::Point contours;std::vectorcv::Vec4i hierarchy;// 初始轮廓检测cv::findContours(edges, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);int initialContourCount static_castint(hierarchy.size());// 细化后的轮廓检测cv::Canny(grayImg, edges, 0, 15);cv::findContours(edges, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);int refinedContourCount static_castint(hierarchy.size());// 防止除以零的情况if (initialContourCount 0) {initialContourCount 1;}double occlusionLevel 1.0 - static_castdouble(refinedContourCount) / static_castdouble(initialContourCount);return occlusionLevel;
}1.1 存在的问题 Canny边缘检测的阈值设置不合理在Canny函数中阈值设为0和0以及0和15这可能导致边缘检测结果不可靠。 错误处理不够明确当输入图像为空时返回-1.0但这个值可能与正常的遮挡程度值混淆。
2. 优化方案
针对上述问题我们对代码进行如下优化 自适应阈值设置根据图像的特性动态设置Canny边缘检测的阈值提高边缘检测的可靠性。 提高代码可读性增加详细的注释使用更具描述性的变量名提升代码的可读性和可维护性。 算法改进使用Sobel算子计算梯度基于边缘密度来判断遮挡程度获得更准确的结果。
3. 优化后的代码
#include opencv2/opencv.hpp
#include vector/*** brief 检测图像中的遮挡情况。* param srcImg 输入的图像* return 如果成功返回一个介于0到1之间的double类型值值越接近1表示遮挡程度越高* 如果输入图像为空返回-1.0。*/
double occlusionDetect(const cv::Mat srcImg) {if (srcImg.empty()) {// 输入图像为空return -1.0;}// 将图像转换为灰度图cv::Mat grayImg;if (srcImg.channels() 3) {cv::cvtColor(srcImg, grayImg, cv::COLOR_BGR2GRAY);} else {grayImg srcImg.clone();}// 对灰度图进行高斯模糊减少噪声cv::GaussianBlur(grayImg, grayImg, cv::Size(5, 5), 0);// 使用Sobel算子计算梯度cv::Mat gradX, gradY;cv::Sobel(grayImg, gradX, CV_64F, 1, 0, 3);cv::Sobel(grayImg, gradY, CV_64F, 0, 1, 3);// 计算梯度幅值和方向cv::Mat magnitude, angle;cv::cartToPolar(gradX, gradY, magnitude, angle, true);// 对梯度幅值进行阈值化得到边缘图double maxVal;cv::minMaxLoc(magnitude, nullptr, maxVal);cv::Mat edges;cv::threshold(magnitude, edges, 0.1 * maxVal, 255, cv::THRESH_BINARY);// 计算边缘密度double edgeDensity cv::countNonZero(edges) / static_castdouble(edges.total());// 根据边缘密度估计遮挡程度假设遮挡区域边缘密度较低double occlusionLevel 1.0 - edgeDensity;// 将结果限定在0到1之间occlusionLevel std::clamp(occlusionLevel, 0.0, 1.0);return occlusionLevel;
}4. 代码详细解读 #mermaid-svg-2XzF6DP9cee2N3AD {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-2XzF6DP9cee2N3AD .error-icon{fill:#552222;}#mermaid-svg-2XzF6DP9cee2N3AD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2XzF6DP9cee2N3AD .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-2XzF6DP9cee2N3AD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2XzF6DP9cee2N3AD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2XzF6DP9cee2N3AD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2XzF6DP9cee2N3AD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2XzF6DP9cee2N3AD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2XzF6DP9cee2N3AD .marker.cross{stroke:#333333;}#mermaid-svg-2XzF6DP9cee2N3AD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2XzF6DP9cee2N3AD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2XzF6DP9cee2N3AD .cluster-label text{fill:#333;}#mermaid-svg-2XzF6DP9cee2N3AD .cluster-label span{color:#333;}#mermaid-svg-2XzF6DP9cee2N3AD .label text,#mermaid-svg-2XzF6DP9cee2N3AD span{fill:#333;color:#333;}#mermaid-svg-2XzF6DP9cee2N3AD .node rect,#mermaid-svg-2XzF6DP9cee2N3AD .node circle,#mermaid-svg-2XzF6DP9cee2N3AD .node ellipse,#mermaid-svg-2XzF6DP9cee2N3AD .node polygon,#mermaid-svg-2XzF6DP9cee2N3AD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2XzF6DP9cee2N3AD .node .label{text-align:center;}#mermaid-svg-2XzF6DP9cee2N3AD .node.clickable{cursor:pointer;}#mermaid-svg-2XzF6DP9cee2N3AD .arrowheadPath{fill:#333333;}#mermaid-svg-2XzF6DP9cee2N3AD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2XzF6DP9cee2N3AD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2XzF6DP9cee2N3AD .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-2XzF6DP9cee2N3AD .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-2XzF6DP9cee2N3AD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2XzF6DP9cee2N3AD .cluster text{fill:#333;}#mermaid-svg-2XzF6DP9cee2N3AD .cluster span{color:#333;}#mermaid-svg-2XzF6DP9cee2N3AD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2XzF6DP9cee2N3AD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是 否 开始 输入图像是否为空 返回 std::nullopt 转换为灰度图 grayImg 高斯模糊处理 计算梯度 gradX 和 gradY 计算梯度幅值和方向 获取最大值 maxVal 阈值化得到 edges 计算边缘密度 edgeDensity 计算遮挡程度 occlusionLevel 限定 occlusionLevel 在0到1之间 返回 occlusionLevel 4.1. 输入检查
if (srcImg.empty()) {return std::nullopt;
}目的确保输入的图像有效。说明如果输入图像为空函数返回std::nullopt明确表示错误状态。
4.2. 图像预处理
cv::Mat grayImg;
if (srcImg.channels() 3) {cv::cvtColor(srcImg, grayImg, cv::COLOR_BGR2GRAY);
} else {grayImg srcImg.clone();
}目的将彩色图像转换为灰度图像。说明灰度图像降低了计算复杂度适用于后续的梯度和边缘检测。
4.3. 高斯模糊
cv::GaussianBlur(grayImg, grayImg, cv::Size(5, 5), 0);目的平滑图像减少噪声对梯度计算的影响。参数解释 cv::Size(5, 5)高斯核的大小可根据需要调整。0高斯核在x方向的标准差设为0表示根据核大小自动计算。
4.4. 梯度计算
cv::Mat gradX, gradY;
cv::Sobel(grayImg, gradX, CV_64F, 1, 0, 3);
cv::Sobel(grayImg, gradY, CV_64F, 0, 1, 3);目的计算图像在x和y方向的梯度。参数解释 CV_64F使用64位浮点型确保梯度值的精度。1, 0 和 0, 1指定导数的阶数分别计算x和y方向的一阶导数。3Sobel核的大小。
4.5. 计算梯度幅值和方向
cv::Mat magnitude, angle;
cv::cartToPolar(gradX, gradY, magnitude, angle, true);目的将梯度的x和y分量转换为极坐标形式得到梯度的幅值和方向。参数解释 true将角度值转换为度数0-360否则为弧度。
4.6. 边缘检测
double maxVal;
cv::minMaxLoc(magnitude, nullptr, maxVal);
cv::Mat edges;
cv::threshold(magnitude, edges, 0.1 * maxVal, 255, cv::THRESH_BINARY);目的通过阈值化梯度幅值提取边缘。步骤 使用cv::minMaxLoc获取梯度幅值的最大值maxVal。设定阈值为0.1 * maxVal将高于此阈值的像素设为255白色其余设为0黑色。
4.7. 计算边缘密度
double edgeDensity cv::countNonZero(edges) / static_castdouble(edges.total());目的计算边缘像素占总像素的比例。说明边缘密度反映了图像中边缘信息的丰富程度。
4.8. 估计遮挡程度
double occlusionLevel 1.0 - edgeDensity;目的根据边缘密度估计遮挡程度。假设遮挡区域的边缘密度较低因此边缘密度越小遮挡程度越高。
4.9. 限定结果范围
occlusionLevel std::clamp(occlusionLevel, 0.0, 1.0);目的确保遮挡程度在有效范围内。
4.10. 返回结果
return occlusionLevel;说明返回的occlusionLevel为double类型范围在0到1之间。无遮挡图像occlusionLevel值接近于0表示遮挡程度低。遮挡图像occlusionLevel值接近于1表示遮挡程度高。