You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
BOE_FOG_DETECT/AlgorithmModule/src/ImageMerge.cpp

802 lines
22 KiB

#include "ImageMerge.h"
#include "CheckUtil.hpp"
#include "CheckErrorCodeDefine.hpp"
ImageMerge::ImageMerge()
{
bshowimg = false;
m_bcalSucc = false;
}
ImageMerge::~ImageMerge() {}
int ImageMerge::CalMergeRoi(DetConfig *pDetConfig, cv::Mat &img1, const cv::Mat &img2)
{
// cv::imwrite("merge1.png", img1);
// cv::imwrite("merge2.png", img2);
m_bcalSucc = false;
std::cout << img1.size() << std::endl;
std::cout << img2.size() << std::endl;
// if (img1.size() != img2.size())
// {
// return -1;
// }
long t1, t2;
t1 = CheckUtil::getcurTime();
int re = 0;
cv::Rect Left_Roi;
cv::Rect Right_Roi;
bool bleft = ProductSide_left(img1);
cv::Mat leftImg = img1;
cv::Mat rightImg = img2;
m_bleft_img1 = bleft;
if (bleft)
{
leftImg = img1;
rightImg = img2;
}
else
{
leftImg = img2;
rightImg = img1;
}
int max_len = img1.cols;
if (img2.cols > max_len)
{
max_len = img2.cols;
}
m_ALLImgSize.width = max_len * 2;
m_ALLImgSize.height = rightImg.rows;
// cv::Mat AllImg = cv::Mat::zeros(rightImg.rows, max_len * 2, rightImg.type());
{
cv::Rect Left_Tem_Roi;
cv::Point Left_Tem_Point_Up;
cv::Point Left_Tem_Point_Donw;
cv::Rect Right_Tem_Roi;
cv::Point Right_Tem_Point_Up;
cv::Point Right_Tem_Point_Donw;
// left Img
{
re = GetRectAndPoint(leftImg, Left_Tem_Roi, Left_Tem_Point_Up, Left_Tem_Point_Donw, true, pDetConfig->strcam, pDetConfig->strchannel + "left");
if (re != 0)
{
// m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg GetRectAndPoint TAA error %d", strcam.c_str(), re);
return 1;
}
re = GetRectAndPoint(rightImg, Right_Tem_Roi, Right_Tem_Point_Up, Right_Tem_Point_Donw, false, pDetConfig->strcam, pDetConfig->strchannel + "right");
if (re != 0)
{
return 1;
}
cv::Rect roi_right;
roi_right.x = 0;
roi_right.y = 0;
roi_right.height = rightImg.rows;
roi_right.width = rightImg.cols;
m_roi_right_img = roi_right;
m_roi_right_ALLimg = roi_right;
// rightImg(roi_right).copyTo(AllImg(roi_right));
int hlen_left = Left_Tem_Point_Donw.y - Left_Tem_Point_Up.y;
int hlen_right = Right_Tem_Point_Donw.y - Right_Tem_Point_Up.y;
float fhscle = hlen_right * 1.0f / hlen_left;
int dy = Right_Tem_Point_Up.y - Left_Tem_Point_Up.y;
cv::Rect allroi = Left_Tem_Roi;
allroi.height *= fhscle;
allroi.x = Right_Tem_Roi.x + Right_Tem_Roi.width;
allroi.y += dy;
// cv::Size sz;
// sz.width = allroi.width;
// sz.height = allroi.height;
m_roi_left_img = Left_Tem_Roi;
m_roi_left_ALLimg = allroi;
// cv::resize(leftImg(Left_Tem_Roi), AllImg(allroi), sz);
}
}
m_bcalSucc = true;
re = detMergeImg(img1, img2);
if (re != 0)
{
return 1;
}
// img1 = AllImg;
t2 = CheckUtil::getcurTime();
//cv::imwrite(pDetConfig->strcam + pDetConfig->strchannel + "_merg.png", img1);
// m_pdetlog->AddCheckstr(PrintLevel_1, "Detect_Pre", "Cam %s Mergimg use time %ld ms", pDetConfig->strcam.c_str(), t2 - t1);
return 0;
}
int ImageMerge::detMergeImg(cv::Mat &img1, const cv::Mat &img2)
{
if (m_bcalSucc == false)
{
return -1;
}
cv::Mat AllImg = cv::Mat::zeros(m_ALLImgSize.height, m_ALLImgSize.width, img1.type());
cv::Mat leftImg = img1;
cv::Mat rightImg = img2;
if (m_bleft_img1)
{
leftImg = img1;
rightImg = img2;
}
else
{
leftImg = img2;
rightImg = img1;
}
rightImg(m_roi_right_img).copyTo(AllImg(m_roi_right_ALLimg));
cv::Size sz;
sz.width = m_roi_left_ALLimg.width;
sz.height = m_roi_left_ALLimg.height;
cv::resize(leftImg(m_roi_left_img), AllImg(m_roi_left_ALLimg), sz);
img1 = AllImg;
return 0;
}
int ImageMerge::GetRectAndPoint(const cv::Mat &img, cv::Rect &roi, cv::Point &merg_p_up, cv::Point &merg_p_down, bool bleft, std::string strcam, std::string strchannel)
{
bshowimg = true;
int A_line_up = 0;
int A_line_down = 0;
Edge_Search_Config config;
if (bshowimg)
{
if (img.channels() != 1)
{
showimg = img.clone();
}
else
{
cv::cvtColor(img, showimg, cv::COLOR_GRAY2BGR);
}
}
config.nSearchCount = 10;
config.strchannel = strchannel;
config.directSign = DirectSign_UP;
if (bleft)
{
config.roi = cv::Rect(0, 0, 200, img.rows * 0.8);
}
else
{
config.roi = cv::Rect(img.cols - 200, 0, 200, img.rows * 0.8);
}
int re123 = GetEdgePoint(img, &config, A_line_up);
if (re123 != 0)
{
// printf("DirectSign_UP::111111111111GetEdgePoint111111 A_line_up %d\n", re123);
return 1;
}
config.directSign = DirectSign_DOWN;
config.strchannel = strchannel + "ccc";
config.roi = cv::Rect(0, img.rows * 0.2, 200, img.rows * 0.8 - 1);
if (bleft)
{
config.roi = cv::Rect(0, img.rows * 0.2, 200, img.rows * 0.8 - 1);
}
else
{
config.roi = cv::Rect(img.cols - 200, img.rows * 0.2, 200, img.rows * 0.8 - 1);
}
re123 = GetEdgePoint(img, &config, A_line_down);
if (re123 != 0)
{
// printf("DirectSign_UP::111111111111GetEdgePoint111111 A_line_down %d\n", re123);
return 1;
}
{
if (bshowimg)
{
cv::line(showimg, cv::Point(0, A_line_down), cv::Point(img.cols, A_line_down), cv::Scalar(0, 255, 0), 2);
cv::line(showimg, cv::Point(0, A_line_up), cv::Point(img.cols, A_line_up), cv::Scalar(0, 255, 0), 2);
cv::imwrite(strcam + strchannel + "_line.png", showimg);
}
}
// printf("DirectSign_UP::111111111111111111 re123 %d\n", re123);
// getchar();
cv::Mat small, smallbin;
cv::resize(img, small, cv::Size(600, 1500));
cv::threshold(small, smallbin, 80, 255,
cv::THRESH_BINARY);
/* 3. contours */
std::vector<std::vector<cv::Point>> contours;
cv::findContours(smallbin, contours,
cv::RETR_EXTERNAL,
cv::CHAIN_APPROX_SIMPLE);
if (contours.empty())
return 1;
/* 4. max contour */
double maxArea = 0;
int idx = -1;
for (int i = 0; i < contours.size(); i++)
{
double area = cv::contourArea(contours[i]);
if (area > maxArea)
{
maxArea = area;
idx = i;
}
}
if (idx < 0)
return 1;
cv::Rect rSmall = cv::boundingRect(contours[idx]);
/* 5. map to original */
float sx = (float)img.cols / smallbin.cols;
float sy = (float)img.rows / smallbin.rows;
cv::Rect rectInSrc;
rectInSrc.x = int(rSmall.x * sx) - 50;
rectInSrc.y = int(rSmall.y * sy) - 50;
rectInSrc.width = int(rSmall.width * sx) + 100;
rectInSrc.height = int(rSmall.height * sy) + 100;
if (rectInSrc.y >= A_line_up)
{
rectInSrc.y = A_line_up - 5;
}
if (rectInSrc.y + rectInSrc.height <= A_line_down)
{
rectInSrc.height = A_line_down + 5 - rectInSrc.y;
}
if (rectInSrc.x < 0)
rectInSrc.x = 0;
if (rectInSrc.y < 0)
rectInSrc.y = 0;
if (rectInSrc.x + rectInSrc.width > img.cols)
rectInSrc.width = img.cols - rectInSrc.x;
if (rectInSrc.y + rectInSrc.height > img.rows)
{
rectInSrc.height = img.rows - rectInSrc.y;
}
merg_p_up.y = A_line_up;
merg_p_up.x = img.cols;
merg_p_down.y = A_line_down;
merg_p_down.x = img.cols;
roi = rectInSrc;
if (bshowimg)
{
cv::rectangle(showimg, rectInSrc, cv::Scalar(0, 0, 255), 2);
cv::imwrite(strcam + strchannel + "_rect.png", showimg);
}
return 0;
}
int ImageMerge::GetEdgePoint(const cv::Mat &img, Edge_Search_Config *pEdge_Search_Config, int &outP)
{
bool bdbuge = false;
bdbuge = bshowimg;
if (img.empty())
{
return -11;
}
if (img.channels() != 1)
{
printf("*****************************channels\n");
return -12;
}
// 检查roi;
if (!CheckUtil::RoiInImg(pEdge_Search_Config->roi, img))
{
return -13;
}
if (!pEdge_Search_Config->CheckConfigValid())
{
return -14;
}
std::vector<cv::Point> pointList;
bool search_UP_DOWN = false;
cv::Rect roi = pEdge_Search_Config->roi;
int sx = roi.x;
int ex = roi.x + roi.width;
int sy = roi.y;
int ey = roi.y + roi.height;
int nSearchLen = roi.width; // 搜索区域的长度
int nCurPoint_Step = pEdge_Search_Config->stepCount; // 当前点搜索的步长
// 搜索小范围确认
int nhalfrang = (int)pEdge_Search_Config->nSearchrange / 2;
int nrange_start = 0 - nhalfrang;
int nrange_end = 0 - nhalfrang;
int num = 0;
while (true)
{
num++;
nrange_end++;
if (num >= pEdge_Search_Config->nSearchrange)
{
break;
}
}
// 判断方向
switch (pEdge_Search_Config->directSign)
{
case DirectSign_UP:
search_UP_DOWN = true;
nSearchLen = roi.width;
sx = roi.x;
ex = roi.x + roi.width;
sy = roi.y;
ey = roi.y + roi.height;
nCurPoint_Step = pEdge_Search_Config->stepCount;
break;
case DirectSign_DOWN:
search_UP_DOWN = true;
nSearchLen = roi.width;
nCurPoint_Step = -pEdge_Search_Config->stepCount;
sx = roi.x;
ex = roi.x + roi.width;
sy = roi.y + roi.height - 1;
ey = roi.y;
break;
case DirectSign_Left:
nSearchLen = roi.height;
search_UP_DOWN = false;
nCurPoint_Step = pEdge_Search_Config->stepCount;
sx = roi.x;
ex = roi.x + roi.width;
sy = roi.y;
ey = roi.y + roi.height;
break;
case DirectSign_Right:
nSearchLen = roi.height;
search_UP_DOWN = false;
nCurPoint_Step = -pEdge_Search_Config->stepCount;
sx = roi.x + roi.width - 1;
ex = roi.x;
sy = roi.y;
ey = roi.y + roi.height;
break;
default:
break;
}
// 搜索 点数
int nSearchPointNum = pEdge_Search_Config->nSearchCount;
// 搜素点的间隔
int nSearchPointStep = 1;
if (nSearchPointNum > 1)
{
nSearchPointStep = int(nSearchLen * 1.0f / (nSearchPointNum - 1));
}
if (bdbuge)
{
cv::rectangle(showimg, roi, cv::Scalar(255, 0, 0), 2);
printf("nSearchPointStep %d nCurPoint_Step %d,nrange_start %d %d\n", nSearchPointStep, nCurPoint_Step, nrange_start, nrange_end);
}
uchar *pdata = (uchar *)img.data;
int offt = 0;
// 搜索 上下边
if (search_UP_DOWN)
{
// 每个搜索点 分布在X方向。
for (int x = sx; x < ex; x = x + nSearchPointStep)
{
int bOKNum = 0;
int cur_x = x;
int cur_y = sy;
bool bSucc = false;
int succ_y = 0;
// 对每个搜索点进行 y方向搜索
for (int y = sy;; y = y + nCurPoint_Step)
{
if (y < 0 || y >= img.rows)
{
continue;
}
//
if (nCurPoint_Step > 0 && y > ey)
{
break;
}
if (nCurPoint_Step < 0 && y < ey)
{
break;
}
offt = y * img.cols;
int range_okNum = 0;
// 对一定范围的点进行判断
for (int k = nrange_start; k < nrange_end; k++)
{
int rangeX = x + k;
if (rangeX < 0 || rangeX >= img.cols)
{
continue;
}
offt += rangeX;
if (offt < 0 || offt >= img.cols * img.rows)
{
printf("rangeX %d nCurPoint_Step %d off %d x %d y %d sy %d ey %d %d %d\n", rangeX, nCurPoint_Step, offt, x, y, sy, ey, img.cols, img.rows);
}
if (pdata[offt] >= pEdge_Search_Config->nValueThreshold) // 找到
{
range_okNum++;
}
}
if (range_okNum >= pEdge_Search_Config->nSearchrange)
{
if (bdbuge)
{
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 0, 255));
}
if (bOKNum == 0)
{
cur_y = y;
}
bOKNum++;
// 连续搜索到 满足要求的点。
if (bOKNum >= pEdge_Search_Config->nLimit)
{
bSucc = true;
succ_y = y;
break;
}
}
else
{
// 如果有间断,需要重新计算连续情况。
bOKNum = 0;
if (bdbuge)
{
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 255, 0));
}
}
}
if (bSucc)
{
cv::Point p(cur_x, cur_y);
if (bdbuge)
{
cv::circle(showimg, p, 3, cv::Scalar(255, 0, 0));
}
pointList.push_back(p);
if (pointList.size() > 5)
{
// printf("=============feeeee\n");
sy = succ_y - 100;
ey = succ_y + 100;
switch (pEdge_Search_Config->directSign)
{
case DirectSign_UP:
sy = succ_y - 100;
ey = succ_y + 100;
break;
case DirectSign_DOWN:
sy = succ_y + 100;
ey = succ_y - 100;
break;
default:
break;
}
if (sy < 0)
{
sy = 0;
}
if (ey >= img.rows)
{
ey = img.rows - 1;
}
if (ey < 0)
{
ey = 0;
}
if (sy >= img.rows)
{
sy = img.rows - 1;
}
}
}
}
}
else // 搜索 左右边
{
// 每个搜索点 分布在X方向。
for (int y = sy; y < ey; y = y + nSearchPointStep)
{
int bOKNum = 0;
int cur_x = sx;
int cur_y = y;
bool bSucc = false;
int succ_x = 0;
// 对每个搜索点进行 y方向搜索
for (int x = sx;; x = x + nCurPoint_Step)
{
if (x < 0 || x >= img.cols)
{
continue;
}
//
if (nCurPoint_Step > 0 && x > ex)
{
break;
}
if (nCurPoint_Step < 0 && x < ex)
{
break;
}
int range_okNum = 0;
// 对一定范围的点进行判断
for (int k = nrange_start; k < nrange_end; k++)
{
int rangey = y + k;
if (rangey < 0 || rangey >= img.rows)
{
continue;
}
offt = rangey * img.cols + x;
if (offt < 0 || offt >= img.cols * img.rows)
{
printf("rangey %d off %d x %d y %d ey %d %d %d\n", rangey, offt, x, y, ey, img.cols, img.rows);
}
if (pdata[offt] >= pEdge_Search_Config->nValueThreshold) // 找到
{
range_okNum++;
}
}
if (range_okNum >= pEdge_Search_Config->nSearchrange)
{
if (bdbuge)
{
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 0, 255));
}
if (bOKNum == 0)
{
cur_x = x;
}
bOKNum++;
// 连续搜索到 满足要求的点。
if (bOKNum >= pEdge_Search_Config->nLimit)
{
bSucc = true;
succ_x = x;
break;
}
}
else
{
// 如果有间断,需要重新计算连续情况。
bOKNum = 0;
if (bdbuge)
{
cv::circle(showimg, cv::Point(x, y), 1, cv::Scalar(0, 255, 0));
}
}
}
if (bSucc)
{
cv::Point p(cur_x, cur_y);
if (bdbuge)
{
cv::circle(showimg, p, 3, cv::Scalar(255, 0, 0));
}
pointList.push_back(p);
if (pointList.size() > 5)
{
// printf("=============feeeee\n");
sx = succ_x - 100;
ex = succ_x + 100;
if (sx < 0)
{
sx = 0;
}
if (ex >= img.cols)
{
ex = img.cols - 1;
}
}
}
}
}
if (bdbuge)
{
cv::imwrite(pEdge_Search_Config->strchannel + "show.png", showimg);
}
{
const int maxDeviation = 10; // 可调阈值:最大允许偏离像素
std::vector<cv::Point> avgPoints;
int PNum = pointList.size();
// 第一次计算粗略均值
int sum_y = 0, sum_x = 0;
for (const auto &pt : pointList)
{
sum_x += pt.x;
sum_y += pt.y;
}
float avg_y = sum_y * 1.0f / PNum;
float avg_x = sum_x * 1.0f / PNum;
// 过滤异常点
std::vector<cv::Point> filtered;
for (const auto &pt : pointList)
{
if (search_UP_DOWN) // 横向:判断 y 偏差
{
if (std::abs(pt.y - avg_y) <= maxDeviation)
filtered.push_back(pt);
}
else // 纵向:判断 x 偏差
{
if (std::abs(pt.x - avg_x) <= maxDeviation)
filtered.push_back(pt);
}
}
if (filtered.empty())
return -1;
int sum_fx = 0, sum_fy = 0;
for (const auto &pt : filtered)
{
sum_fx += pt.x;
sum_fy += pt.y;
}
if (search_UP_DOWN) // 横向:判断 y 偏差
{
outP = sum_fy / (int)filtered.size();
}
else // 纵向:判断 x 偏差
{
outP = sum_fx / (int)filtered.size();
}
}
return 0;
}
int ImageMerge::GetLine(const cv::Mat &img, std::vector<cv::Point> &pointList, int lineNum, int xory, int &outP)
{
if (pointList.size() < 0)
return -1;
const int maxDeviation = 10; // 可调阈值:最大允许偏离像素
std::vector<cv::Point> avgPoints;
int PNum = pointList.size();
// 第一次计算粗略均值
int sum_y = 0, sum_x = 0;
for (const auto &pt : pointList)
{
sum_x += pt.x;
sum_y += pt.y;
}
float avg_y = sum_y * 1.0f / PNum;
float avg_x = sum_x * 1.0f / PNum;
// 过滤异常点
std::vector<cv::Point> filtered;
for (const auto &pt : pointList)
{
if (xory == 0) // 横向:判断 y 偏差
{
if (std::abs(pt.y - avg_y) <= maxDeviation)
filtered.push_back(pt);
}
else // 纵向:判断 x 偏差
{
if (std::abs(pt.x - avg_x) <= maxDeviation)
filtered.push_back(pt);
}
}
if (filtered.empty())
return -1;
int sum_fx = 0, sum_fy = 0;
for (const auto &pt : filtered)
{
sum_fx += pt.x;
sum_fy += pt.y;
}
if (xory == 0) // 横向:判断 y 偏差
{
outP = sum_fy / (int)filtered.size();
}
else // 纵向:判断 x 偏差
{
outP = sum_fx / (int)filtered.size();
}
return 0;
}
bool ImageMerge::ProductSide_left(const cv::Mat &img)
{
cv::Rect Roi_left, Right_Roi;
Roi_left.x = 0;
Roi_left.y = 0;
Roi_left.width = img.cols * 0.1;
Roi_left.height = img.rows;
Right_Roi.x = img.cols - img.cols * 0.1;
Right_Roi.y = 0;
Right_Roi.width = img.cols * 0.1;
Right_Roi.height = img.rows;
cv::Mat left_img = img(Roi_left);
cv::Mat right_img = img(Right_Roi);
cv::Size sz = cv::Size(200, 600);
cv::resize(left_img, left_img, sz);
cv::resize(right_img, right_img, sz);
int nonZeroCount_left = cv::countNonZero(left_img);
int nonZeroCount_right = cv::countNonZero(right_img);
if (nonZeroCount_left >= nonZeroCount_right)
{
return true;
}
else
{
return false;
}
return false;
}