update 拼图上下错位

dev_lsy
liusiyang 1 week ago
parent 718d12b26b
commit 5d80fc5c8e

@ -188,6 +188,9 @@ private:
int GetLine(const cv::Mat &img, std::vector<cv::Point> &pointList, int lineNum, int xory, int &outP);
// 找到产品(亮色区域)所在的第一行(顶部边缘), 用于左右图上下对齐
int GetProductFirstRow(const cv::Mat &img, int &outRow);
public:
// 运行的基本参数
RunInfoST m_RunConfig;

@ -9,6 +9,7 @@
#include "CameraCheckAnalysisy.hpp"
#include "CheckUtil.hpp"
#include "Define.h"
#include <algorithm>
CameraCheckAnalysisy::CameraCheckAnalysisy()
{
@ -174,19 +175,52 @@ int CameraCheckAnalysisy::Detect_Pre()
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s ==================img size/type != img_B ", strBasic.c_str());
return 1;
}
cv::Mat &img = pImageResult->result->in_shareImage->img;
cv::Mat &img_B = pImageResult->result->in_shareImage->img_B;
// 左右图存在上下错位: 找到左右图产品所在的第一行, 进行简单上下对齐
{
int rowLeft = -1;
int rowRight = -1;
if (GetProductFirstRow(img, rowLeft) == 0 && GetProductFirstRow(img_B, rowRight) == 0)
{
// 以较高的顶边为基准, 把较低的那张图向上平移, 使两图顶边对齐
int refRow = std::min(rowLeft, rowRight);
int shiftLeft = refRow - rowLeft; // <= 0, 负值表示向上平移
int shiftRight = refRow - rowRight; // <= 0
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s ==================align rowLeft %d rowRight %d shiftLeft %d shiftRight %d",
strBasic.c_str(), rowLeft, rowRight, shiftLeft, shiftRight);
if (shiftLeft < 0)
{
cv::Mat M = (cv::Mat_<double>(2, 3) << 1, 0, 0, 0, 1, (double)shiftLeft);
cv::warpAffine(img, img, M, img.size(), cv::INTER_NEAREST, cv::BORDER_CONSTANT, cv::Scalar(0));
}
if (shiftRight < 0)
{
cv::Mat M = (cv::Mat_<double>(2, 3) << 1, 0, 0, 0, 1, (double)shiftRight);
cv::warpAffine(img_B, img_B, M, img_B.size(), cv::INTER_NEAREST, cv::BORDER_CONSTANT, cv::Scalar(0));
}
}
else
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s ==================GetProductFirstRow fail, skip align", strBasic.c_str());
}
}
const int overlap = 1056;
if (pImageResult->result->in_shareImage->img.cols <= overlap)
if (img.cols <= overlap)
{
m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s ==================img.cols <= overlap %d ", strBasic.c_str(), overlap);
return 1;
}
cv::Mat merge_img;
cv::hconcat(pImageResult->result->in_shareImage->img(cv::Rect(0, 0, pImageResult->result->in_shareImage->img.cols - overlap, pImageResult->result->in_shareImage->img.rows)),
pImageResult->result->in_shareImage->img_B, merge_img);
pImageResult->result->in_shareImage->img = merge_img;
cv::hconcat(img(cv::Rect(0, 0, img.cols - overlap, img.rows)), img_B, merge_img);
img = merge_img;
// 拼接完成后 img_B 不再需要,立即释放内存
pImageResult->result->in_shareImage->img_B.release();
img_B.release();
if (pImageResult->result->in_shareImage->Det_Mode == DET_MODE_MergeImg)
{
@ -1519,3 +1553,79 @@ int CameraCheckAnalysisy::GetLine(const cv::Mat &img, std::vector<cv::Point> &po
return 0;
}
// 找到图像中产品(亮色区域)所在的第一行(顶部边缘), 用于左右图上下对齐
// 从上往下逐行扫描, 当某一行亮像素数量超过阈值比例时, 认为该行是产品顶边
int CameraCheckAnalysisy::GetProductFirstRow(const cv::Mat &img, int &outRow)
{
outRow = -1;
if (img.empty())
{
return 1;
}
cv::Mat gray;
if (img.channels() == 1)
{
gray = img;
}
else if (img.channels() == 3)
{
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
}
else
{
return 1;
}
const uchar brightThreshold = 35; // 亮像素灰度阈值(与背景判断阈值保持一致)
const int needBrightCount = std::max(1, (int)(gray.cols * 0.2)); // 该行亮像素数量占比超过 20% 认为是产品所在行
const int rowStep = 16; // 跳行扫描步长
// 判断某一行是否为产品所在行(亮像素数量达到阈值)
auto isProductRow = [&](int row) -> bool
{
const uchar *p = gray.ptr<uchar>(row);
int brightCount = 0;
for (int col = 0; col < gray.cols; ++col)
{
if (p[col] >= brightThreshold)
{
if (++brightCount >= needBrightCount)
{
return true;
}
}
}
return false;
};
// 1、跳行粗扫: 每隔 rowStep 行扫描一次, 定位产品顶边的大致位置
int rowFound = -1;
for (int row = 0; row < gray.rows; row += rowStep)
{
if (isProductRow(row))
{
rowFound = row;
break;
}
}
if (rowFound < 0)
{
return 2; // 未找到产品顶边
}
// 2、在上一个采样行与 rowFound 之间逐行精确定位
int rowStart = std::max(0, rowFound - rowStep + 1);
for (int row = rowStart; row <= rowFound; ++row)
{
if (isProductRow(row))
{
outRow = row;
return 0;
}
}
return 2; // 理论上不会走到这里
}

Loading…
Cancel
Save