code_device/hgdriver/ImageProcess/ImageApplyOutHole.cpp

358 lines
12 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "ImageApplyOutHole.h"
#include "ImageProcess_Public.h"
//#define DRAW_PIC
CImageApplyOutHole::CImageApplyOutHole(void)
: CImageApply()
, m_borderSize(20)
, m_edgeScale(0.1f, 0.1f, 0.1f, 0.1f)
, m_threshold(50)
{
}
CImageApplyOutHole::CImageApplyOutHole(float borderSize, cv::Vec4f edgeScale, double threshold)
: CImageApply()
, m_borderSize(borderSize)
, m_edgeScale(edgeScale)
, m_threshold(threshold)
{
}
CImageApplyOutHole::~CImageApplyOutHole(void)
{
}
void CImageApplyOutHole::apply(cv::Mat& pDib, int side)
{
(void)pDib;
(void)side;
}
void CImageApplyOutHole::dilateContour(std::vector<cv::Point>& contour, int distance)
{
cv::Moments mu = cv::moments(contour);
cv::Point2f center(mu.m10 / mu.m00, mu.m01 / mu.m00), p_temp;
for (size_t i = 0; i < contour.size(); i++)
{
p_temp = contour[i];
double dis = cv::sqrt(cv::pow(p_temp.x - center.x, 2) + cv::pow(p_temp.y - center.y, 2));
double scale = dis / (distance + dis);
double x = (p_temp.x - center.x) / scale + center.x;
double y = (p_temp.y - center.y) / scale + center.y;
contour[i] = cv::Point(x, y);
}
}
#define RESIZE_FIXED_WIDTH 2448.0
#define LINE_WIDTH 18
void CImageApplyOutHole::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "enter ImageOutHole apply");
#endif // LOG
if (mats.size() < 2)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG
return;
}
if (mats[0].empty() || mats[1].empty())
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG
return;
}
double resize_scale = cv::min(RESIZE_FIXED_WIDTH / static_cast<double>(mats[0].cols), 1.0);
//¶þÖµ»¯Õý·´ÃæͼÏñ
cv::Mat front, back;
if (resize_scale != 1.0)
{
cv::resize(mats[0], front, cv::Size(), resize_scale, resize_scale);
cv::resize(mats[1], back, cv::Size(), resize_scale, resize_scale);
}
else
{
front = mats[0];
back = mats[1];
}
cv::Mat front_thre, back_thre;
hg::threshold_Mat(front, front_thre, m_threshold);
hg::threshold_Mat(back, back_thre, m_threshold);
#ifdef DRAW_PIC
cv::imwrite("front_thre.jpg", front_thre);
cv::imwrite("back_thre.jpg", back_thre);
#endif
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(m_borderSize * resize_scale / 4, 1));
cv::morphologyEx(front_thre, front_thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
cv::morphologyEx(back_thre, back_thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
#ifdef DRAW_PIC
cv::imwrite("front_thre2.jpg", front_thre);
cv::imwrite("back_thre2.jpg", back_thre);
#endif
//·´Ãæ¶þÖµ»¯Í¼Ïñˮƽ·­×ª
cv::flip(back_thre, back_thre, 1); //1:Horizontal
//Õý·´ÃæͼÏñÑ°±ß
std::vector<std::vector<cv::Point>> contours_front, contours_back;
std::vector<cv::Vec4i> b1_front, b1_back;
hg::findContours(front_thre.clone(), contours_front, b1_front, cv::RETR_CCOMP);
hg::findContours(back_thre.clone(), contours_back, b1_back, cv::RETR_CCOMP);
////ÌáÈ¡Õý·´ÃæͼÏñ×î´óÂÖÀª
std::vector<cv::Point> maxContour_front = hg::getMaxContour(contours_front, b1_front);
std::vector<cv::Point> maxContour_back = hg::getMaxContour(contours_back, b1_back);
if (maxContour_front.empty() || maxContour_back.empty())
return;
cv::RotatedRect rrect_front = hg::getBoundingRect(maxContour_front); //ÌáÈ¡ÕýÃæ×î´óÂÖÀªµÄ×îСÍâ½Ó¾ØÐÎ
cv::RotatedRect rrect_back = hg::getBoundingRect(maxContour_back); //ÌáÈ¡·´Ãæ×î´óÂÖÀªµÄ×îСÍâ½Ó¾ØÐÎ
//Èç¹ûÕý·´ÃæͼÏñ³ß´ç²îÒ쳬¹ý20¸öÏñËØ£¬Ö±½Ó·ÅÆú´¦Àí
if (cv::abs(rrect_front.size.width - rrect_back.size.width) > 20 ||
cv::abs(rrect_front.size.height - rrect_back.size.height) > 20)
return;
//ÌáÈ¡Õý·´ÃæͼÏñÖصþ²¿·ÖÇøÓò
cv::Rect roi_front, roi_back;
cv::RotatedRect mask_rotatedRect;
getRoi(rrect_front, rrect_back, front.size(), back.size(), roi_front, roi_back, mask_rotatedRect);
cv::Mat roiMat_front(front_thre, roi_front); //ÔÚÕýÃæ¶þֵͼÏñÖнØÈ¡Öصþ²¿·Ö
cv::Mat roiMat_back(back_thre, roi_back); //ÔÚ·´Ãæ¶þֵͼÏñÖнØÈ¡Öصþ²¿·Ö
#ifdef DRAW_PIC
cv::imwrite("roiMat_front.jpg", roiMat_front);
cv::imwrite("roiMat_back.jpg", roiMat_back);
#endif
//Õý·´Ãæ¶þֵͼÏñ×ö»òÔËË㣬ÕæÕýïοÕÇøÓò±£Áô0£¬ÆäËûµØ·½Ìî³äΪ255
cv::Mat mask;
cv::bitwise_or(roiMat_front, roiMat_back, mask); //»òÔËË㣬Õý·´Ãæ¶þֵͼÏñÖصþ
#ifdef DRAW_PIC
cv::imwrite("mask1.jpg", mask);
#endif
//¶þֵͼÏñÖصþͼÏñÑÕÉ«È¡·´£¬ÅòÕÍ£¬ÌáÈ¡ÂÖÀª
cv::bitwise_not(mask, mask);
#ifdef DRAW_PIC
cv::imwrite("mask2.jpg", mask); //·´É«
#endif
//ΪÁ˱ÜÃâ¿×¶´³¹µ×¹á´©Ö½±ß£¬ÈËΪ»æÖÆÖ½ÕÅÂÖÀª£¬È·±£ËùÓп׶´Îª·â±ÕͼÐΣ¬²»»áÓë±³¾°Õ³Á¬
cv::polylines(mask, hg::getVertices(mask_rotatedRect), true, cv::Scalar(0), LINE_WIDTH * resize_scale); //»æÖÆÖ½ÕžØÐαßÔµ
#ifdef DRAW_PIC
cv::imwrite("mask3.jpg", mask);
#endif
#ifdef DRAW_PIC
cv::imwrite("mask4.jpg", mask);
#endif
//ÌáÈ¡ÖصþͼÏñÂÖÀª
std::vector<std::vector<cv::Point>> contours_mask;
std::vector<cv::Vec4i> b1_mask;
hg::findContours(mask, contours_mask, b1_mask, cv::RETR_TREE);
//¹ýÂ˷ǿ׶´µÄÁªÍ¨ÇøÓò
std::vector<std::vector<cv::Point>> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize * resize_scale);
for (size_t i = 0; i < hole_contours.size(); i++)
for (size_t j = 0; j < hole_contours[i].size(); j++)
hole_contours[i][j] /= resize_scale;
cv::Mat thumbnail;
cv::resize(front(roi_front), thumbnail, cv::Size(200, 200));
cv::Scalar color = hg::getBackGroundColor(thumbnail, cv::Mat(), m_threshold);
roi_front.x /= resize_scale;
roi_front.y /= resize_scale;
roi_front.width /= resize_scale;
roi_front.height /= resize_scale;
for (size_t i = 0; i < hole_contours.size(); i++)
{
std::vector<std::vector<cv::Point>> contourss_temp;
dilateContour(hole_contours[i], m_borderSize / 4);
contourss_temp.push_back(hole_contours[i]);
cv::Mat front_temp = mats[0](roi_front);
hg::fillPolys(front_temp, contourss_temp, color);
}
if (isTwoSide)
{
int width_ = roi_back.width;
roi_back.x = back.cols - roi_back.width - roi_back.x; //ÒòΪ֮ǰ·´ÃæͼÏñ·­×ª£¬ËùÒÔÏÖÔÚROIÒ²Òª½øÐÐÏàÓ¦·­×ª
cv::resize(back(roi_back), thumbnail, cv::Size(200, 200));
color = hg::getBackGroundColor(thumbnail, cv::Mat(), m_threshold);
roi_back.x /= resize_scale;
roi_back.y /= resize_scale;
roi_back.width /= resize_scale;
roi_back.height /= resize_scale;
hole_contours.clear();
hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, cv::Vec4f(m_edgeScale[0], m_edgeScale[1], m_edgeScale[2], m_edgeScale[3]), m_borderSize * resize_scale);
for (size_t i = 0; i < hole_contours.size(); i++)
{
std::vector<cv::Point> hole_contour;
for (size_t j = 0; j < hole_contours[i].size(); j++)
{
hole_contour.push_back(cv::Point(width_ - hole_contours[i][j].x - 1, hole_contours[i][j].y));
hole_contour[j] /= resize_scale;
}
std::vector<std::vector<cv::Point>> contours_temp;
dilateContour(hole_contour, m_borderSize / 4);
contours_temp.push_back(hole_contour);
cv::Mat back_temp = mats[1](roi_back);
hg::fillPolys(back_temp, contours_temp, color);
}
}
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG
}
void CImageApplyOutHole::getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, const cv::Size& srcSize_front, const cv::Size& srcSize_back, cv::Rect& roi_front,
cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect)
{
cv::Rect roi_front_ = rrect_front.boundingRect();
cv::Rect roi_back_ = rrect_back.boundingRect();
cv::Size meanSize = (roi_front_.size() + roi_back_.size()) / 2;
roi_front_.x += (roi_front_.width - meanSize.width) / 2;
roi_front_.width = meanSize.width;
roi_front_.y += (roi_front_.height - meanSize.height) / 2;
roi_front_.height = meanSize.height;
roi_back_.x += (roi_back_.width - meanSize.width) / 2;
roi_back_.width = meanSize.width;
roi_back_.y += (roi_back_.height - meanSize.height) / 2;
roi_back_.height = meanSize.height;
mask_rotatedRect.angle = (rrect_front.angle + rrect_back.angle) / 2;
mask_rotatedRect.size = (rrect_front.size + rrect_back.size) / 2.0f;
mask_rotatedRect.center = cv::Point2f(roi_front_.size().width + roi_back_.size().width, roi_front_.size().height + roi_back_.size().height) / 4.0f;
roi_front = roi_front_ & cv::Rect(cv::Point(0, 0), srcSize_front);
roi_back = roi_back_ & cv::Rect(cv::Point(0, 0), srcSize_back);
int offset_left_f = roi_front.x - roi_front_.x;
int offset_left_b = roi_back.x - roi_back_.x;
int offset_top_f = roi_front.y - roi_front_.y;
int offset_top_b = roi_back.y - roi_back_.y;
int offset_right_f = roi_front_.br().x - roi_front.br().x;
int offset_right_b = roi_back_.br().x - roi_back.br().x;
int offset_bottom_f = roi_front_.br().y - roi_front.br().y;
int offset_bottom_b = roi_back_.br().y - roi_back.br().y;
if (offset_left_f > offset_left_b)
{
roi_back.x += offset_left_f - offset_left_b;
roi_back.width -= offset_left_f - offset_left_b;
mask_rotatedRect.center.x -= offset_left_f - offset_left_b;
}
else
{
roi_front.x += offset_left_b - offset_left_f;
roi_front.width -= offset_left_b - offset_left_f;
mask_rotatedRect.center.x -= offset_left_b - offset_left_f;
}
if (offset_top_f > offset_top_b)
{
roi_back.y += offset_top_f - offset_top_b;
roi_back.height -= offset_top_f - offset_top_b;
mask_rotatedRect.center.y -= offset_top_f - offset_top_b;
}
else
{
roi_front.y += offset_top_b - offset_top_f;
roi_front.height -= offset_top_b - offset_top_f;
mask_rotatedRect.center.y -= offset_top_b - offset_top_f;
}
if (offset_right_f > offset_right_b)
roi_back.width -= offset_right_f - offset_right_b;
else
roi_front.width -= offset_right_b - offset_right_f;
if (offset_bottom_f > offset_bottom_b)
roi_back.height -= offset_bottom_f - offset_bottom_b;
else
roi_front.height -= offset_bottom_b - offset_bottom_f;
}
#define SIDE_LENGTH_UP_SCALE 6
#define PI 3.14159265359f
std::vector<std::vector<cv::Point>> CImageApplyOutHole::filterPoly(std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& m,
cv::RotatedRect roi, cv::Vec4f edgeScale, float sideLengthLow)
{
cv::RotatedRect roi2(roi.center,
cv::Size2f(roi.size.width * (1 - edgeScale[2] - edgeScale[3]), roi.size.height * (1 - edgeScale[0] - edgeScale[1])),
roi.angle);
cv::Point2f offset_0(roi.size.width * (edgeScale[2] - edgeScale[3]) / 2 + roi.center.x, roi.size.height * (edgeScale[0] - edgeScale[1]) / 2 + roi.center.y);
roi2.center.x = (offset_0.x - roi.center.x) * cos(roi.angle * PI / 180.0f) - (offset_0.y - roi.center.y) * sin(roi2.angle * PI / 180.0f) + roi.center.x;
roi2.center.y = (offset_0.x - roi.center.x) * sin(roi.angle * PI / 180.0f) + (offset_0.y - roi.center.y) * cos(roi2.angle * PI / 180.0f) + roi.center.y;
std::vector<cv::Point> vertices_roi1 = hg::getVertices(roi);
std::vector<cv::Point> vertices_roi2 = hg::getVertices(roi2);
std::vector<std::vector<cv::Point>> hole_contours;
for (size_t i = 0; i < contours.size(); i++)
{
if (m[i][2] != -1)
{
contours.erase(contours.begin() + i);
m.erase(m.begin() + i);
i--;
continue;
}
cv::RotatedRect rrect = hg::getBoundingRect(contours[i]);
if (rrect.size.width < sideLengthLow ||
rrect.size.height < sideLengthLow ||
rrect.size.width > sideLengthLow * SIDE_LENGTH_UP_SCALE ||
rrect.size.height > sideLengthLow * SIDE_LENGTH_UP_SCALE)
{
contours.erase(contours.begin() + i);
m.erase(m.begin() + i);
i--;
continue;
}
bool enabled = true;
for (size_t j = 0, count = contours[i].size(); j < count; j++)
{
cv::Point p(contours[i][j]);
double temp1 = pointPolygonTest(vertices_roi1, p, false); //ÅжÏÊÇ·ñÔÚÖ½ÕÅÄÚ 1£ºÄÚ£»0£ºÉÏ£»-1£ºÍâ
double temp2 = pointPolygonTest(vertices_roi2, p, false); //ÅжÏÊÇ·ñÔÚ±ßÔµÇøÓòÄÚ 1£ºÄÚ£»0£ºÉÏ£»-1£ºÍâ
//Èç¹ûÔÚÖ½ÕÅÍ⣬»òÕß±ßÔµÄÚ£¬ÊÓΪ·Ç¿×¶´
if (temp1 <= 0 || temp2 >= 0)
{
enabled = false;
//qDebug() << rrect.center.x << ":" << rrect.center.y << "::::" << rrect.size.width << " - " << rrect.size.height;
break;
}
}
if (enabled)
hole_contours.push_back(contours[i]);
}
return hole_contours;
}