twain3.0/huagao/ImageProcess/ImageApplyOutHole.cpp

252 lines
8.2 KiB
C++
Raw Normal View History

#include "ImageApplyOutHole.h"
#include "ImageProcess_Public.h"
#ifdef LOG
#include "Device/filetools.h"
#endif // LOG
CImageOutHole::CImageOutHole(void)
: CImageApply()
, m_borderSize(200)
, m_edgeScale(0.1f)
, m_threshold(50)
{
}
CImageOutHole::CImageOutHole(float borderSize, float edgeScale, double threshold)
: CImageApply()
, m_borderSize(borderSize)
, m_edgeScale(edgeScale)
, m_threshold(threshold)
{
}
CImageOutHole::~CImageOutHole(void)
{
}
void CImageOutHole::apply(cv::Mat& pDib, int side) {}
void CImageOutHole::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;
}
//<2F><>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>
cv::Mat front = mats[0];
cv::Mat 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);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>ͼ<EFBFBD><CDBC>ˮƽ<CBAE><C6BD>ת
cv::flip(back_thre, back_thre, 1); //1:Horizontal
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>Ѱ<EFBFBD><D1B0>
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_EXTERNAL);
hg::findContours(back_thre.clone(), contours_back, b1_back, cv::RETR_EXTERNAL);
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::vector<cv::Point> maxContour_front = hg::getMaxContour(contours_front, b1_front);
std::vector<cv::Point> maxContour_back = hg::getMaxContour(contours_back, b1_back);
cv::RotatedRect rrect_front = hg::getBoundingRect(maxContour_front); //<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>Ӿ<EFBFBD><D3BE><EFBFBD>
cv::RotatedRect rrect_back = hg::getBoundingRect(maxContour_back); //<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>Ӿ<EFBFBD><D3BE><EFBFBD>
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cv::Rect roi_front, roi_back;
cv::RotatedRect mask_rotatedRect;
getRoi(rrect_front, rrect_back, cv::Size(front.cols, front.rows), roi_front, roi_back, mask_rotatedRect);
cv::Mat roiMat_front(front_thre, roi_front); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵͼ<D6B5><CDBC><EFBFBD>н<EFBFBD>ȡ<EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>
cv::Mat roiMat_back(back_thre, roi_back); //<2F>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD>ֵͼ<D6B5><CDBC><EFBFBD>н<EFBFBD>ȡ<EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵͼ<D6B5><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3A3AC><EFBFBD><EFBFBD><EFBFBD>ο<EFBFBD><CEBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ط<EFBFBD><D8B7><EFBFBD><EFBFBD><EFBFBD>Ϊ255
cv::Mat mask;
bitwise_or(roiMat_front, roiMat_back, mask); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵͼ<D6B5><CDBC><EFBFBD>ص<EFBFBD>
//<2F><>ֵͼ<D6B5><CDBC><EFBFBD>ص<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ɫȡ<C9AB><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
std::vector<std::vector<cv::Point>> contours_mask;
std::vector<cv::Vec4i> b1_mask;
bitwise_not(mask, mask); //<2F><>ɫ
cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(15, 15));
dilate(mask, mask, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar(255)); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׶<EFBFBD><D7B6><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//Ϊ<>˱<EFBFBD><CBB1><EFBFBD><EFBFBD>׶<EFBFBD><D7B6><EFBFBD><EFBFBD>׹ᴩֽ<E1B4A9>ߣ<EFBFBD><DFA3><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD><EFBFBD>п׶<D0BF>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ͼ<EFBFBD>Σ<EFBFBD><CEA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBB1B3>ճ<EFBFBD><D5B3>
polylines(mask, hg::getVertices(mask_rotatedRect), true, cv::Scalar(0), 15); //<2F><><EFBFBD><EFBFBD>ֽ<EFBFBD>ž<EFBFBD><C5BE>α<EFBFBD>Ե
hg::findContours(mask.clone(), contours_mask, b1_mask, cv::RETR_TREE); //<2F><>ȡ<EFBFBD>ص<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>˷ǿ׶<C7BF><D7B6><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD>
std::vector<std::vector<cv::Point>> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize);
for (int i = 0; i < hole_contours.size(); i++)
cv::drawContours(mask, hole_contours, i, cv::Scalar(127), 2);
for (size_t i = 0; i < hole_contours.size(); i++)
{
cv::Scalar color = getBackGroudColor(front(roi_front), hole_contours[i]);
cv::Mat temp = front(roi_front);
std::vector<std::vector<cv::Point>> contourss_temp;
contourss_temp.push_back(hole_contours[i]);
hg::fillPolys(temp, contourss_temp, color);
}
if (isTwoSide)
{
int width_ = roi_back.width;
roi_back.x = back.cols - roi_back.width - roi_back.x; //<2F><>Ϊ֮ǰ<D6AE><C7B0><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ROIҲҪ<D2B2><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>ת
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));
cv::Scalar color = getBackGroudColor(back(roi_back), hole_contour);
cv::Mat temp = back(roi_back);
std::vector<std::vector<cv::Point>> contours_temp;
contours_temp.push_back(hole_contour);
hg::fillPolys(temp, contours_temp, color);
}
}
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG
}
void CImageOutHole::getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize,
cv::Rect& roi_front, cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect)
{
cv::Size size(static_cast<int>(rrect_front.size.width + rrect_back.size.width) / 2, static_cast<int>(rrect_front.size.height + rrect_back.size.height) / 2);
float angle = (rrect_front.angle + rrect_back.angle) / 2;
rrect_front.size = rrect_back.size = size;
rrect_front.angle = rrect_back.angle = angle;
roi_front = rrect_front.boundingRect();
roi_back = rrect_back.boundingRect();
if (roi_front.width != roi_back.width || roi_front.height != roi_back.height)
{
roi_front.height = roi_back.height;
roi_front.width = roi_back.width;
}
cv::Point offset(0, 0);
int top = std::min(roi_front.y, roi_back.y);
if (top < 0)
{
roi_front.y -= top;
roi_back.y -= top;
roi_front.height += top;
roi_back.height += top;
offset.y += top;
}
int left = std::min(roi_front.x, roi_back.x);
if (left < 0)
{
roi_front.x -= left;
roi_back.x -= left;
roi_front.width += left;
roi_back.width += left;
offset.x += left;
}
int right = std::max(roi_front.x + roi_front.width, roi_back.x + roi_back.width);
if (right >= srcSize.width)
{
roi_front.width -= (right - srcSize.width + 1);
roi_back.width -= (right - srcSize.width + 1);
}
int bottom = std::max(roi_front.y + roi_front.height, roi_back.y + roi_back.height);
if (bottom >= srcSize.height)
{
roi_front.height -= (bottom - srcSize.height + 1);
roi_back.height -= (bottom - srcSize.height + 1);
}
mask_rotatedRect.center = cv::Point((roi_front.width + offset.x) / 2, (roi_front.height + offset.y) / 2);
mask_rotatedRect.size = size;
mask_rotatedRect.angle = angle;
}
std::vector<std::vector<cv::Point>> CImageOutHole::filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& m,
cv::RotatedRect roi, float edgeScale, float areaThreshold)
{
edgeScale = std::min(0.49f, std::max(edgeScale, 0.0f));
cv::RotatedRect roi2(roi.center, cv::Size(static_cast<int>(roi.size.width * (1 - edgeScale * 2)),
static_cast<int>(roi.size.height * (1 - edgeScale * 2))), roi.angle);
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, length = contours.size(); i < length; i++)
{
if (m[i][2] != -1) continue;
cv::RotatedRect rrect = hg::getBoundingRect(contours[i]);
if (rrect.size.width > areaThreshold || rrect.size.height > areaThreshold) 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); //<2F>ж<EFBFBD><D0B6>Ƿ<EFBFBD><C7B7><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD> 1<><31><EFBFBD>ڣ<EFBFBD>0<EFBFBD><30><EFBFBD>ϣ<EFBFBD>-1<><31><EFBFBD><EFBFBD>
double temp2 = pointPolygonTest(vertices_roi2, p, false); //<2F>ж<EFBFBD><D0B6>Ƿ<EFBFBD><C7B7>ڱ<EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31><EFBFBD>ڣ<EFBFBD>0<EFBFBD><30><EFBFBD>ϣ<EFBFBD>-1<><31><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><E2A3AC><EFBFBD>߱<EFBFBD>Ե<EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD>Ϊ<EFBFBD>ǿ׶<C7BF>
if (temp1 < 0 || temp2 > 0)
{
enabled = false;
break;
}
}
if (enabled)
hole_contours.push_back(contours[i]);
}
return hole_contours;
}
cv::Scalar CImageOutHole::getBackGroudColor(const cv::Mat &image, const std::vector<cv::Point> pixelPoints)
{
if (pixelPoints.empty()) return cv::Scalar(255, 255, 255);
int channels = image.channels();
int temp[3] = { 0 };
for (size_t i = 0, length = pixelPoints.size(); i < length; ++i)
{
int x = cv::min(cv::max(0, pixelPoints[i].x), image.cols - 1);
int y = cv::min(cv::max(0, pixelPoints[i].y), image.rows - 1);
const unsigned char* ptr = image.ptr(y, x);
for (int j = 0; j < channels; ++j)
temp[j] += ptr[j];
}
return cv::Scalar(temp[0] / pixelPoints.size(), temp[1] / pixelPoints.size(), temp[2] / pixelPoints.size());
}