#include #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(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) 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()); // ���� �߽�����roi���� vector> contour; vector pts; pts.push_back(cv::Point(rcc->m_MaskTopLeftX, rcc->m_MaskTopLeftY)); pts.push_back(cv::Point(rcc->m_MaskTopRightX, rcc->m_MaskTopRightY)); pts.push_back(cv::Point(rcc->m_MaskBottomRightX, rcc->m_MaskBottomRightY)); pts.push_back(cv::Point(rcc->m_MaskBottomLeftX, rcc->m_MaskBottomLeftY)); pts.push_back(cv::Point(rcc->m_MaskTopLeftX, rcc->m_MaskTopLeftY)); contour.push_back(pts); // ���� drawContours(mask, contour, 0, cv::Scalar::all(255), -1); //cv::Ptr 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, rcc->m_MaskTopLeftY); srcTri[1] = cv::Point2f(rcc->m_MaskTopRightX, rcc->m_MaskTopRightY); srcTri[2] = cv::Point2f(rcc->m_MaskBottomLeftX, rcc->m_MaskBottomLeftY); srcTri[3] = cv::Point2f(rcc->m_MaskBottomRightX, rcc->m_MaskBottomRightY); cv::Point2f dstTri[4]; dstTri[0] = cv::Point2f(rcc->m_TransformTopLeftX, rcc->m_TransformTopLeftY); dstTri[1] = cv::Point2f(rcc->m_TransformTopRightX, rcc->m_TransformTopRightY); dstTri[2] = cv::Point2f(rcc->m_TransformBottomLeftX, rcc->m_TransformBottomLeftY); dstTri[3] = cv::Point2f(rcc->m_TransformBottomRightX, rcc->m_TransformBottomRightY); 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, 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> disp_contours; vector 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> contours; vector 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 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()); 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 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 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 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 RecoatCheck::GetLayerBorders(MetaData* metadata, unsigned int layer, PolyTree& m_Borders) { if (metadata == nullptr || layer > metadata->GetLayerCount()) return vector(); MetaData::Layer* player = metadata->GetCurrentLayer(); if (player == NULL || player->index != layer) { if (metadata->LoadLayerByIndex(layer)) player = metadata->GetCurrentLayer(); else return vector(); } vector noBorderParts; m_Borders.Clear(); vector m_BordersDB; vector> m_WorkBorders; for (std::map::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(point->points[k]->x * CLIPPER_SCALE), static_cast(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>& 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); // ɸѡ�����������Χ�ڵ����� 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 * CLIPPER_SCALE * CLIPPER_SCALE; double LenThreshold = rcc->m_LengthThresholdFactor * 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) 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 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::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) 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> contour; vector pts; pts.push_back(cv::Point(rcc->m_MaskTopLeftX, rcc->m_MaskTopLeftY)); pts.push_back(cv::Point(rcc->m_MaskTopRightX, rcc->m_MaskTopRightY)); pts.push_back(cv::Point(rcc->m_MaskBottomRightX, rcc->m_MaskBottomRightY)); pts.push_back(cv::Point(rcc->m_MaskBottomLeftX, rcc->m_MaskBottomLeftY)); pts.push_back(cv::Point(rcc->m_MaskTopLeftX, rcc->m_MaskTopLeftY)); 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(pow((float)i / 255.0, gamma) * 255.0f); } cv::MatIterator_ it = image.begin(); cv::MatIterator_ end = image.end(); 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, rcc->m_MaskTopLeftY); srcTri[1] = cv::Point2f(rcc->m_MaskTopRightX, rcc->m_MaskTopRightY); srcTri[2] = cv::Point2f(rcc->m_MaskBottomRightX, rcc->m_MaskBottomRightY); srcTri[3] = cv::Point2f(rcc->m_MaskBottomLeftX, rcc->m_MaskBottomLeftY); cv::Point2f tempTri[4], dstTri[4]; // Mat warp_mat = getPerspectiveTransform(srcTri, dstTri); float plr = (float)mcfg->m_PlatformLength->GetValue() / mcfg->m_PlatformWidth->GetValue(); int wwidth = 1000; int wheight = 1000.0f / plr; 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(i, j) = log(1 + imageTemp.at(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) { for (int i = 0; i < upPart.rows; i++) { for (int j = 0; j < upPart.cols; j++) { upPart.at(i, j) = dst.at(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(0, 0); sd = mat_stddev.at(0, 0); int bt = avg + sd + 10; if (bt > 200)bt = 200; if (bt < rcc->m_BinaryThreshold)bt = rcc->m_BinaryThreshold; 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(0, 0); sd = mat_stddev.at(0, 0); int bt = avg + sd + 20; if (bt > 200)bt = 200; if (bt < rcc->m_BinaryThreshold)bt = rcc->m_BinaryThreshold; threshold(dst, dst, bt, 255, cv::ThresholdTypes::THRESH_BINARY); if (rcc->m_IsUpPartNotLight) { for (int i = 0; i < upPart.rows; i++) { for (int j = 0; j < upPart.cols; j++) { dst.at(i, j) = upPart.at(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> disp_contours; vector 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; } 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 disp_hierarchy; vector> 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> contour2; vector 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 m_HatchingDB; vector m_SupportDB; metadata->LockMainDB(); for (std::map::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 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) { 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)return true; if (m_CameraCalibrationCfg->m_CameraMatrix00 == 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 cameraMatrix.at(0, 0) = m_CameraCalibrationCfg->m_CameraMatrix00; cameraMatrix.at(0, 1) = m_CameraCalibrationCfg->m_CameraMatrix01; cameraMatrix.at(0, 2) = m_CameraCalibrationCfg->m_CameraMatrix02; cameraMatrix.at(1, 0) = m_CameraCalibrationCfg->m_CameraMatrix10; cameraMatrix.at(1, 1) = m_CameraCalibrationCfg->m_CameraMatrix11; cameraMatrix.at(1, 2) = m_CameraCalibrationCfg->m_CameraMatrix12; cameraMatrix.at(2, 0) = m_CameraCalibrationCfg->m_CameraMatrix20; cameraMatrix.at(2, 1) = m_CameraCalibrationCfg->m_CameraMatrix21; cameraMatrix.at(2, 2) = m_CameraCalibrationCfg->m_CameraMatrix22; distCoeffs.at(0, 0) = m_CameraCalibrationCfg->m_DistCoeffs0; distCoeffs.at(0, 1) = m_CameraCalibrationCfg->m_DistCoeffs1; distCoeffs.at(0, 2) = m_CameraCalibrationCfg->m_DistCoeffs2; distCoeffs.at(0, 3) = m_CameraCalibrationCfg->m_DistCoeffs3; distCoeffs.at(0, 4) = m_CameraCalibrationCfg->m_DistCoeffs4; cv::Mat calImage; undistort(divImage, calImage, cameraMatrix, distCoeffs); //g_log->TraceInfo("undistort"); //cv::imwrite("g:/testimage/cal.bmp", calImage); cv::Point2f srcTri[4]; srcTri[0] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageTopLeftX, (float)m_CameraCalibrationCfg->m_ImageTopLeftY); srcTri[1] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageTopRightX, (float)m_CameraCalibrationCfg->m_ImageTopRightY); srcTri[2] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageBottomRightX, (float)m_CameraCalibrationCfg->m_ImageBottomRightY); srcTri[3] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageBottomLeftX, (float)m_CameraCalibrationCfg->m_ImageBottomLeftY); cv::Point2f tempTri[4]; int tx = (m_CameraCalibrationCfg->m_PlatformTopRightX - m_CameraCalibrationCfg->m_PlatformTopLeftX) * rcc->m_ImageScale; int ty = (m_CameraCalibrationCfg->m_PlatformTopRightY - m_CameraCalibrationCfg->m_PlatformBottomRightY) * rcc->m_ImageScale; 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(0, 0); bgFix.release(); cv::Mat dst; cv::boxFilter(wm, dst, -1, cv::Size(3, 3)); cv::MatIterator_ it = dst.begin(); cv::MatIterator_ end = dst.end(); double area = 0.0; while (it != end) { double gray = *it; if (gray > bgGrayAvg + rcc->m_GrayOffset || gray < bgGrayAvg - rcc->m_GrayOffset) { *it = 255; area += 1.0; } else { *it = 0; } it++; } //cv::imwrite("g:/testimage/dst.bmp", dst); //g_log->TraceInfo("bin"); vector check_hierarchy; vector> 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"); double realArea = area / rcc->m_ImageScale / rcc->m_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 - m_CameraCalibrationCfg->m_PlatformTopLeftX) * rcc->m_ImageScale / 2.0f; float halfHigh = (float)(m_CameraCalibrationCfg->m_PlatformTopRightY - m_CameraCalibrationCfg->m_PlatformBottomRightY) * rcc->m_ImageScale / 2.0f; map infos; metadata->LockMainDB(); for (std::map::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 hatchingDB; vector 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 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 * rcc->m_ImageScale * rcc->m_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; vector points; points.push_back(cv::Point(point1x * rcc->m_ImageScale + halfWidth, halfHigh - ppint1y * rcc->m_ImageScale)); points.push_back(cv::Point(point2x * rcc->m_ImageScale + halfWidth, halfHigh - ppint2y * rcc->m_ImageScale)); points.push_back(cv::Point(point3x * rcc->m_ImageScale + halfWidth, halfHigh - ppint3y * rcc->m_ImageScale)); points.push_back(cv::Point(point4x * rcc->m_ImageScale + halfWidth, halfHigh - ppint4y * rcc->m_ImageScale)); info->m_Counter.push_back(points); infos[partid] = info; } metadata->UnLockMainDB(); double AreaSum = 0.0; for (map::iterator it = infos.begin(); it != infos.end(); it++) { RecoatCheckInfo* info = it->second; AreaSum += info->m_PartArea; delete info; } infos.clear(); float areaRat = area / AreaSum * 100.0f; if (areaRat > rcc->m_UncoverPercentage) { 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)return; if (m_CameraCalibrationCfg->m_CameraMatrix00 == 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 cameraMatrix.at(0, 0) = m_CameraCalibrationCfg->m_CameraMatrix00; cameraMatrix.at(0, 1) = m_CameraCalibrationCfg->m_CameraMatrix01; cameraMatrix.at(0, 2) = m_CameraCalibrationCfg->m_CameraMatrix02; cameraMatrix.at(1, 0) = m_CameraCalibrationCfg->m_CameraMatrix10; cameraMatrix.at(1, 1) = m_CameraCalibrationCfg->m_CameraMatrix11; cameraMatrix.at(1, 2) = m_CameraCalibrationCfg->m_CameraMatrix12; cameraMatrix.at(2, 0) = m_CameraCalibrationCfg->m_CameraMatrix20; cameraMatrix.at(2, 1) = m_CameraCalibrationCfg->m_CameraMatrix21; cameraMatrix.at(2, 2) = m_CameraCalibrationCfg->m_CameraMatrix22; distCoeffs.at(0, 0) = m_CameraCalibrationCfg->m_DistCoeffs0; distCoeffs.at(0, 1) = m_CameraCalibrationCfg->m_DistCoeffs1; distCoeffs.at(0, 2) = m_CameraCalibrationCfg->m_DistCoeffs2; distCoeffs.at(0, 3) = m_CameraCalibrationCfg->m_DistCoeffs3; distCoeffs.at(0, 4) = m_CameraCalibrationCfg->m_DistCoeffs4; cv::Mat calImage; undistort(divImage, calImage, cameraMatrix, distCoeffs); //cv::imwrite("g:/testimage/cal.bmp", calImage); cv::Point2f srcTri[4]; srcTri[0] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageTopLeftX, (float)m_CameraCalibrationCfg->m_ImageTopLeftY); srcTri[1] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageTopRightX, (float)m_CameraCalibrationCfg->m_ImageTopRightY); srcTri[2] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageBottomRightX, (float)m_CameraCalibrationCfg->m_ImageBottomRightY); srcTri[3] = cv::Point2f((float)m_CameraCalibrationCfg->m_ImageBottomLeftX, (float)m_CameraCalibrationCfg->m_ImageBottomLeftY); cv::Point2f tempTri[4]; int tx = (m_CameraCalibrationCfg->m_PlatformTopRightX - m_CameraCalibrationCfg->m_PlatformTopLeftX) * rcc->m_ImageScale; int ty = (m_CameraCalibrationCfg->m_PlatformTopRightY - m_CameraCalibrationCfg->m_PlatformBottomRightY) * rcc->m_ImageScale; 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(0, 0); bgFix.release(); cv::Mat dst; cv::boxFilter(wm, dst, -1, cv::Size(3, 3)); if (m_CameraCalibrationCfg->m_BlackFace) { 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 check_hierarchy; vector> 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); }