#include "pch.h" #include "coutlinedetector.h" #include "GSurface.h" #include //#include ".\include\PolygonTreeInterface.h" //#include ".\include\InterfaceElements.h" #include "..\..\SSBase\VoronoiMap\PolygonTreeInterface.h" #include "..\..\SSBase\VoronoiMap\InterfaceElements.h" #include "clipper2\clipper.h" //using namespace std; COutlineDetector::COutlineDetector() :m_pSurface(nullptr) , m_nIterations(3) , m_zlower(0) , m_zupper(0) , m_smoothTimes(0) , m_minArea(0) { } void COutlineDetector::clear() { // m_pSurface = nullptr; m_originalContours.clear(); m_matMorp.release(); } //设置最小轮廓线面积 void COutlineDetector::setContourMinArea(float area) { if (area < 0) area = 0; m_minArea = area; } //设置输出轮廓线平滑次数 void COutlineDetector::setContourSmoothTimes(unsigned int times) { if (times < 1) times = 0; m_smoothTimes = times; } void COutlineDetector::setSurface(GSurface *pSurf, float zlower, float zupper, unsigned int nIters) { m_pSurface = pSurf; setIterations(nIters); setTargetZRange(zlower, zupper); } void COutlineDetector::setTargetZRange(float zlower, float zupper) { m_zlower = zlower; m_zupper = zupper; } bool COutlineDetector::ProcessImage() { if (nullptr == m_pSurface) return false; morphologySolve(); createContours(); SmoothContours(); return true; } void COutlineDetector::multiContourToRealCoords(const Contours& inputContour, Contours & dstContours, int smoothTimes) { dstContours.resize(inputContour.size()); for (int i = 0; i < inputContour.size(); i++) contourToRealCoords(inputContour[i], dstContours[i], smoothTimes); } void COutlineDetector::contourToRealCoords(const Contour& inputContour, Contour& dstContour, int smoothTimes) { int N = inputContour.size(); double* x = new double[N]; double* y = new double[N]; float x0 = m_pSurface->X(0); float y0 = m_pSurface->Y(0); float dx = m_pSurface->DeltX(); float dy = m_pSurface->DeltY(); double tx, ty; for (int i = 0; i < N; i++) { tx = inputContour[i].x; ty = inputContour[i].y; x[i] = x0 + dx * tx; y[i] = y0 + dy * ty; } if (N > 4 && smoothTimes > 0) { ContourUtils::Smooth53(x, N, smoothTimes); ContourUtils::Smooth53(y, N, smoothTimes); } dstContour.resize(N); for (int i = 0; i < N; i++) { dstContour[i].x = x[i]; dstContour[i].y = y[i]; } delete[]x; delete[]y; } void toPline(Contour& src, CPolyline& dstLine) { dstLine.Clear(); for (auto& p : src) { dstLine.AddPoint(p.x, p.y, 0); } } void fromPline(CPolyline& src, Contour& dst) { CPointXYZ pt; dst.resize(src.GetSize()); for (int i = 0; i < src.GetSize(); i++) { pt = src.GetPoint(i); dst[i].x = pt.x0; dst[i].y = pt.y0; } } //生成沉积相轮廓线,局部合并内部包含孔洞的轮廓线 int COutlineDetector::CreateFaciesContours(void) { //m_faciesContours.clear(); m_pgnTree.Clear(); std::vector polygons; int i = 0; char chs[20]; polygons.reserve(m_originalContours.size()); float x0 = m_pSurface->X(0); float y0 = m_pSurface->Y(0); float dx = m_pSurface->DeltX(); float dy = m_pSurface->DeltY(); //double tx, ty; //for (int i = 0; i < N; i++) //{ // tx = inputContour[i].x; // ty = inputContour[i].y; // x[i] = x0 + dx * tx; // y[i] = y0 + dy * ty; //} for (auto& p : m_originalContours) { CPolyline* pl = new CPolyline; for (auto& pt : p) { pl->AddPoint(x0 + dx* pt.x, y0 + dy * pt.y, 0); } //toPline(p, *pl); sprintf(chs, "%d", i); pl->SetName(chs); pl->setClosed(); i++; polygons.push_back(pl); } std::vector> hierarchy; hierarchy.resize(m_hierarchy.size(), vector(4, -1)); for (i = 0; i < m_hierarchy.size(); i++) { for (int j = 0; j < 4; j++) hierarchy[i][j] = m_hierarchy[i][j]; } //CPolygonTreeInterface pgnTree; m_pgnTree.SetPolygons(polygons); m_pgnTree.SetHierarchy(hierarchy); //double deltX = m_pSurface->DeltX(); //double deltY = m_pSurface->DeltY(); double minArea = m_minArea / (dx*dy); if (minArea < 1e-4) minArea = 1e-4; m_pgnTree.Create(minArea); int N = m_pgnTree.GetResultPolygons().size(); //清空临时变量 for (auto p : polygons) delete p; return N; } void COutlineDetector::setIterations(unsigned int nIterations) { m_nIterations = nIterations; } void COutlineDetector::morphologySolve() { TraceBorder(); cv::Mat srcMat; ImageUtils::convertSurfaceToMat(m_pSurface, m_zlower, m_zupper, srcMat); //surface to bin mat m_matSrc = srcMat; cv::Mat bin = srcMat; cv::Mat kernel; kernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3, 3));//矩形结构元素 cv::Mat materode, matdilate; //膨胀 dilate(bin, matdilate, kernel, cv::Point(-1, -1), m_nIterations); //腐蚀 erode(matdilate, materode, kernel, cv::Point(-1, -1), m_nIterations + 1); //imshow("腐蚀", materode); // erode(bin, materode, kernel,Point(-1,-1),m_nIterations); // //imshow("腐蚀", materode); // //膨胀 // dilate(materode, matdilate, kernel, Point(-1, -1), m_nIterations+1); // //imshow("膨胀", matdilate); // // imwrite("d:/腐蚀膨胀后.bmp", matdilate); m_matMorp = matdilate; //由matBorder对越界部分进行修改 for (int j = 0; j < m_matMorp.rows; j++) { for (int i = 0; i < m_matMorp.cols; i++) { if (0 == m_matBorder.at(j, i)) { m_matMorp.at(j, i) = 0; } } } } Contours& COutlineDetector::GetOriginalContours(void) { return m_originalContours; } //获取沉积相轮廓线 CPolygonTreeInterface* COutlineDetector::GetFaciesContours(void) { CPolygonTreeInterface* pIntptr = &m_pgnTree; return pIntptr; } shared_ptr COutlineDetector::GetRealContours(void) { int nCount = m_pgnTree.GetResultPolygons().size(); auto faciesContours =std::make_shared(); faciesContours->resize(nCount); for (int i = 0; i < nCount; i++) { fromPline(*m_pgnTree.GetResultPolygons().at(i), (*faciesContours)[i]); } Contours dstvec; multiContourToRealCoords(*faciesContours, dstvec, 0); return faciesContours; } void COutlineDetector::TraceBorder() { m_border.clear(); ImageUtils::convertSurfaceToMat(m_pSurface, m_pSurface->GetRange()[0], m_pSurface->GetRange()[1], m_matBorder); std::vector> contours; std::vector hierarchy; // hierarchy 四个参数:下一个,前一个,子轮廓,父轮廓 (不存在则为-1) cv::findContours(m_matBorder, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE, cv::Point()); if (contours.size() > 0) { m_border.resize(contours[0].size()); for (int i = 0; i < contours[0].size(); i++) { m_border[i] = contours[0][i]; } } } void COutlineDetector::createContours() { m_originalContours.clear(); //m_faciesContours.clear(); m_pgnTree.Clear(); std::vector> contours; std::vector hierarchy; // hierarchy 四个参数:下一个,前一个,子轮廓,父轮廓 (不存在则为-1) cv::findContours(m_matMorp, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE, cv::Point()); m_originalContours.resize(contours.size()); for (int i = 0; i < contours.size(); i++) { approxPolyDP(contours[i], m_originalContours[i], 0.3, true); } m_hierarchy.assign(hierarchy.begin(), hierarchy.end()); } void COutlineDetector::FilterContours(float minArea, Contours& ReservedContours) { double dx = m_pSurface->DeltX(); double dy = m_pSurface->DeltY(); double gridArea = dx * dy; //对应图片上的面积 double imArea = minArea / gridArea; if (m_originalContours.empty() || imArea < 1e-4) { ReservedContours.assign(m_originalContours.begin(), m_originalContours.end()); return; } ReservedContours.reserve(m_originalContours.size()); for (auto& p : m_originalContours) { if (p.size() < 3) continue; double area = contourArea(p); if (area < imArea) continue; ReservedContours.push_back(p); } } void COutlineDetector::SmoothContours() { ContourUtils::SmoothContour(m_originalContours, m_border, m_hierarchy, m_smoothTimes); } cv::Mat &COutlineDetector::getResultMat() { return m_matMorp; }