|
|
|
|
@ -480,6 +480,63 @@ int ImgCheckAnalysisy::Adapt_Config(RotatedRect tplOuterRect, RotatedRect curOut
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 应用内 OpenCV 线程池随首个调用线程(通常为先绑核的检测线程)初始化成单线程,parallel_for 实际串行,
|
|
|
|
|
// 全分辨率 warp 要 150~200ms;这里把输出按行切条、用独立线程并行 warp,
|
|
|
|
|
// 结果与整图 warpAffine 逐像素一致(已离线验证 maxdiff=0),耗时降到约 1/3
|
|
|
|
|
static void WarpAffineBandParallel(const cv::Mat &src, cv::Mat &dst, const cv::Mat &affine,
|
|
|
|
|
const cv::Size &size, int nThreads = 8, int interp = cv::INTER_LINEAR,
|
|
|
|
|
int borderType = cv::BORDER_REPLICATE)
|
|
|
|
|
{
|
|
|
|
|
dst.create(size, src.type());
|
|
|
|
|
nThreads = std::max(1, std::min(nThreads, size.height));
|
|
|
|
|
int bandH = (size.height + nThreads - 1) / nThreads;
|
|
|
|
|
int nBands = (size.height + bandH - 1) / bandH;
|
|
|
|
|
|
|
|
|
|
auto warpBand = [&](int b)
|
|
|
|
|
{
|
|
|
|
|
// 新建线程默认继承调用线程的 CPU 亲和性(检测线程已绑单核),这里放开到全核,让条带真正并行
|
|
|
|
|
cpu_set_t cpus;
|
|
|
|
|
CPU_ZERO(&cpus);
|
|
|
|
|
long ncpu = sysconf(_SC_NPROCESSORS_ONLN);
|
|
|
|
|
for (long i = 0; i < ncpu; i++)
|
|
|
|
|
{
|
|
|
|
|
CPU_SET(i, &cpus);
|
|
|
|
|
}
|
|
|
|
|
pthread_setaffinity_np(pthread_self(), sizeof(cpus), &cpus);
|
|
|
|
|
|
|
|
|
|
int y0 = b * bandH;
|
|
|
|
|
int h = std::min(bandH, size.height - y0);
|
|
|
|
|
// warpAffine 默认接收正向矩阵(src->dst)并内部求逆;条带只把输出平移项减去 y0
|
|
|
|
|
cv::Mat matBand = affine.clone();
|
|
|
|
|
matBand.at<double>(1, 2) -= y0;
|
|
|
|
|
cv::warpAffine(src, dst(cv::Rect(0, y0, size.width, h)), matBand,
|
|
|
|
|
cv::Size(size.width, h), interp, borderType);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::vector<std::thread> threads;
|
|
|
|
|
threads.reserve(nBands);
|
|
|
|
|
int b = 0;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
for (; b < nBands; b++)
|
|
|
|
|
{
|
|
|
|
|
threads.emplace_back(warpBand, b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (const std::system_error &)
|
|
|
|
|
{
|
|
|
|
|
// 线程资源不足:剩余条带留在本线程串行补完
|
|
|
|
|
}
|
|
|
|
|
for (auto &t : threads)
|
|
|
|
|
{
|
|
|
|
|
t.join();
|
|
|
|
|
}
|
|
|
|
|
for (; b < nBands; b++)
|
|
|
|
|
{
|
|
|
|
|
warpBand(b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ImgCheckAnalysisy::CheckRun()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
@ -596,7 +653,18 @@ int ImgCheckAnalysisy::CheckRun()
|
|
|
|
|
{
|
|
|
|
|
cv::cvtColor(colorPatch, grayPatch, cv::COLOR_BGRA2GRAY);
|
|
|
|
|
}
|
|
|
|
|
cv::warpAffine(grayPatch, m_pImageAllResult->detImg, matPad, cv::Size(detW, detH), cv::INTER_LINEAR, cv::BORDER_REPLICATE);
|
|
|
|
|
WarpAffineBandParallel(grayPatch, m_pImageAllResult->detImg, matPad, cv::Size(detW, detH));
|
|
|
|
|
|
|
|
|
|
// 彩色原图时再输出一张同样摆正的彩色检测图:供裁剪图(_RE_CutImg)保存时保留原图通道
|
|
|
|
|
// (检测算法仍只用灰度 detImg)
|
|
|
|
|
if (colorPatch.channels() == 3 || colorPatch.channels() == 4)
|
|
|
|
|
{
|
|
|
|
|
WarpAffineBandParallel(colorPatch, m_pImageAllResult->detColorImg, matPad, cv::Size(detW, detH));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_pImageAllResult->detColorImg.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4、检测图坐标系下 m_outer_roi 即整张检测图;原图坐标系下 CutRoi 仍取旋转矩形外接区域(兼容旧语义/JSON)
|
|
|
|
|
m_outer_roi = cv::Rect(0, 0, detW, detH);
|
|
|
|
|
@ -2567,7 +2635,10 @@ int ImgCheckAnalysisy::ImgPreDet()
|
|
|
|
|
creatsavedir();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_CheckResult_shareP->cutSrcimg = m_pImageAllResult->detImg;
|
|
|
|
|
// 裁剪图(_RE_CutImg)保留原图通道:源图为彩色时用彩色摆正图,否则回退灰度检测图
|
|
|
|
|
m_CheckResult_shareP->cutSrcimg = m_pImageAllResult->detColorImg.empty()
|
|
|
|
|
? m_pImageAllResult->detImg
|
|
|
|
|
: m_pImageAllResult->detColorImg;
|
|
|
|
|
ResizeImg();
|
|
|
|
|
|
|
|
|
|
m_pImageAllResult->fscale_detToresult_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols;
|
|
|
|
|
|