GrpcPrint/PrintS/RecoatCheck/RecoatCheck.cpp

1597 lines
57 KiB
C++
Raw Normal View History

#include <algorithm>
#include "../external/imgui/imgui.h"
#include "RecoatCheck.h"
#include "../LanguageManager.h"
#include "../Logger.h"
#include "../job/VolumeCalc.h"
#include "../config/ConfigManager.h"
#include "../additional/Calibration.h"
#define CLIPPER_SCALE 1.0e9
RecoatCheck::RecoatCheck()
:m_DispTex(0)
, m_CaptureTex(0)
{
InitializeCriticalSection(&cs);
InitializeCriticalSection(&disp_cs);
m_DstWidth = 800;
m_DstHeight = 800;
m_WarpDst = cv::Mat(cv::Size(m_DstWidth, m_DstHeight), CV_8U);
m_ExtCfg = ConfigManager::GetInstance()->GetExtCfg();
m_CameraCalibrationCfg = ConfigManager::GetInstance()->GetCameraCalibrationCfg();
}
RecoatCheck::~RecoatCheck()
{
DeleteCriticalSection(&cs);
DeleteCriticalSection(&disp_cs);
}
float allMasks[5][5] = { { 1, 4, 6, 4, 1 }, //level -- 0
{ -1, -2, 0, 2, 1 }, //edge -- 1
{ -1, 0, 2, 0, -1 }, //spot -- 2
{ -1, 2, 0, -2, 1 }, //wave -- 3
{ 1, -4, 6, -4, 1 } }; //ripple -- 4
cv::Mat RecoatCheck::generateMask2D(float allMasks[5][5], int row1, int row2)
{
cv::Mat mask = cv::Mat::zeros(5, 5, CV_32F);
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
mask.at<float>(i, j) = (float)(allMasks[row2][j] * allMasks[row1][i]);
}
}
return mask;
}
bool RecoatCheck::CheckOL(MetaData* metadata, unsigned int layer, unsigned char** img, int width, int high)
{
RecoatCheckCfg* rcc = ConfigManager::GetInstance()->GetRecoatCheckCfg();
if (!rcc->m_Enable->GetValue())
return true;
if (!img || width <= 0 || high <= 0)
return true;
cv::Mat image(high, width, CV_8U, *img);
//delete[] * img;
//*img = nullptr;
//Mat mask = imread("E:\\prj\\cv\\cv\\x64\\Release\\mask.bmp", ImreadModes::IMREAD_GRAYSCALE);
//Mat image = imread("E:\\prj\\rc00.bmp", ImreadModes::IMREAD_GRAYSCALE);
cv::Mat mask = cv::Mat::zeros(image.size(), image.type());
// <20><><EFBFBD><EFBFBD> <20>߽<EFBFBD><DFBD><EFBFBD><EFBFBD><EFBFBD>roi<6F><69><EFBFBD><EFBFBD>
vector<vector<cv::Point>> contour;
vector<cv::Point> pts;
pts.push_back(cv::Point(rcc->m_MaskTopLeftX->GetValue(), rcc->m_MaskTopLeftY->GetValue()));
pts.push_back(cv::Point(rcc->m_MaskTopRightX->GetValue(), rcc->m_MaskTopRightY->GetValue()));
pts.push_back(cv::Point(rcc->m_MaskBottomRightX->GetValue(), rcc->m_MaskBottomRightY->GetValue()));
pts.push_back(cv::Point(rcc->m_MaskBottomLeftX->GetValue(), rcc->m_MaskBottomLeftY->GetValue()));
pts.push_back(cv::Point(rcc->m_MaskTopLeftX->GetValue(), rcc->m_MaskTopLeftY->GetValue()));
contour.push_back(pts);
// <20><><EFBFBD><EFBFBD>
drawContours(mask, contour, 0, cv::Scalar::all(255), -1);
//cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE();
//clahe->setClipLimit(1.5);
//cv::Mat dst;
//clahe->apply(image, dst);
cv::Mat bg;
GaussianBlur(image, bg, cv::Size(201, 201), 100);
cv::Scalar m = mean(bg);
divide(image, bg, image, m.val[0]);
bitwise_and(image, mask, image);
//imwrite("ffc.bmp", image);
cv::Point2f srcTri[4];
srcTri[0] = cv::Point2f(rcc->m_MaskTopLeftX->GetValue(), rcc->m_MaskTopLeftY->GetValue());
srcTri[1] = cv::Point2f(rcc->m_MaskTopRightX->GetValue(), rcc->m_MaskTopRightY->GetValue());
srcTri[2] = cv::Point2f(rcc->m_MaskBottomLeftX->GetValue(), rcc->m_MaskBottomLeftY->GetValue());
srcTri[3] = cv::Point2f(rcc->m_MaskBottomRightX->GetValue(), rcc->m_MaskBottomRightY->GetValue());
cv::Point2f dstTri[4];
dstTri[0] = cv::Point2f(rcc->m_TransformTopLeftX->GetValue(), rcc->m_TransformTopLeftY->GetValue());
dstTri[1] = cv::Point2f(rcc->m_TransformTopRightX->GetValue(), rcc->m_TransformTopRightY->GetValue());
dstTri[2] = cv::Point2f(rcc->m_TransformBottomLeftX->GetValue(), rcc->m_TransformBottomLeftY->GetValue());
dstTri[3] = cv::Point2f(rcc->m_TransformBottomRightX->GetValue(), rcc->m_TransformBottomRightY->GetValue());
cv::Mat warp_mat = getPerspectiveTransform(srcTri, dstTri);
dstTri[0] = cv::Point2f(0.f, 0.f);
dstTri[1] = cv::Point2f(800.f, 0.f);
dstTri[2] = cv::Point2f(0.f, 800.f);
dstTri[3] = cv::Point2f(800.f, 800.f);
cv::Mat disp_warp_mat = getPerspectiveTransform(srcTri, dstTri);
cv::Mat laws_mask = generateMask2D(allMasks, 1, 0);
cv::Mat dst;
cv::blur(image, dst, cv::Size(3, 3));
cv::filter2D(dst, dst, -1, laws_mask);
//dst = dst / 3.0;
//GaussianBlur(dst, dst, Size(13, 13), 10);
cv::blur(dst, dst, cv::Size(13, 13));
threshold(dst, dst, rcc->m_BinaryThreshold->GetValue(), 255, cv::ThresholdTypes::THRESH_BINARY);
//Mat element2 = getStructuringElement( MorphShapes::MORPH_ELLIPSE, Size( 2*10 + 1, 2*10+1 ), Point( /*morph_size, morph_size*/ ) );
//morphologyEx(dst, dst, MORPH_DILATE, element2);
//morphologyEx(dst, dst, MORPH_ERODE, element2);
//Mat element3 = getStructuringElement( MorphShapes::MORPH_ELLIPSE, Size( 2*5 + 1, 2*5+1 ), Point( /*morph_size, morph_size*/ ) );
//morphologyEx(dst, dst, MORPH_OPEN, element3);
if (isNeedDisp) {
EnterCriticalSection(&disp_cs);
cv::warpPerspective(dst, m_WarpDst, disp_warp_mat, m_WarpDst.size());
vector<vector<cv::Point>> disp_contours;
vector<cv::Vec4i> disp_hierarchy;
cv::findContours(m_WarpDst, disp_contours, disp_hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE, cv::Point());
cv::warpPerspective(image, m_WarpDst, disp_warp_mat, m_WarpDst.size());
cv::drawContours(m_WarpDst, disp_contours, -1, cv::Scalar(255), 2);
isDispUpdated = true;
LeaveCriticalSection(&disp_cs);
}
//Mat imageContours;
//warp_dst.copyTo(imageContours);
//warpAffine(dst, warp_dst, warp_mat, warp_dst.size());
//imshow("image", warp_dst);
EnterCriticalSection(&cs);
realc.clear();
vector<vector<cv::Point>> contours;
vector<cv::Vec4i> hierarchy;
cv::findContours(dst, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE, cv::Point());
for (size_t i = 0; i < contours.size(); i++) {
vector<cv::Point2f> tmp;
for (size_t j = 0; j < contours[i].size(); j++) {
tmp.emplace_back(contours[i][j].x, contours[i][j].y);
}
realc.push_back(vector<cv::Point2f>());
perspectiveTransform(tmp, realc[i], warp_mat);
}
m_Solutions.clear();
LeaveCriticalSection(&cs);
if (metadata && layer > 0) {
GetLayerBorders(metadata, layer, m_Borders);
bool flag = RecoatCheckByContoursIntersect(m_Borders, realc, metadata);
EnterCriticalSection(&cs);
isDrawed = false;
LeaveCriticalSection(&cs);
return flag;
}
else {
return true;
}
}
void RecoatCheck::DrawPoly(vl::ref<vl::VectorGraphics> vg)
{
EnterCriticalSection(&cs);
if (vg && realc.size() > 0 && !isDrawed) {
isDrawed = true;
vg->clear();
vg->startDrawing();
vg->setColor(vl::yellow);
vg->setLineWidth(1.0f);
vg->currentEffect()->shader()->disable(vl::EEnable::EN_LINE_SMOOTH);
for (size_t i = 0; i < realc.size(); i++) {
vector<vl::dvec2> poly;
for (size_t j = 0; j < realc[i].size(); j++) {
poly.emplace_back(realc[i][j].x, realc[i][j].y);
}
poly.emplace_back(realc[i][0].x, realc[i][0].y);
vg->drawLineStrip(poly);
}
vg->setColor(vl::red);
vg->setLineWidth(2.0f);
vg->currentEffect()->shader()->disable(vl::EEnable::EN_LINE_SMOOTH);
for (size_t i = 0; i < m_Solutions.size(); i++) {
vector<vl::dvec2> poly;
for (size_t j = 0; j < m_Solutions[i].size(); j++) {
poly.emplace_back(m_Solutions[i][j].X / CLIPPER_SCALE, m_Solutions[i][j].Y / CLIPPER_SCALE);
}
poly.emplace_back(m_Solutions[i][0].X / CLIPPER_SCALE, m_Solutions[i][0].Y / CLIPPER_SCALE);
vg->drawLineStrip(poly);
}
vg->endDrawing();
}
LeaveCriticalSection(&cs);
}
std::vector<int> RecoatCheck::GetLayerBorders(MetaData* metadata, unsigned int layer, PolyTree& m_Borders)
{
if (metadata == nullptr || layer > metadata->GetLayerCount())
return vector<int>();
MetaData::Layer* player = metadata->GetCurrentLayer();
if (player == NULL || player->index != layer) {
if (metadata->LoadLayerByIndex(layer))
player = metadata->GetCurrentLayer();
else
return vector<int>();
}
vector<int> noBorderParts;
m_Borders.Clear();
vector<BPBinary::BinDataBlock*> m_BordersDB;
vector<vector<cv::Point>> m_WorkBorders;
for (std::map<int, MetaData::DataBlockList*>::iterator it = player->data_blocks_map.begin(); it != player->data_blocks_map.end(); it++) {
int partid = it->first;
MetaData::Part* part = metadata->GetPart(partid);
if (!part->print_enable)
continue;
MetaData::DataBlockList* datas = it->second;
if (datas == NULL)continue;
bool noBorder = true;
for (size_t i = 0; i < datas->size(); ++i) {
BPBinary::BinDataBlock* pdb = metadata->GetDataBlock((*datas)[i]);
if (!pdb)break;
MetaData::ParameterSet* ps = metadata->GetParameterSet((*datas)[i]->references->process);
if (!ps)continue;
if (ps->set_type == "Border" || ps->set_type == "BorderUp" || ps->set_type == "BorderDown" ||
ps->set_type == "InBorder" || ps->set_type == "UpBorder" || ps->set_type == "DownBorder" ||
ps->set_type == "InBorderJ" || ps->set_type == "DownBorderJ" || ps->set_type == "UpBorderJ") {
m_BordersDB.push_back(pdb);
noBorder = false;
}
}
if (noBorder) {
noBorderParts.push_back(part->id);
}
}
PolyTree tmp;
for (auto db : m_BordersDB) {
for (size_t i = 0; i < db->point_indexs.size(); i++) {
BPBinary::ChainPoint* point = (BPBinary::ChainPoint*)db->point_indexs[i];
PolyNode* poly = new PolyNode;
for (unsigned int k = 0; k < point->points.size(); ++k) {
poly->Contour.emplace_back(static_cast<cInt>(point->points[k]->x * CLIPPER_SCALE), static_cast<cInt>(point->points[k]->y * CLIPPER_SCALE));
}
if (poly->Contour.front() == poly->Contour.back()) {
m_Borders.Childs.push_back(poly);
m_Borders.AllNodes.push_back(poly);
}
else {
tmp.Childs.push_back(poly);
}
}
}
#if 0
for (int i = 0; i < tmp.ChildCount(); i++) {
char buf[1024];
sprintf_s(buf, "#index:%d, cnt:%zd\n", i, tmp.Childs[i]->Contour.size());
OutputDebugStringA(buf);
for (size_t j = 0; j < tmp.Childs[i]->Contour.size(); j++) {
memset(buf, '\0', 1024);
sprintf_s(buf, "%.10f, %.10f\n", tmp.Childs[i]->Contour[j].X / CLIPPER_SCALE, tmp.Childs[i]->Contour[j].Y / CLIPPER_SCALE);
OutputDebugStringA(buf);
}
OutputDebugStringA("\n\n");
}
#endif
while (tmp.ChildCount() > 0) {
PolyNode* closed = tmp.Childs.front();
tmp.Childs.erase(tmp.Childs.begin());
while (closed->Contour.front() != closed->Contour.back()) {
bool poly_found = false;
for (int i = 0; i < tmp.ChildCount(); i++) {
Path& contour = tmp.Childs[i]->Contour;
if (closed->Contour.back() == contour.front()) {
closed->Contour.insert(closed->Contour.end(), contour.begin(), contour.end());
PolyNode* poly = tmp.Childs[i];
tmp.Childs.erase(tmp.Childs.begin() + i);
delete poly;
poly_found = true;
break;
}
else if (closed->Contour.back() == contour.back()) {
reverse(contour.begin(), contour.end());
closed->Contour.insert(closed->Contour.end(), contour.begin(), contour.end());
PolyNode* poly = tmp.Childs[i];
tmp.Childs.erase(tmp.Childs.begin() + i);
delete poly;
poly_found = true;
break;
}
else if (isBetween(contour[0], contour[1], closed->Contour.back())) {
if (contour.size() == 2) {
if (isBetween(closed->Contour.back(), closed->Contour[closed->Contour.size() - 2], contour[0])) {
closed->Contour.push_back(contour[1]);
}
else {
closed->Contour.push_back(contour[0]);
}
}
else {
closed->Contour.insert(closed->Contour.end(), contour.begin() + 1, contour.end());
}
PolyNode* poly = tmp.Childs[i];
tmp.Childs.erase(tmp.Childs.begin() + i);
delete poly;
poly_found = true;
break;
}
else if (isBetween(contour.back(), contour[contour.size() - 2], closed->Contour.back())) {
if (isBetween(closed->Contour.back(), closed->Contour[closed->Contour.size() - 2], contour.back())/* ||
isBetween(contour.back(), contour[contour.size() - 2], closed->Contour[closed->Contour.size() - 2])*/) {
reverse(contour.begin(), contour.end());
closed->Contour.insert(closed->Contour.end(), contour.begin() + 1, contour.end());
}
else {
closed->Contour.push_back(contour.back());
}
PolyNode* poly = tmp.Childs[i];
tmp.Childs.erase(tmp.Childs.begin() + i);
delete poly;
poly_found = true;
break;
}
else {
for (size_t j = 0; j < 10 && j < contour.size() - 1; j++) {
if (isBetween(contour[j], contour[j + 1], closed->Contour.back())) {
if (!isBetween(closed->Contour.back(), closed->Contour[closed->Contour.size() - 2], contour[j + 1]) ||
!isBetween(contour[j], contour[j + 1], closed->Contour[closed->Contour.size() - 2])) {
closed->Contour.insert(closed->Contour.end(), contour.begin() + j + 1, contour.end());
}
else {
reverse(contour.begin(), contour.end());
closed->Contour.insert(closed->Contour.end(), contour.begin() + (contour.size() - j - 1), contour.end());
}
PolyNode* poly = tmp.Childs[i];
tmp.Childs.erase(tmp.Childs.begin() + i);
delete poly;
poly_found = true;
break;
}
}
if (poly_found)
break;
int end_idx = contour.size() - 1;
for (size_t j = 0; j < 10 && j < contour.size() - 1; j++) {
if (isBetween(contour[end_idx - j], contour[end_idx - j - 1], closed->Contour.back())) {
if (!isBetween(closed->Contour.back(), closed->Contour[closed->Contour.size() - 2], contour[end_idx - j - 1]) ||
!isBetween(contour[end_idx - j], contour[end_idx - j - 1], closed->Contour[closed->Contour.size() - 2])) {
reverse(contour.begin(), contour.end());
closed->Contour.insert(closed->Contour.end(), contour.begin() + j + 1, contour.end());
}
else {
closed->Contour.insert(closed->Contour.end(), contour.begin() + (contour.size() - j - 1), contour.end());
}
PolyNode* poly = tmp.Childs[i];
tmp.Childs.erase(tmp.Childs.begin() + i);
delete poly;
poly_found = true;
break;
}
}
if (poly_found)
break;
for (size_t j = 0; j < contour.size() - 1; j++) {
if (isBetween(contour[j], contour[j + 1], closed->Contour.back())) {
if (!isBetween(closed->Contour.back(), closed->Contour[closed->Contour.size() - 2], contour[j + 1]) ||
!isBetween(contour[j], contour[j + 1], closed->Contour[closed->Contour.size() - 2])) {
closed->Contour.insert(closed->Contour.end(), contour.begin() + j + 1, contour.end());
}
else {
reverse(contour.begin(), contour.end());
closed->Contour.insert(closed->Contour.end(), contour.begin() + (contour.size() - j - 1), contour.end());
}
PolyNode* poly = tmp.Childs[i];
tmp.Childs.erase(tmp.Childs.begin() + i);
delete poly;
poly_found = true;
break;
}
}
if (poly_found)
break;
}
}
if (!poly_found)
break;
}
if (closed->Contour.front() == closed->Contour.back()) {
m_Borders.AllNodes.push_back(closed);
m_Borders.Childs.push_back(closed);
}
else {
bool connected = false;
for (size_t j = 0; j < 10 && j < closed->Contour.size() - 1; j++) {
if (isBetween(closed->Contour[j], closed->Contour[j + 1], closed->Contour.back())) {
closed->Contour.erase(closed->Contour.begin(), closed->Contour.begin() + j);
m_Borders.AllNodes.push_back(closed);
m_Borders.Childs.push_back(closed);
connected = true;
break;
}
}
if (!connected) {
closed->Contour.push_back(closed->Contour.front());
m_Borders.AllNodes.push_back(closed);
m_Borders.Childs.push_back(closed);
}
}
}
BuildTree(&m_Borders);
return noBorderParts;
}
bool RecoatCheck::RecoatCheckByContoursIntersect(PolyTree& borders, vector<vector<cv::Point2f>>& uncover, MetaData* metadata)
{
RecoatCheckCfg* rcc = ConfigManager::GetInstance()->GetRecoatCheckCfg();
float xmin = FLT_MAX, xmax = -FLT_MAX, ymin = FLT_MAX, ymax = -FLT_MAX;
MetaData::JobDimensions* dim = metadata->GetJobDimensions();
if (uncover.size() == 0)
return true;
if (!metadata)
return true;
Paths uncovers, untmp;
for (size_t i = 0; i < uncover.size(); i++) {
Path tmp;
for (size_t j = 0; j < uncover[i].size(); j++) {
tmp.emplace_back(uncover[i][j].x * CLIPPER_SCALE, uncover[i][j].y * CLIPPER_SCALE);
xmin = std::min(xmin, uncover[i][j].x);
xmax = std::max(xmax, uncover[i][j].x);
ymin = std::min(ymin, uncover[i][j].y);
ymax = std::max(ymax, uncover[i][j].y);
}
// make sure it is closed
tmp.emplace_back(uncover[i][0].x * CLIPPER_SCALE, uncover[i][0].y * CLIPPER_SCALE);
// ɸѡ<C9B8><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>
if (xmax < dim->xmin || xmin > dim->xmax || ymin > dim->ymax || ymax < dim->ymin)
continue;
untmp.push_back(tmp);
}
SimplifyPolygons(untmp, uncovers);
//double thick = *metadata->GetLayerThickness();
double AreaThreshold = rcc->m_AreaThresholdFactor->GetValue() * CLIPPER_SCALE * CLIPPER_SCALE;
double LenThreshold = rcc->m_LengthThresholdFactor->GetValue() * CLIPPER_SCALE;
for (int i = 0; i < borders.ChildCount(); i++) {
Paths solutions, tmp;
Clipper clp;
//EnterCriticalSection(&cs);
//clp.AddPath(borders.Childs[i]->Contour, ptClip, true);
tmp.push_back(borders.Childs[i]->Contour);
for (int j = 0; j < borders.Childs[i]->ChildCount(); j++) {
//clp.AddPath(borders.Childs[i]->Childs[j]->Contour, ptClip, true);
tmp.push_back(borders.Childs[i]->Childs[j]->Contour);
}
//CleanPolygons(tmp);
SimplifyPolygons(tmp);
//m_Solutions.insert(m_Solutions.end(), tmp.begin(), tmp.end());
//LeaveCriticalSection(&cs);
clp.AddPaths(tmp, ptClip, true);
clp.AddPaths(uncovers, ptSubject, true);
clp.Execute(ctIntersection, solutions);
EnterCriticalSection(&cs);
m_Solutions.insert(m_Solutions.begin(), solutions.begin(), solutions.end());
LeaveCriticalSection(&cs);
if (solutions.size() > rcc->m_PerIslandCntThreshold->GetValue())
return false;
if (solutions.size() > 0) {
for (size_t i = 0; i < solutions.size(); i++) {
double tmp = Area(solutions[i]);
if (tmp > AreaThreshold)
return false;
if (Len(solutions[i]) > LenThreshold)
return false;
}
}
}
return true;
}
double RecoatCheck::Len(Path& p)
{
double len = 0;
if (p.size() < 2)
return 0;
for (size_t i = 0; i < p.size() - 1; i++) {
double tt = (p[i].X - p[i + 1].X) * (p[i].X - p[i + 1].X) + (p[i].Y - p[i + 1].Y) * (p[i].Y - p[i + 1].Y);
len += sqrt((tt < 0.0) ? 0.0 : tt);
}
double tp = (p[0].X - p.back().X) * (p[0].X - p.back().X) + (p[0].Y - p.back().Y) * (p[0].Y - p.back().Y);
len += sqrt((tp < 0.0) ? 0.0 : tp);
return len;
}
void RecoatCheck::BuildTree(PolyTree* node)
{
if (node->ChildCount() < 2)
return;
for (int i = 0; i < node->ChildCount(); i++)
node->Childs[i]->CalcBounds();
unsigned int max_level = 0;
for (int i = 0; i < node->ChildCount(); i++) {
ClipperLib::PolyNode* p0 = node->Childs[i];
for (int j = 0; j < node->ChildCount(); j++) {
if (j == i)
continue;
ClipperLib::PolyNode* p1 = node->Childs[j];
if (p1->IsInside(p0)) {
p1->depth++;
if (p1->depth > max_level)
max_level = p1->depth;
}
}
}
vector<PolyNode*> childs_copy;
childs_copy.insert(childs_copy.begin(), node->Childs.begin(), node->Childs.end());
for (unsigned int i = 1; i <= max_level; i += 2) {
for (size_t j = 0; j < childs_copy.size(); j++) {
if (childs_copy[j]->depth != i)
continue;
PolyNode* pj = childs_copy[j];
if (Orientation(pj->Contour))
ReversePath(pj->Contour);
for (size_t k = 0; k < childs_copy.size(); k++) {
if (childs_copy[k]->depth != i - 1)
continue;
PolyNode* pk = childs_copy[k];
if (!Orientation(pk->Contour))
ReversePath(pk->Contour);
if (pj->IsInside(pk)) {
if (node->ChildCount() > 0) {
vector<PolyNode*>::iterator it = node->Childs.begin();
for (; it != node->Childs.end(); it++) {
if (*it == pj) {
node->Childs.erase(it);
break;
}
}
}
pj->Parent = pk;
pk->Childs.push_back(pj);
break;
}
}
}
}
for (PolyNode* poly : node->Childs) {
if (poly->ChildCount() == 0 && !Orientation(poly->Contour))
ReversePath(poly->Contour);
}
double* bounds = node->GetBounds();
for (PolyNode* poly : node->AllNodes) {
bounds[0] = std::min(bounds[0], poly->GetBounds()[0]);
bounds[1] = std::max(bounds[1], poly->GetBounds()[1]);
bounds[2] = std::min(bounds[2], poly->GetBounds()[2]);
bounds[3] = std::max(bounds[3], poly->GetBounds()[3]);
}
}
bool RecoatCheck::isBetween(IntPoint a, IntPoint b, IntPoint c)
{
double ax = a.X * 1.0e-9;
double ay = a.Y * 1.0e-9;
double bx = b.X * 1.0e-9;
double by = b.Y * 1.0e-9;
double cx = c.X * 1.0e-9;
double cy = c.Y * 1.0e-9;
double actemp = ((cx - ax) * (cx - ax) + (cy - ay) * (cy - ay));
double bctemp = (cx - bx) * (cx - bx) + (cy - by) * (cy - by);
double abtemp = (ax - bx) * (ax - bx) + (ay - by) * (ay - by);
double ac = sqrt((actemp < 0.0f) ? 0.0f : actemp);
double bc = sqrt((bctemp < 0.0f) ? 0.0f : bctemp);
double ab = sqrt((abtemp < 0.0f) ? 0.0f : abtemp);
double delta = abs(ab - (ac + bc));
return delta < 1.0e-9;
#if 0
// if AC is vertical
if (a.X == c.X) return b.X == c.X;
// if AC is horizontal
if (a.Y == c.Y) return b.Y == c.Y;
// match the gradients
return (a.X - c.X) * (a.Y - c.Y) == (c.X - b.X) * (c.Y - b.Y);
#if 0
if (a == c || b == c)
return true;
#endif
cInt crossproduct = (c.Y - a.Y) * (b.X - a.X) - (c.X - a.X) * (b.Y - a.Y);
// compare versus epsilon for floating point values, or != 0 if using integers
double tmp = abs(crossproduct * 1.0e-18);
if (tmp > 2.0e-3)
return false;
cInt dotproduct = (c.X - a.X) * (b.X - a.X) + (c.Y - a.Y) * (b.Y - a.Y);
double ddotproduct = dotproduct * 1.0e-18;
if (ddotproduct < 0)
return false;
cInt squaredlengthba = (b.X - a.X) * (b.X - a.X) + (b.Y - a.Y) * (b.Y - a.Y);
double dsquaredlengthba = squaredlengthba * 1.0e-18;
if (ddotproduct > dsquaredlengthba)
return false;
return true;
#endif
}
double RecoatCheck::Dist(IntPoint a, IntPoint b)
{
double tt = (a.X / CLIPPER_SCALE - b.X / CLIPPER_SCALE) * (a.X / CLIPPER_SCALE - b.X / CLIPPER_SCALE) +
(a.Y / CLIPPER_SCALE - b.Y / CLIPPER_SCALE) * (a.Y / CLIPPER_SCALE - b.Y / CLIPPER_SCALE);
double tmp = sqrt((tt < 0.0) ? 0.0 : tt);
return tmp;
}
//void RecoatCheck::DrawStatus(bool* isShow)
//{
// if (!*isShow) {
// isNeedDisp = false;
// if (m_DispTex > 0) {
// glDeleteTextures(1, &m_DispTex);
// m_DispTex = 0;
// }
// return;
// }
//
// isNeedDisp = true;
// ImGui::Begin(g_LngManager->Cfg_RecoatCheckConfig->ShowText(), isShow, ImGuiWindowFlags_NoDocking);
// //if (ImGui::IsWindowAppearing())
// // isNeedDisp = true;
//
// //if (ImGui::Button("Test")) {
// // Check(nullptr, 0, nullptr, 0, 0);
// //}
// EnterCriticalSection(&disp_cs);
// if (isDispUpdated) {
// isDispUpdated = false;
// if (m_DispTex == 0) {
// glGenTextures(1, &m_DispTex);
// glBindTexture(GL_TEXTURE_2D, m_DispTex);
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_DstWidth, m_DstHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_WarpDst.data);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// glBindTexture(GL_TEXTURE_2D, 0);
// }
// else {
// glBindTexture(GL_TEXTURE_2D, m_DispTex);
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_DstWidth, m_DstHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_WarpDst.data);
// glBindTexture(GL_TEXTURE_2D, 0);
// }
// }
// LeaveCriticalSection(&disp_cs);
//
// ImGui::Image((ImTextureID)m_DispTex, ImVec2(600, 600));
// ImGui::End();
//}
bool RecoatCheck::CheckWP(MetaData* metadata, unsigned int layer, unsigned char** img, int width, int high)
{
MachineCfg* mcfg = ConfigManager::GetInstance()->GetMachineCfg();
RecoatCheckCfg* rcc = ConfigManager::GetInstance()->GetRecoatCheckCfg();
if (!rcc->m_Enable->GetValue())
return true;
if (!img || width <= 0 || high <= 0)
return true;
cv::Mat image(high, width, CV_8U, *img);
switch (m_ExtCfg->m_ShowImageRotateAngle)
{
case ExtCfg::Angle_0: {
}break;
case ExtCfg::Angle_90: {
cv::rotate(image, image, cv::ROTATE_90_COUNTERCLOCKWISE);
}break;
case ExtCfg::Angle_180: {
cv::rotate(image, image, cv::ROTATE_180);
}break;
case ExtCfg::Angle_270: {
cv::rotate(image, image, cv::ROTATE_90_CLOCKWISE);
}break;
}
cv::Mat mask = cv::Mat::zeros(image.size(), image.type());
vector<vector<cv::Point>> contour;
vector<cv::Point> pts;
pts.push_back(cv::Point(rcc->m_MaskTopLeftX->GetValue(), rcc->m_MaskTopLeftY->GetValue()));
pts.push_back(cv::Point(rcc->m_MaskTopRightX->GetValue(), rcc->m_MaskTopRightY->GetValue()));
pts.push_back(cv::Point(rcc->m_MaskBottomRightX->GetValue(), rcc->m_MaskBottomRightY->GetValue()));
pts.push_back(cv::Point(rcc->m_MaskBottomLeftX->GetValue(), rcc->m_MaskBottomLeftY->GetValue()));
pts.push_back(cv::Point(rcc->m_MaskTopLeftX->GetValue(), rcc->m_MaskTopLeftY->GetValue()));
contour.push_back(pts);
drawContours(mask, contour, 0, cv::Scalar::all(255), -1);
unsigned char lut[256];
double gamma = 0.5;
for (int i = 0; i < 256; i++)
{
lut[i] = cv::saturate_cast<uchar>(pow((float)i / 255.0, gamma) * 255.0f);
}
cv::MatIterator_<uchar> it = image.begin<uchar>();
cv::MatIterator_<uchar> end = image.end<uchar>();
while (it != end)
{
*it = lut[(*it)];
it++;
}
//imwrite("g:/testimage/ffc0.bmp", image);
//Mat bg;
//GaussianBlur(image, bg, Size(201, 201), 100);
//Scalar m = mean(image);
//divide(image, bg, image, m.val[0]);
//equalizeHist(image, image);
bitwise_and(image, mask, image);
// imwrite("g:/testimage/ffc1.bmp", image);
cv::Point2f srcTri[4];
srcTri[0] = cv::Point2f(rcc->m_MaskTopLeftX->GetValue(), rcc->m_MaskTopLeftY->GetValue());
srcTri[1] = cv::Point2f(rcc->m_MaskTopRightX->GetValue(), rcc->m_MaskTopRightY->GetValue());
srcTri[2] = cv::Point2f(rcc->m_MaskBottomRightX->GetValue(), rcc->m_MaskBottomRightY->GetValue());
srcTri[3] = cv::Point2f(rcc->m_MaskBottomLeftX->GetValue(), rcc->m_MaskBottomLeftY->GetValue());
cv::Point2f tempTri[4], dstTri[4];
// Mat warp_mat = getPerspectiveTransform(srcTri, dstTri);
2024-05-30 11:18:10 +08:00
float plr = (float)mcfg->m_PlatformLength->GetValue() / mcfg->m_PlatformWidth->GetValue();
int wwidth = 1000;
int wheight = 1000.0f / plr;
2024-05-30 11:18:10 +08:00
float wr = 1000.0 / mcfg->m_PlatformLength->GetValue();
float wh = (float)wheight / mcfg->m_PlatformWidth->GetValue();
tempTri[0] = cv::Point2f(0.0f, 0.0f);
tempTri[1] = cv::Point2f(wwidth, 0.0f);
tempTri[2] = cv::Point2f(wwidth, wheight);
tempTri[3] = cv::Point2f(0.0f, wheight);
cv::Mat warp_mat = getPerspectiveTransform(srcTri, tempTri);
dstTri[0] = cv::Point2f(0.f, 0.f);
dstTri[1] = cv::Point2f(m_DstWidth, 0.f);
dstTri[2] = cv::Point2f(m_DstWidth, m_DstHeight);
dstTri[3] = cv::Point2f(0.0f, m_DstHeight);
cv::Mat disp_warp_mat = getPerspectiveTransform(tempTri, dstTri);
cv::Mat imageTemp(cv::Size(wwidth, wheight), CV_8U);
warpPerspective(image, imageTemp, warp_mat, imageTemp.size());
//imwrite("g:/testimage/ffc3.bmp", imageTemp);
cv::Mat laws_mask = generateMask2D(allMasks, 1, 0);
//boxFilter(loc, loc,-1, Size(3, 3));
//imwrite("g:/testimage/ffc2-1.bmp", loc);
//equalizeHist(imageTemp, imageTemp);
//imwrite("g:/testimage/ffc2-1.bmp", imageTemp);
/*Mat imageTemp2(Size(wwidth, wheight), CV_8U);
for (int i = 0; i < imageTemp.rows; i++)
{
for (int j = 0; j < imageTemp.cols; j++)
{
imageTemp2.at<unsigned char>(i, j) = log(1 + imageTemp.at<unsigned char>(i, j));
}
}
normalize(imageTemp2, imageTemp2, 0, 255, NORM_MINMAX);*/
//imwrite("g:/testimage/ffc3.bmp", imageTemp);
//GaussianBlur(imageLog, imageLog, Size(5, 5), 0, 0);
cv::Mat dst;
//blur(imageTemp, dst, Size(3, 3));
cv::boxFilter(imageTemp, dst, -1, cv::Size(3, 3));
//
//boxFilter(imageTemp, dst,-1, Size(3, 3));
//imwrite("g:/testimage/ffc3-1.bmp", dst);
//Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
//morphologyEx(imageTemp, dst, MORPH_CLOSE, element);
//blur(dst, dst, Size(3, 3));
//filter2D(dst, dst, -1, laws_mask);
//blur(dst, dst, Size(7, 7));
//imwrite("g:/testimage/ffc4.bmp", imageTemp);
cv::Mat mat_mean, mat_stddev;
double avg = 0.0, sd = 0.0;
cv::Mat upPart(cv::Size(dst.size().width, dst.size().height / 2), CV_8U);
if (rcc->m_IsUpPartNotLight->GetValue()) {
for (int i = 0; i < upPart.rows; i++) {
for (int j = 0; j < upPart.cols; j++) {
upPart.at<unsigned char>(i, j) = dst.at<unsigned char>(i, j);
}
}
//GaussianBlur(upPart, upPart, Size(5, 5), 0, 0);
cv::filter2D(upPart, upPart, -1, laws_mask);
cv::blur(upPart, upPart, cv::Size(7, 7));
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(8, 8));
morphologyEx(upPart, upPart, cv::MORPH_CLOSE, element);
morphologyEx(upPart, upPart, cv::MORPH_OPEN, element);
//imwrite("g:/testimage/ffc3-2.bmp", upPart);
meanStdDev(upPart, mat_mean, mat_stddev);
avg = mat_mean.at<double>(0, 0);
sd = mat_stddev.at<double>(0, 0);
int bt = avg + sd + 10;
if (bt > 200)bt = 200;
if (bt < rcc->m_BinaryThreshold->GetValue())bt = rcc->m_BinaryThreshold->GetValue();
threshold(upPart, upPart, bt, 255, cv::ThresholdTypes::THRESH_BINARY);
}
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(8, 8));
morphologyEx(dst, dst, cv::MORPH_CLOSE, element);
//imwrite("g:/testimage/ffc4.bmp", upPart);
meanStdDev(dst, mat_mean, mat_stddev);
avg = mat_mean.at<double>(0, 0);
sd = mat_stddev.at<double>(0, 0);
int bt = avg + sd + 20;
if (bt > 200)bt = 200;
if (bt < rcc->m_BinaryThreshold->GetValue())bt = rcc->m_BinaryThreshold->GetValue();
threshold(dst, dst, bt, 255, cv::ThresholdTypes::THRESH_BINARY);
if (rcc->m_IsUpPartNotLight->GetValue()) {
for (int i = 0; i < upPart.rows; i++) {
for (int j = 0; j < upPart.cols; j++) {
dst.at<unsigned char>(i, j) = upPart.at<unsigned char>(i, j);
}
}
}
//filter2D(dst, dst, -1, laws_mask);
//imwrite("g:/testimage/ffc4-1.bmp", dst);
//imwrite("g:/testimage/ffc4-1.bmp", dst);
//s = s < 130 ? s + 40 : s;
//Mat imageTemp2(dst.size(), CV_8U);
//threshold(dst, dst, avg+sd, 255, ThresholdTypes::THRESH_BINARY);
//threshold(dst, dst, rcc->m_BinaryThreshold, 255, ThresholdTypes::THRESH_BINARY);
//imwrite("g:/testimage/ffc5.bmp", dst);
//if (isNeedDisp) {
EnterCriticalSection(&disp_cs);
vector<vector<cv::Point>> disp_contours;
vector<cv::Vec4i> disp_hierarchy;
findContours(dst, disp_contours, disp_hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE, cv::Point());
//warpPerspective(image, warp_dst, disp_warp_mat, warp_dst.size());
drawContours(imageTemp, disp_contours, -1, cv::Scalar(255), 2);
warpPerspective(imageTemp, m_WarpDst, disp_warp_mat, m_WarpDst.size());
isDispUpdated = true;
LeaveCriticalSection(&disp_cs);
//}
if (metadata && layer > 0) {
if (metadata == nullptr || layer > metadata->GetLayerCount())return true;
MetaData::Layer* player = metadata->GetCurrentLayer();
if (player == NULL || player->index != layer) {
if (metadata->LoadLayerByIndex(layer))
player = metadata->GetCurrentLayer();
else
return true;
}
2024-05-30 11:18:10 +08:00
float halfWidth = (float)mcfg->m_PlatformLength->GetValue() / 2.0f;
float halfHigh = (float)mcfg->m_PlatformWidth->GetValue() / 2.0f;
//imwrite("g:/testimage/ffc8.bmp", dataimg);
vector<cv::Vec4i> disp_hierarchy;
vector<vector<cv::Point>> disp_contours;
MetaData::JobDimensions* dim = metadata->GetJobDimensions();
int xmin_m2 = (halfWidth + dim->xmin) * wr;
int xmax_m2 = (halfWidth + dim->xmax) * wr;
int ymin_m2 = (halfHigh - dim->ymax) * wh;
int ymax_m2 = (halfHigh - dim->ymin) * wh;
cv::Mat mask2 = cv::Mat::zeros(dst.size(), dst.type());
vector<vector<cv::Point>> contour2;
vector<cv::Point> pts2;
pts2.push_back(cv::Point(xmin_m2, ymin_m2));
pts2.push_back(cv::Point(xmax_m2, ymin_m2));
pts2.push_back(cv::Point(xmax_m2, ymax_m2));
pts2.push_back(cv::Point(xmin_m2, ymax_m2));
pts2.push_back(cv::Point(xmin_m2, ymin_m2));
contour2.push_back(pts2);
drawContours(mask2, contour2, 0, cv::Scalar::all(255), -1);
//imwrite("g:/testimage/ffc9.bmp", mask2);
bitwise_and(dst, mask2, dst);
mask2.release();
//imwrite("g:/testimage/ffc9-1.bmp", dst);
findContours(dst, disp_contours, disp_hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
double area = 0.0f;
for (size_t i = 0; i < disp_contours.size(); i++) {
area += contourArea(disp_contours[i]);
}
//drawContours(imageTemp, disp_contours, -1, Scalar(100), 2);
//imwrite("g:/testimage/ffc9-1.bmp", imageTemp);
float dotWidth = 0.0f;
vector<BPBinary::BinDataBlock*> m_HatchingDB;
vector<BPBinary::BinDataBlock*> m_SupportDB;
metadata->LockMainDB();
for (std::map<int, MetaData::DataBlockList*>::iterator it = player->data_blocks_map.begin(); it != player->data_blocks_map.end(); it++) {
int partid = it->first;
MetaData::Part* part = metadata->GetPart(partid);
if (!part->print_enable)
continue;
MetaData::DataBlockList* datas = it->second;
if (datas == NULL)continue;
for (unsigned int i = 0; i < datas->size(); ++i) {
BPBinary::BinDataBlock* pdb = metadata->GetDataBlock((*datas)[i]);
if (!pdb)break;
MetaData::ParameterSet* ps = metadata->GetParameterSet((*datas)[i]->references->process);
if (!ps) {
continue;
}
if (ps->set_type.find("Hatching") != ps->set_type.npos)
{
if (pdb->type == BIN_VECTOR) {
m_HatchingDB.push_back(pdb);
}
}
else if (ps->set_type.find("Support") != ps->set_type.npos) {
m_SupportDB.push_back(pdb);
}
}
}
int calcCount = 0;
vector<CalcVar> calcV;
float AreaSum = 0.0f;
for (size_t i = 0; i < m_HatchingDB.size(); i++) {
for (size_t j = 0; j < m_HatchingDB[i]->point_indexs.size(); ++j) {
BPBinary::VectorPoint* pvp = (BPBinary::VectorPoint*)m_HatchingDB[i]->point_indexs[j];
CalcVar cv;
cv.difx = pvp->x2 - pvp->x1;
cv.dify = pvp->y2 - pvp->y1;
cv.a = -(pvp->y2 - pvp->y1);
cv.b = pvp->x2 - pvp->x1;
cv.c = (pvp->y2 - pvp->y1) * pvp->x1 - (pvp->x2 - pvp->x1) * pvp->y1;
calcV.push_back(cv);
calcCount++;
if (calcCount >= 10)break;
}
if (calcCount >= 10)break;
}
metadata->UnLockMainDB();
if (calcV.size() < 10) {
dotWidth = 1.0f;
}
else {
CalcVar preV = calcV[0];
float disSum = 0.0f;
int count = 0;
float maxcalc = -FLT_MAX;
float mincalc = FLT_MAX;
for (size_t i = 1; i < calcV.size(); i++) {
CalcVar tempV = calcV[i];
float value = abs((preV.difx * tempV.dify) - (preV.dify * tempV.difx));
if (value < 0.01f) {
float calcT = preV.a * preV.a + preV.b * preV.b;
if (calcT > 0.0f) {
float calcSqr = sqrt(calcT);
if (calcSqr != 0.0f) {
float dis = abs(preV.c - preV.b * tempV.c / tempV.b) / calcSqr;
disSum += dis;
count++;
if (dis > maxcalc)maxcalc = dis;
if (dis < mincalc)mincalc = dis;
}
else {
preV = tempV;
continue;
}
}
else {
preV = tempV;
continue;
}
}
preV = tempV;
}
if (count >= 3) {
disSum -= maxcalc;
disSum -= mincalc;
dotWidth = disSum / (count - 2);
}
else {
dotWidth = 1.0f;
}
}
metadata->LockMainDB();
for (size_t i = 0; i < m_HatchingDB.size(); i++) {
for (size_t j = 0; j < m_HatchingDB[i]->point_indexs.size(); ++j) {
BPBinary::VectorPoint* pvp = (BPBinary::VectorPoint*)m_HatchingDB[i]->point_indexs[j];
float dsq = (pvp->x1 - pvp->x2) * (pvp->x1 - pvp->x2) + (pvp->y1 - pvp->y2) * (pvp->y1 - pvp->y2);
if (dsq > 0.0f) {
float dis = sqrt(dsq);
AreaSum = AreaSum + (dis * dotWidth);
}
}
}
for (size_t i = 0; i < m_SupportDB.size(); i++) {
BPBinary::BinDataBlock* pdb = m_SupportDB[i];
if (pdb->type == BIN_VECTOR) {
for (size_t j = 0; j < m_SupportDB[i]->point_indexs.size(); ++j) {
BPBinary::VectorPoint* pvp = (BPBinary::VectorPoint*)m_SupportDB[i]->point_indexs[j];
float dsq = (pvp->x1 - pvp->x2) * (pvp->x1 - pvp->x2) + (pvp->y1 - pvp->y2) * (pvp->y1 - pvp->y2);
if (dsq > 0.0f) {
float dis = sqrt(dsq);
AreaSum = AreaSum + (dis * dotWidth);
}
}
}
else if (pdb->type == BIN_CHAIN) {
for (unsigned int j = 0; j < pdb->point_indexs.size(); ++j) {
BPBinary::ChainPoint* point = (BPBinary::ChainPoint*)pdb->point_indexs[j];
if (point->points.empty())continue;
float prex = point->points[0]->x;
float prey = point->points[0]->y;
for (unsigned int k = 1; k < point->points.size(); ++k) {
float x = point->points[k]->x;
float y = point->points[k]->y;
float dsq = (prex - x) * (prex - x) + (prey - y) * (prey - y);
if (dsq > 0.0f) {
float dis = sqrt(dsq);
AreaSum = AreaSum + (dis * dotWidth);
}
prex = x;
prey = y;
}
}
}
}
metadata->UnLockMainDB();
/*GetLayerBorders(metadata, layer, m_Borders);
Paths tmp_paths;
PolyTreeToPaths(m_Borders, tmp_paths);
ClipperLib::ClipperOffset co;
co.AddPaths(tmp_paths, ClipperLib::jtMiter, ClipperLib::etClosedPolygon);
co.MiterLimit = 1.2;
co.ArcTolerance = 0.25 * CLIPPER_SCALE;
m_Borders.Clear();
co.Execute(m_Borders, 0.03 * CLIPPER_SCALE);
double AreaSum = 0.0f;
for (PolyNode* pn : m_Borders.AllNodes) {
AreaSum += Area(pn->Contour);
}*/
AreaSum = AreaSum * wh * wr;
if (AreaSum == 0.0f) {
return true;
}
float areaRat = area / AreaSum * 100.0f;
if (areaRat > rcc->m_UncoverPercentage->GetValue())
{
return false;
}
else return true;
}
else return true;
}
bool RecoatCheck::CheckWP2(MetaData* metadata, unsigned int layer)
{
MachineCfg* mcfg = ConfigManager::GetInstance()->GetMachineCfg();
RecoatCheckCfg* rcc = ConfigManager::GetInstance()->GetRecoatCheckCfg();
if (!rcc->m_Enable->GetValue())return true;
2024-05-31 11:49:20 +08:00
if (m_CameraCalibrationCfg->m_CameraMatrix00->GetValue() == 0.0 || !Calibration::m_CoverImage) {
return true;
}
int width = 0, high = 0, datasize = 0;
m_Camera->GetOriginSize(width, high, datasize);
//width = 3840; high = 2748; datasize = width*high;
if (datasize <= 0 || width <= 0 || high <= 0)return true;
unsigned char* img = new unsigned char[datasize];
if (!m_Camera->GetRawImage(img))
{
if (img)delete[] img;
return true;
}
cv::Mat image(high, width, CV_8U, img);
//cv::Mat image = cv::imread("g:/testimage/1.bmp");
//cv::cvtColor(image, image, 11);
switch (m_ExtCfg->m_ShowImageRotateAngle)
{
case ExtCfg::Angle_0: {
}break;
case ExtCfg::Angle_90: {
cv::rotate(image, image, cv::ROTATE_90_COUNTERCLOCKWISE);
}break;
case ExtCfg::Angle_180: {
cv::rotate(image, image, cv::ROTATE_180);
}break;
case ExtCfg::Angle_270: {
cv::rotate(image, image, cv::ROTATE_90_CLOCKWISE);
}break;
}
//g_log->TraceInfo("divide");
cv::Mat divImage;
cv::Scalar partMean = cv::mean(image);
cv::divide(image, Calibration::m_CoverImage->m_ImageMat, divImage, partMean.val[0]);
//image.release();
//cv::imwrite("g:/testimage/div.bmp", divImage);
//g_log->TraceInfo("release");
cv::Mat divImage2;
cv::Scalar partMean2 = cv::mean(Calibration::m_CoverImage->m_ImageMat);
cv::divide(Calibration::m_CoverImage->m_ImageMat, Calibration::m_CoverImage->m_ImageMat, divImage2, partMean2.val[0]);
//cv::imwrite("g:/testimage/cc.bmp", divImage2);
//g_log->TraceInfo("divide2");
cv::Mat cameraMatrix = cv::Mat(3, 3, CV_64FC1, cv::Scalar::all(0)); //摄像机内参数矩阵
cv::Mat distCoeffs = cv::Mat(1, 5, CV_64FC1, cv::Scalar::all(0)); //摄像机的5个畸变系数k1,k2,p1,p2,k3
2024-05-31 11:49:20 +08:00
cameraMatrix.at<double>(0, 0) = m_CameraCalibrationCfg->m_CameraMatrix00->GetValue();
cameraMatrix.at<double>(0, 1) = m_CameraCalibrationCfg->m_CameraMatrix01->GetValue();
cameraMatrix.at<double>(0, 2) = m_CameraCalibrationCfg->m_CameraMatrix02->GetValue();
cameraMatrix.at<double>(1, 0) = m_CameraCalibrationCfg->m_CameraMatrix10->GetValue();
cameraMatrix.at<double>(1, 1) = m_CameraCalibrationCfg->m_CameraMatrix11->GetValue();
cameraMatrix.at<double>(1, 2) = m_CameraCalibrationCfg->m_CameraMatrix12->GetValue();
cameraMatrix.at<double>(2, 0) = m_CameraCalibrationCfg->m_CameraMatrix20->GetValue();
cameraMatrix.at<double>(2, 1) = m_CameraCalibrationCfg->m_CameraMatrix21->GetValue();
cameraMatrix.at<double>(2, 2) = m_CameraCalibrationCfg->m_CameraMatrix22->GetValue();
distCoeffs.at<double>(0, 0) = m_CameraCalibrationCfg->m_DistCoeffs0->GetValue();
distCoeffs.at<double>(0, 1) = m_CameraCalibrationCfg->m_DistCoeffs1->GetValue();
distCoeffs.at<double>(0, 2) = m_CameraCalibrationCfg->m_DistCoeffs2->GetValue();
distCoeffs.at<double>(0, 3) = m_CameraCalibrationCfg->m_DistCoeffs3->GetValue();
distCoeffs.at<double>(0, 4) = m_CameraCalibrationCfg->m_DistCoeffs4->GetValue();
cv::Mat calImage;
undistort(divImage, calImage, cameraMatrix, distCoeffs);
//g_log->TraceInfo("undistort");
//cv::imwrite("g:/testimage/cal.bmp", calImage);
cv::Point2f srcTri[4];
2024-05-31 11:49:20 +08:00
srcTri[0] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageTopLeftX->GetValue(), (float)m_CameraCalibrationCfg->m_ImageTopLeftY->GetValue());
srcTri[1] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageTopRightX->GetValue(), (float)m_CameraCalibrationCfg->m_ImageTopRightY->GetValue());
srcTri[2] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageBottomRightX->GetValue(), (float)m_CameraCalibrationCfg->m_ImageBottomRightY->GetValue());
srcTri[3] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageBottomLeftX->GetValue(), (float)m_CameraCalibrationCfg->m_ImageBottomLeftY->GetValue());
cv::Point2f tempTri[4];
int tx = (m_CameraCalibrationCfg->m_PlatformTopRightX->GetValue() - m_CameraCalibrationCfg->m_PlatformTopLeftX->GetValue()) * rcc->m_ImageScale->GetValue();
int ty = (m_CameraCalibrationCfg->m_PlatformTopRightY->GetValue() - m_CameraCalibrationCfg->m_PlatformBottomRightY->GetValue()) * rcc->m_ImageScale->GetValue();
tempTri[0] = cv::Point2f(0.0f, 0.0f);
tempTri[1] = cv::Point2f((float)tx, 0.0f);
tempTri[2] = cv::Point2f((float)tx, (float)ty);
tempTri[3] = cv::Point2f(0.0f, (float)ty);
cv::Mat warp_mat = cv::getPerspectiveTransform(srcTri, tempTri);
cv::Mat wm(cv::Size(tx, ty), CV_8U);
cv::Mat bgFix(cv::Size(tx, ty), CV_8U);
warpPerspective(calImage, wm, warp_mat, wm.size());
//cv::imwrite("g:/testimage/war.bmp", wm);
warpPerspective(divImage2, bgFix, warp_mat, bgFix.size());
//g_log->TraceInfo("warpPerspective");
cv::Mat bg_mean, bg_stddev;
cv::meanStdDev(bgFix, bg_mean, bg_stddev);
double bgGrayAvg = 0.0;
bgGrayAvg = bg_mean.at<double>(0, 0);
bgFix.release();
cv::Mat dst;
cv::boxFilter(wm, dst, -1, cv::Size(3, 3));
cv::MatIterator_<uchar> it = dst.begin<uchar>();
cv::MatIterator_<uchar> end = dst.end<uchar>();
double area = 0.0;
while (it != end)
{
double gray = *it;
if (gray > bgGrayAvg + rcc->m_GrayOffset->GetValue() || gray < bgGrayAvg - rcc->m_GrayOffset->GetValue()) {
*it = 255;
area += 1.0;
}
else {
*it = 0;
}
it++;
}
//cv::imwrite("g:/testimage/dst.bmp", dst);
//g_log->TraceInfo("bin");
vector<cv::Vec4i> check_hierarchy;
vector<vector<cv::Point>> check_contours;
findContours(dst, check_contours, check_hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
EnterCriticalSection(&disp_cs);
drawContours(wm, check_contours, -1, cv::Scalar(255, 0, 0), 2);
//cv::imwrite("g:/testimage/wm.bmp", wm);
cv::resize(wm, m_WarpDst, m_WarpDst.size());
isDispUpdated = true;
LeaveCriticalSection(&disp_cs);
if (img)delete[] img;
//g_log->TraceInfo("countarea");
int imageScale = rcc->m_ImageScale->GetValue();
double realArea = area / imageScale / imageScale;
if (realArea > 2500)return false;
if (metadata && layer > 0) {
if (metadata == nullptr || layer > metadata->GetLayerCount())return true;
MetaData::Layer* player = metadata->GetCurrentLayer();
if (player == NULL || player->index != layer) {
if (metadata->LoadLayerByIndex(layer))
player = metadata->GetCurrentLayer();
else
return true;
}
float halfWidth = (float)(m_CameraCalibrationCfg->m_PlatformTopRightX->GetValue() - m_CameraCalibrationCfg->m_PlatformTopLeftX->GetValue()) * imageScale / 2.0f;
float halfHigh = (float)(m_CameraCalibrationCfg->m_PlatformTopRightY->GetValue() - m_CameraCalibrationCfg->m_PlatformBottomRightY->GetValue()) * imageScale / 2.0f;
map<int, RecoatCheckInfo*> infos;
metadata->LockMainDB();
for (std::map<int, MetaData::DataBlockList*>::iterator it = player->data_blocks_map.begin(); it != player->data_blocks_map.end(); it++) {
int partid = it->first;
MetaData::Part* part = metadata->GetPart(partid);
if (!part->print_enable)
continue;
MetaData::DataBlockList* datas = it->second;
if (datas == NULL)continue;
float dotWidth = 0.0f;
vector<BPBinary::BinDataBlock*> hatchingDB;
vector<BPBinary::BinDataBlock*> supportDB;
RecoatCheckInfo* info = new RecoatCheckInfo();
for (unsigned int i = 0; i < datas->size(); ++i) {
BPBinary::BinDataBlock* pdb = metadata->GetDataBlock((*datas)[i]);
if (!pdb)break;
MetaData::ParameterSet* ps = metadata->GetParameterSet((*datas)[i]->references->process);
if (!ps) {
continue;
}
if (ps->set_type.find("Hatching") != ps->set_type.npos)
{
if (pdb->type == BIN_VECTOR) {
hatchingDB.push_back(pdb);
}
}
else if (ps->set_type.find("Support") != ps->set_type.npos) {
supportDB.push_back(pdb);
}
}
int calcCount = 0;
vector<CalcVar> calcV;
float AreaSum = 0.0f;
for (size_t i = 0; i < hatchingDB.size(); i++) {
for (size_t j = 0; j < hatchingDB[i]->point_indexs.size(); ++j) {
BPBinary::VectorPoint* pvp = (BPBinary::VectorPoint*)hatchingDB[i]->point_indexs[j];
CalcVar cv;
cv.difx = pvp->x2 - pvp->x1;
cv.dify = pvp->y2 - pvp->y1;
cv.a = -(pvp->y2 - pvp->y1);
cv.b = pvp->x2 - pvp->x1;
cv.c = (pvp->y2 - pvp->y1) * pvp->x1 - (pvp->x2 - pvp->x1) * pvp->y1;
calcV.push_back(cv);
calcCount++;
if (calcCount >= 10)break;
}
if (calcCount >= 10)break;
}
if (calcV.size() < 10) {
dotWidth = 0.1f;
}
else {
CalcVar preV = calcV[0];
float disSum = 0.0f;
int count = 0;
float maxcalc = -FLT_MAX;
float mincalc = FLT_MAX;
for (size_t i = 1; i < calcV.size(); i++) {
CalcVar tempV = calcV[i];
float value = abs((preV.difx * tempV.dify) - (preV.dify * tempV.difx));
if (value < 0.01f) {
float calcT = preV.a * preV.a + preV.b * preV.b;
if (calcT > 0.0f) {
float calcSqr = sqrt(calcT);
if (calcSqr != 0.0f) {
float dis = abs(preV.c - preV.b * tempV.c / tempV.b) / calcSqr;
disSum += dis;
count++;
if (dis > maxcalc)maxcalc = dis;
if (dis < mincalc)mincalc = dis;
}
else {
preV = tempV;
continue;
}
}
else {
preV = tempV;
continue;
}
}
preV = tempV;
}
if (count >= 3) {
disSum -= maxcalc;
disSum -= mincalc;
dotWidth = disSum / (count - 2);
}
else {
dotWidth = 0.1f;
}
}
float xmin = FLT_MAX;
float xmax = -FLT_MAX;
float ymin = FLT_MAX;
float ymax = -FLT_MAX;
for (size_t i = 0; i < hatchingDB.size(); i++) {
for (size_t j = 0; j < hatchingDB[i]->point_indexs.size(); ++j) {
BPBinary::VectorPoint* pvp = (BPBinary::VectorPoint*)hatchingDB[i]->point_indexs[j];
float dsq = (pvp->x1 - pvp->x2) * (pvp->x1 - pvp->x2) + (pvp->y1 - pvp->y2) * (pvp->y1 - pvp->y2);
if (dsq > 0.0f) {
float dis = sqrt(dsq);
AreaSum = AreaSum + (dis * dotWidth);
}
if (xmin > pvp->x1)xmin = pvp->x1;
if (xmin > pvp->x2)xmin = pvp->x2;
if (xmax < pvp->x1)xmax = pvp->x1;
if (xmax < pvp->x2)xmax = pvp->x2;
if (ymin > pvp->y1)ymin = pvp->y1;
if (ymin > pvp->y2)ymin = pvp->y2;
if (ymax < pvp->y1)ymax = pvp->y1;
if (ymax < pvp->y2)ymax = pvp->y2;
}
}
for (size_t i = 0; i < supportDB.size(); i++) {
BPBinary::BinDataBlock* pdb = supportDB[i];
if (pdb->type == BIN_VECTOR) {
for (size_t j = 0; j < supportDB[i]->point_indexs.size(); ++j) {
BPBinary::VectorPoint* pvp = (BPBinary::VectorPoint*)supportDB[i]->point_indexs[j];
float dsq = (pvp->x1 - pvp->x2) * (pvp->x1 - pvp->x2) + (pvp->y1 - pvp->y2) * (pvp->y1 - pvp->y2);
if (dsq > 0.0f) {
float dis = sqrt(dsq);
AreaSum = AreaSum + (dis * dotWidth);
}
if (xmin > pvp->x1)xmin = pvp->x1;
if (xmin > pvp->x2)xmin = pvp->x2;
if (xmax < pvp->x1)xmax = pvp->x1;
if (xmax < pvp->x2)xmax = pvp->x2;
if (ymin > pvp->y1)ymin = pvp->y1;
if (ymin > pvp->y2)ymin = pvp->y2;
if (ymax < pvp->y1)ymax = pvp->y1;
if (ymax < pvp->y2)ymax = pvp->y2;
}
}
else if (pdb->type == BIN_CHAIN) {
for (unsigned int j = 0; j < pdb->point_indexs.size(); ++j) {
BPBinary::ChainPoint* point = (BPBinary::ChainPoint*)pdb->point_indexs[j];
if (point->points.empty())continue;
float prex = point->points[0]->x;
float prey = point->points[0]->y;
for (unsigned int k = 1; k < point->points.size(); ++k) {
float x = point->points[k]->x;
float y = point->points[k]->y;
float dsq = (prex - x) * (prex - x) + (prey - y) * (prey - y);
if (dsq > 0.0f) {
float dis = sqrt(dsq);
AreaSum = AreaSum + (dis * dotWidth);
}
prex = x;
prey = y;
if (xmin > x)xmin = x;
if (xmax < x)xmax = x;
if (ymin > y)ymin = y;
if (ymax < y)ymax = y;
}
}
}
hatchingDB.clear();
}
if (xmin == FLT_MAX)continue;
info->m_PartArea = AreaSum * imageScale * imageScale;
float xminfix = part->partPosBean.m_XOffset + xmin;
float xmaxfix = part->partPosBean.m_XOffset + xmax;
float yminfix = part->partPosBean.m_YOffset + ymin;
float ymaxfix = part->partPosBean.m_YOffset + ymax;
float point1x = (xminfix - part->partPosBean.m_PartCenterX) * cos(part->partPosBean.m_Radians) - (yminfix - part->partPosBean.m_PartCenterY) * sin(part->partPosBean.m_Radians) + part->partPosBean.m_PartCenterX;
float ppint1y = (xminfix - part->partPosBean.m_PartCenterX) * sin(part->partPosBean.m_Radians) + (yminfix - part->partPosBean.m_PartCenterY) * cos(part->partPosBean.m_Radians) + part->partPosBean.m_PartCenterY;
float point2x = (xminfix - part->partPosBean.m_PartCenterX) * cos(part->partPosBean.m_Radians) - (ymaxfix - part->partPosBean.m_PartCenterY) * sin(part->partPosBean.m_Radians) + part->partPosBean.m_PartCenterX;
float ppint2y = (xminfix - part->partPosBean.m_PartCenterX) * sin(part->partPosBean.m_Radians) + (ymaxfix - part->partPosBean.m_PartCenterY) * cos(part->partPosBean.m_Radians) + part->partPosBean.m_PartCenterY;
float point3x = (xmaxfix - part->partPosBean.m_PartCenterX) * cos(part->partPosBean.m_Radians) - (ymaxfix - part->partPosBean.m_PartCenterY) * sin(part->partPosBean.m_Radians) + part->partPosBean.m_PartCenterX;
float ppint3y = (xmaxfix - part->partPosBean.m_PartCenterX) * sin(part->partPosBean.m_Radians) + (ymaxfix - part->partPosBean.m_PartCenterY) * cos(part->partPosBean.m_Radians) + part->partPosBean.m_PartCenterY;
float point4x = (xmaxfix - part->partPosBean.m_PartCenterX) * cos(part->partPosBean.m_Radians) - (yminfix - part->partPosBean.m_PartCenterY) * sin(part->partPosBean.m_Radians) + part->partPosBean.m_PartCenterX;
float ppint4y = (xmaxfix - part->partPosBean.m_PartCenterX) * sin(part->partPosBean.m_Radians) + (yminfix - part->partPosBean.m_PartCenterY) * cos(part->partPosBean.m_Radians) + part->partPosBean.m_PartCenterY;
int ImageScale = imageScale;
vector<cv::Point> points;
points.push_back(cv::Point(point1x * ImageScale + halfWidth, halfHigh - ppint1y * ImageScale));
points.push_back(cv::Point(point2x * ImageScale + halfWidth, halfHigh - ppint2y * ImageScale));
points.push_back(cv::Point(point3x * ImageScale + halfWidth, halfHigh - ppint3y * ImageScale));
points.push_back(cv::Point(point4x * ImageScale + halfWidth, halfHigh - ppint4y * ImageScale));
info->m_Counter.push_back(points);
infos[partid] = info;
}
metadata->UnLockMainDB();
double AreaSum = 0.0;
for (map<int, RecoatCheckInfo*>::iterator it = infos.begin(); it != infos.end(); it++) {
RecoatCheckInfo* info = it->second;
AreaSum += info->m_PartArea;
delete info;
}
infos.clear();
float areaRat = (float)area / AreaSum * 100.0f;
if (areaRat > rcc->m_UncoverPercentage->GetValue())
{
return false;
}
else return true;
}
else return true;
}
void RecoatCheck::TestCheck()
{
if (!m_Camera)return;
if (!m_Camera->IsConnect())return;
MachineCfg* mcfg = ConfigManager::GetInstance()->GetMachineCfg();
RecoatCheckCfg* rcc = ConfigManager::GetInstance()->GetRecoatCheckCfg();
if (!rcc->m_Enable->GetValue())return;
2024-05-31 11:49:20 +08:00
if (m_CameraCalibrationCfg->m_CameraMatrix00->GetValue() == 0.0 || !Calibration::m_CoverImage) {
return;
}
int width = 0, height = 0, datasize = 0;
m_Camera->GetOriginSize(width, height, datasize);
if (datasize == 0)return;
unsigned char* img = new unsigned char[datasize];
if (!m_Camera->GetRawImage(img))
{
if (img)delete[] img;
return;
}
cv::Mat image(height, width, CV_8U, img);
switch (m_ExtCfg->m_ShowImageRotateAngle)
{
case ExtCfg::Angle_0: {
}break;
case ExtCfg::Angle_90: {
cv::rotate(image, image, cv::ROTATE_90_COUNTERCLOCKWISE);
}break;
case ExtCfg::Angle_180: {
cv::rotate(image, image, cv::ROTATE_180);
}break;
case ExtCfg::Angle_270: {
cv::rotate(image, image, cv::ROTATE_90_CLOCKWISE);
}break;
}
cv::Mat divImage;
cv::Scalar partMean = cv::mean(image);
cv::divide(image, Calibration::m_CoverImage->m_ImageMat, divImage, partMean.val[0]);
image.release();
//cv::imwrite("g:/testimage/div.bmp", divImage);
cv::Mat cameraMatrix = cv::Mat(3, 3, CV_64FC1, cv::Scalar::all(0)); //摄像机内参数矩阵
cv::Mat distCoeffs = cv::Mat(1, 5, CV_64FC1, cv::Scalar::all(0)); //摄像机的5个畸变系数k1,k2,p1,p2,k3
2024-05-31 11:49:20 +08:00
cameraMatrix.at<double>(0, 0) = m_CameraCalibrationCfg->m_CameraMatrix00->GetValue();
cameraMatrix.at<double>(0, 1) = m_CameraCalibrationCfg->m_CameraMatrix01->GetValue();
cameraMatrix.at<double>(0, 2) = m_CameraCalibrationCfg->m_CameraMatrix02->GetValue();
cameraMatrix.at<double>(1, 0) = m_CameraCalibrationCfg->m_CameraMatrix10->GetValue();
cameraMatrix.at<double>(1, 1) = m_CameraCalibrationCfg->m_CameraMatrix11->GetValue();
cameraMatrix.at<double>(1, 2) = m_CameraCalibrationCfg->m_CameraMatrix12->GetValue();
cameraMatrix.at<double>(2, 0) = m_CameraCalibrationCfg->m_CameraMatrix20->GetValue();
cameraMatrix.at<double>(2, 1) = m_CameraCalibrationCfg->m_CameraMatrix21->GetValue();
cameraMatrix.at<double>(2, 2) = m_CameraCalibrationCfg->m_CameraMatrix22->GetValue();
distCoeffs.at<double>(0, 0) = m_CameraCalibrationCfg->m_DistCoeffs0->GetValue();
distCoeffs.at<double>(0, 1) = m_CameraCalibrationCfg->m_DistCoeffs1->GetValue();
distCoeffs.at<double>(0, 2) = m_CameraCalibrationCfg->m_DistCoeffs2->GetValue();
distCoeffs.at<double>(0, 3) = m_CameraCalibrationCfg->m_DistCoeffs3->GetValue();
distCoeffs.at<double>(0, 4) = m_CameraCalibrationCfg->m_DistCoeffs4->GetValue();
cv::Mat calImage;
undistort(divImage, calImage, cameraMatrix, distCoeffs);
//cv::imwrite("g:/testimage/cal.bmp", calImage);
cv::Point2f srcTri[4];
2024-05-31 11:49:20 +08:00
srcTri[0] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageTopLeftX->GetValue(), (float)m_CameraCalibrationCfg->m_ImageTopLeftY->GetValue());
srcTri[1] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageTopRightX->GetValue(), (float)m_CameraCalibrationCfg->m_ImageTopRightY->GetValue());
srcTri[2] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageBottomRightX->GetValue(), (float)m_CameraCalibrationCfg->m_ImageBottomRightY->GetValue());
srcTri[3] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageBottomLeftX->GetValue(), (float)m_CameraCalibrationCfg->m_ImageBottomLeftY->GetValue());
cv::Point2f tempTri[4];
int tx = (m_CameraCalibrationCfg->m_PlatformTopRightX->GetValue() - m_CameraCalibrationCfg->m_PlatformTopLeftX->GetValue()) * rcc->m_ImageScale->GetValue();
int ty = (m_CameraCalibrationCfg->m_PlatformTopRightY->GetValue() - m_CameraCalibrationCfg->m_PlatformBottomRightY->GetValue()) * rcc->m_ImageScale->GetValue();
tempTri[0] = cv::Point2f(0.0f, 0.0f);
tempTri[1] = cv::Point2f((float)tx, 0.0f);
tempTri[2] = cv::Point2f((float)tx, (float)ty);
tempTri[3] = cv::Point2f(0.0f, (float)ty);
cv::Mat warp_mat = cv::getPerspectiveTransform(srcTri, tempTri);
cv::Mat wm(cv::Size(tx, ty), CV_8U);
cv::Mat bgFix(cv::Size(tx, ty), CV_8U);
warpPerspective(calImage, wm, warp_mat, wm.size());
//cv::imwrite("g:/testimage/war.bmp", wm);
warpPerspective(Calibration::m_CoverImage->m_ImageMat, bgFix, warp_mat, bgFix.size());
cv::Mat bg_mean, bg_stddev;
cv::meanStdDev(bgFix, bg_mean, bg_stddev);
double bgGrayAvg = 0.0;
bgGrayAvg = bg_mean.at<double>(0, 0);
bgFix.release();
cv::Mat dst;
cv::boxFilter(wm, dst, -1, cv::Size(3, 3));
2024-05-31 11:49:20 +08:00
if (m_CameraCalibrationCfg->m_BlackFace->GetValue()) {
cv::threshold(dst, dst, bgGrayAvg - 20, 255, cv::ThresholdTypes::THRESH_BINARY_INV);
}
else {
cv::threshold(dst, dst, bgGrayAvg + 20, 255, cv::ThresholdTypes::THRESH_BINARY);
}
//cv::imwrite("g:/testimage/dst.bmp", dst);
vector<cv::Vec4i> check_hierarchy;
vector<vector<cv::Point>> check_contours;
findContours(dst, check_contours, check_hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
double area = 0.0f;
for (size_t i = 0; i < check_contours.size(); i++) {
area += contourArea(check_contours[i]);
}
EnterCriticalSection(&disp_cs);
drawContours(wm, check_contours, -1, cv::Scalar(255, 0, 0), 2);
cv::resize(wm, m_WarpDst, m_WarpDst.size());
isDispUpdated = true;
LeaveCriticalSection(&disp_cs);
}