update 裁剪图不改变通道

dev_lsy
liusiyang 4 weeks ago
parent 60fdbe7ebc
commit 97cd938656

@ -62,6 +62,8 @@ public:
cv::Rect CropRoi = cv::Rect(0, 0, 0, 0); cv::Rect CropRoi = cv::Rect(0, 0, 0, 0);
// 检测的原始图片 // 检测的原始图片
cv::Mat detImg; cv::Mat detImg;
// 摆正后的彩色检测图(保留原图通道,供裁剪图 _RE_CutImg 输出;灰度源图时为空)
cv::Mat detColorImg;
// AI 推理的mask图片 // AI 推理的mask图片
cv::Mat AIMaskImg; cv::Mat AIMaskImg;
// 结果图片 // 结果图片

@ -480,6 +480,63 @@ int ImgCheckAnalysisy::Adapt_Config(RotatedRect tplOuterRect, RotatedRect curOut
return 0; 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() int ImgCheckAnalysisy::CheckRun()
{ {
@ -596,7 +653,18 @@ int ImgCheckAnalysisy::CheckRun()
{ {
cv::cvtColor(colorPatch, grayPatch, cv::COLOR_BGRA2GRAY); 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) // 4、检测图坐标系下 m_outer_roi 即整张检测图;原图坐标系下 CutRoi 仍取旋转矩形外接区域(兼容旧语义/JSON)
m_outer_roi = cv::Rect(0, 0, detW, detH); m_outer_roi = cv::Rect(0, 0, detW, detH);
@ -2567,7 +2635,10 @@ int ImgCheckAnalysisy::ImgPreDet()
creatsavedir(); 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(); ResizeImg();
m_pImageAllResult->fscale_detToresult_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols; m_pImageAllResult->fscale_detToresult_x = m_pImageAllResult->resultImg.cols * 1.0f / m_pImageAllResult->detImg.cols;

@ -1016,16 +1016,13 @@ int deal::SendImgToCheck(std::shared_ptr<JC_IMAGE_INFO_> pDetImageInfo, IN_IMG_S
} }
if (status == IN_IMG_Status_End) if (status == IN_IMG_Status_End)
{ {
// 一张图上下拆分成两个产品(_0 上半、_1 下半),给两个产品分别发送结束标志 // 不再上下拆图:一张图对应一个产品,只给该产品发送一次结束标志
for (int pi = 0; pi < 2; pi++) std::shared_ptr<shareImage> tem = std::make_shared<shareImage>();
tem->strImgProductID = pDetImageInfo->strProductID;
tem->Status = -1;
if (m_pALLImgCheckAnalysisy)
{ {
std::shared_ptr<shareImage> tem = std::make_shared<shareImage>(); m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem);
tem->strImgProductID = pDetImageInfo->strProductID + "_" + std::to_string(pi);
tem->Status = -1;
if (m_pALLImgCheckAnalysisy)
{
m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem);
}
} }
return 0; return 0;
} }
@ -1079,38 +1076,7 @@ int deal::SendImgToCheck(std::shared_ptr<JC_IMAGE_INFO_> pDetImageInfo, IN_IMG_S
int re = 0; int re = 0;
// 一张图拍多个产品:上下拆分成多张,子图产品ID加索引后缀,分别送检 // 不再上下拆图:一张图对应一个产品,整图直接送检(产品ID不加索引后缀)
std::vector<cv::Mat> splitList;
if (!pDetImageInfo->img.empty() && pDetImageInfo->img.rows >= 2)
{
int half = pDetImageInfo->img.rows / 2;
splitList.push_back(pDetImageInfo->img(cv::Rect(0, 0, pDetImageInfo->img.cols, half)).clone());
splitList.push_back(pDetImageInfo->img(cv::Rect(0, half, pDetImageInfo->img.cols, pDetImageInfo->img.rows - half)).clone());
}
if (splitList.size() > 1)
{
for (size_t i = 0; i < splitList.size(); i++)
{
std::shared_ptr<shareImage> sub = std::make_shared<shareImage>();
*sub = *tem;
sub->img = splitList[i];
sub->strImgProductID = tem->strImgProductID + "_" + std::to_string(i);
// 同一产品(上半/下半)可能包含多个通道的图,子图作为中间图,待所有通道送完后再统一发送结束标志
sub->Status = IN_IMG_Status_Other;
if (m_pALLImgCheckAnalysisy)
{
re = m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(sub);
if (re != 0)
{
return re;
}
}
m_nPushImgCount++;
}
return 0;
}
if (m_pALLImgCheckAnalysisy) if (m_pALLImgCheckAnalysisy)
{ {
re = m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem); re = m_pALLImgCheckAnalysisy->SetDataRun_SharePtr(tem);

Loading…
Cancel
Save