You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
8.0 KiB
C++

#include "pch.h"
#include "coutlinedetector.h"
#include "GSurface.h"
#include <QDebug>
//#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<CPolyline*> 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<vector<int>> hierarchy;
hierarchy.resize(m_hierarchy.size(), vector<int>(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<uchar>(j, i))
{
m_matMorp.at<uchar>(j, i) = 0;
}
}
}
}
Contours& COutlineDetector::GetOriginalContours(void)
{
return m_originalContours;
}
//获取沉积相轮廓线
CPolygonTreeInterface* COutlineDetector::GetFaciesContours(void)
{
CPolygonTreeInterface* pIntptr = &m_pgnTree;
return pIntptr;
}
shared_ptr<Contours> COutlineDetector::GetRealContours(void)
{
int nCount = m_pgnTree.GetResultPolygons().size();
auto faciesContours =std::make_shared<Contours>();
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<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> 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<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> 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;
}