update 优化传统分类耗时

dev_lsy
liusiyang 2 weeks ago
parent a979c07179
commit 0e72b46f87

@ -115,6 +115,7 @@ private:
cv::Mat m_matBlur; cv::Mat m_matBlur;
cv::Mat m_matDraw; cv::Mat m_matDraw;
cv::Rect m_rtCrop; // TraditionalDetect 中确定的裁剪区域(原图坐标),供分类结果坐标映射
cv::Size m_sizeImage; cv::Size m_sizeImage;
std::string m_strCurFile; std::string m_strCurFile;

@ -223,10 +223,21 @@ void CTcsCheck::ClassifyBlobs(const cv::Mat& blurCrop, const cv::Mat& imgBlob)
{ {
m_vecDefectInfo.clear(); m_vecDefectInfo.clear();
// 分步计时记录每个步骤的耗时ms
auto tStart = std::chrono::high_resolution_clock::now();
auto tPrev = tStart;
auto logStep = [&](const std::string& step) {
auto tNow = std::chrono::high_resolution_clock::now();
double elapsedMs = std::chrono::duration_cast<std::chrono::milliseconds>(tNow - tPrev).count();
std::cout << "[ClassifyBlobs] " << step << " 耗时(ms): " << elapsedMs << std::endl;
tPrev = tNow;
};
cv::Mat labels; cv::Mat labels;
cv::Mat stats; cv::Mat stats;
cv::Mat centroids; cv::Mat centroids;
const int nLabels = cv::connectedComponentsWithStats(imgBlob, labels, stats, centroids, 8, CV_32S); const int nLabels = cv::connectedComponentsWithStats(imgBlob, labels, stats, centroids, 8, CV_32S);
// logStep("1.连通域分析");
if (nLabels <= 1) return; if (nLabels <= 1) return;
struct BlobItem { int label; int area; }; struct BlobItem { int label; int area; };
@ -238,11 +249,13 @@ void CTcsCheck::ClassifyBlobs(const cv::Mat& blurCrop, const cv::Mat& imgBlob)
blobs.push_back({ label, area }); blobs.push_back({ label, area });
} }
} }
// logStep("2.面积过滤");
if (blobs.empty()) return; if (blobs.empty()) return;
std::sort(blobs.begin(), blobs.end(), [](const BlobItem& a, const BlobItem& b) { std::sort(blobs.begin(), blobs.end(), [](const BlobItem& a, const BlobItem& b) {
return a.area > b.area; return a.area > b.area;
}); });
// logStep("3.面积排序");
// 大块缺陷的面积阈值 // 大块缺陷的面积阈值
const int largeAreaThreshold = std::max(1, m_cpCfg.nBlockSize * m_cpCfg.nBlockSize / 4); const int largeAreaThreshold = std::max(1, m_cpCfg.nBlockSize * m_cpCfg.nBlockSize / 4);
@ -307,6 +320,14 @@ void CTcsCheck::ClassifyBlobs(const cv::Mat& blurCrop, const cv::Mat& imgBlob)
info.strDefectDesc = DEFECT_TYPE_DESC[defectType]; info.strDefectDesc = DEFECT_TYPE_DESC[defectType];
m_vecDefectInfo.push_back(info); m_vecDefectInfo.push_back(info);
} }
// logStep("4.缺陷分类决策");
// // 总耗时
// {
// auto tEnd = std::chrono::high_resolution_clock::now();
// double totalMs = std::chrono::duration_cast<std::chrono::milliseconds>(tEnd - tStart).count();
// std::cout << "[ClassifyBlobs] 总耗时(ms): " << totalMs << std::endl;
// }
} }
// ============================================================ // ============================================================
@ -421,6 +442,8 @@ int CTcsCheck::TraditionalDetect(const cv::Mat& img, cv::Rect detRoi, cv::Mat& b
return -1; return -1;
} }
} }
// 缓存裁剪区域,供 TraditionalClassify 将小图坐标映射回原图
m_rtCrop = rtCrop;
// logStep("4.安全裁剪"); // logStep("4.安全裁剪");
cv::Mat matCrop = m_matLoad(rtCrop); cv::Mat matCrop = m_matLoad(rtCrop);
@ -468,17 +491,41 @@ int CTcsCheck::TraditionalDetect(const cv::Mat& img, cv::Rect detRoi, cv::Mat& b
// ============================================================ // ============================================================
// TraditionalClassify — 独立分类接口 // TraditionalClassify — 独立分类接口
// 对残点二值图做连通域分析+缺陷分类决策树 // 优先在小图缓存m_matBlur/m_matBlob上做连通域分析+缺陷分类,
// 前提: 已调用 TraditionalDetectblobImg 已与 m_matLoad 同尺寸) // 再将结果坐标映射回原图,避免对全尺寸 mask 做昂贵计算。
// 使用没有任何处理的原图 m_matLoad 计算灰阶差
// 返回: 分类到的缺陷数量,<0 表示异常 // 返回: 分类到的缺陷数量,<0 表示异常
// ============================================================ // ============================================================
int CTcsCheck::TraditionalClassify(const cv::Mat& blobImg) int CTcsCheck::TraditionalClassify(const cv::Mat& blobImg)
{ {
// 全尺寸 mask 仅是小图 INTER_NEAREST 放大结果,连通域数量/形状完全等价,
// 在小图上分类可避免对全尺寸图做昂贵的 connectedComponentsWithStats。
if (m_matBlur.empty() || m_matBlob.empty())
{
// 回退:无小图缓存时,退化为全尺寸分类(旧行为)
if (m_matLoad.empty() || blobImg.empty()) return -1; if (m_matLoad.empty() || blobImg.empty()) return -1;
// 不再为全尺寸 mask 做一次 clone直接使用 blobImg 分类
ClassifyBlobs(m_matLoad, blobImg); ClassifyBlobs(m_matLoad, blobImg);
return static_cast<int>(m_vecDefectInfo.size());
}
auto tStart = std::chrono::high_resolution_clock::now();
ClassifyBlobs(m_matBlur, m_matBlob);
// 小图坐标/面积映射回原图坐标系,与下游 blobs.blobTab全尺寸坐标对齐
const double scaleX = (m_matBlob.cols > 0) ? static_cast<double>(m_rtCrop.width) / m_matBlob.cols : 1.0;
const double scaleY = (m_matBlob.rows > 0) ? static_cast<double>(m_rtCrop.height) / m_matBlob.rows : 1.0;
for (auto& info : m_vecDefectInfo)
{
info.nDefectX = static_cast<int>(info.nDefectX * scaleX + 0.5) + m_rtCrop.x;
info.nDefectY = static_cast<int>(info.nDefectY * scaleY + 0.5) + m_rtCrop.y;
info.nDefectWidth = std::max(1, static_cast<int>(info.nDefectWidth * scaleX + 0.5));
info.nDefectHeight = std::max(1, static_cast<int>(info.nDefectHeight * scaleY + 0.5));
info.nDefectArea = std::max(1, static_cast<int>(info.nDefectArea * scaleX * scaleY + 0.5));
}
auto tEnd = std::chrono::high_resolution_clock::now();
double totalMs = std::chrono::duration_cast<std::chrono::milliseconds>(tEnd - tStart).count();
std::cout << "[TraditionalClassify] 总耗时(ms): " << totalMs << std::endl;
return static_cast<int>(m_vecDefectInfo.size()); return static_cast<int>(m_vecDefectInfo.size());
} }

Loading…
Cancel
Save