algoLib/SieveNodeDetection_test/SieveNodeDetection_test.cpp
2025-06-11 22:14:58 +08:00

1171 lines
34 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <VZNL_Types.h>
#include "direct.h"
#include <string>
#include "SG_sieveNodeDetection_Export.h"
#include <opencv2/opencv.hpp>
#include <Windows.h>
SVzNL3DPoint _ptRotate(SVzNL3DPoint pt3D, double matrix3d[9])
{
SVzNL3DPoint _r_pt;
_r_pt.x = pt3D.x * matrix3d[0] + pt3D.y * matrix3d[1] + pt3D.z * matrix3d[2];
_r_pt.y = pt3D.x * matrix3d[3] + pt3D.y * matrix3d[4] + pt3D.z * matrix3d[5];
_r_pt.z = pt3D.x * matrix3d[6] + pt3D.y * matrix3d[7] + pt3D.z * matrix3d[8];
return _r_pt;
}
#define DATA_VER_OLD 0
#define DATA_VER_NEW 1
#define DATA_VER_FROM_CUSTOM 2
#define VZ_LASER_LINE_PT_MAX_NUM 4096
SVzNLXYZRGBDLaserLine* vzReadLaserScanPointFromFile_XYZRGB(const char* fileName, int* scanLineNum, float* scanV,
int* dataCalib, int* scanMaxStamp, int* canClockUnit)
{
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return NULL;
SVzNLXYZRGBDLaserLine* _scanLines = NULL;
int lines = 0;
int dataElements = 4;
int firstIndex = -1;
int dataFileVer = DATA_VER_OLD;
std::getline(inputFile, linedata); //第一行
int lineNum = 0;
if (0 == strncmp("LineNum:", linedata.c_str(), 8))
{
dataFileVer = DATA_VER_NEW;
sscanf_s(linedata.c_str(), "LineNum:%d", &lines);
if (lines == 0)
return NULL;
lineNum = lines;
_scanLines = (SVzNLXYZRGBDLaserLine*)malloc(sizeof(SVzNLXYZRGBDLaserLine) * (lineNum + 1));
memset(_scanLines, 0, sizeof(SVzNLXYZRGBDLaserLine) * (lineNum + 1));
if (scanLineNum)
*scanLineNum = lines;
}
else if (0 == strncmp("LineNum_", linedata.c_str(), 8))
{
dataFileVer = DATA_VER_OLD;
sscanf_s(linedata.c_str(), "LineNum_%d", &lines);
if (lines == 0)
return NULL;
lineNum = lines;
_scanLines = (SVzNLXYZRGBDLaserLine*)malloc(sizeof(SVzNLXYZRGBDLaserLine) * (lineNum + 1));
memset(_scanLines, 0, sizeof(SVzNLXYZRGBDLaserLine) * (lineNum + 1));
if (scanLineNum)
*scanLineNum = lines;
}
if (_scanLines == NULL)
return NULL;
int ptNum = 0;
int lineIdx = -1;
int ptIdx = 0;
SVzNLPointXYZRGBA* p3DPoint = NULL;
if (dataFileVer == DATA_VER_NEW)
{
while (getline(inputFile, linedata))
{
if (0 == strncmp("ScanSpeed:", linedata.c_str(), 10))
{
double lineV = 0;
sscanf_s(linedata.c_str(), "ScanSpeed:%lf", &lineV);
if (scanV)
*scanV = (float)lineV;
}
else if (0 == strncmp("PointAdjust:", linedata.c_str(), 12))
{
int ptAdjusted = 0;
sscanf_s(linedata.c_str(), "PointAdjust:%d", &ptAdjusted);
if (dataCalib)
*dataCalib = ptAdjusted;
}
else if (0 == strncmp("MaxTimeStamp:", linedata.c_str(), 13))
{
unsigned int maxTimeStamp = 0;
unsigned int timePerStamp = 0;
sscanf_s(linedata.c_str(), "MaxTimeStamp:%u_%u", &maxTimeStamp, &timePerStamp);
if (scanMaxStamp)
*scanMaxStamp = maxTimeStamp;
if (canClockUnit)
*canClockUnit = timePerStamp;
}
else if (0 == strncmp("Line_", linedata.c_str(), 5))
{
int lineIndex;
unsigned int timeStamp;
sscanf_s(linedata.c_str(), "Line_%d_%u_%d", &lineIndex, &timeStamp, &ptNum);
if (firstIndex < 0)
firstIndex = lineIndex;
lineIndex = lineIndex - firstIndex;
if ((lineIndex < 0) || (lineIndex >= lines))
break;
//new Line
lineIdx++;
if (ptNum > 0)
{
p3DPoint = (SVzNLPointXYZRGBA*)malloc(sizeof(SVzNLPointXYZRGBA) * ptNum);
memset(p3DPoint, 0, sizeof(SVzNLPointXYZRGBA) * ptNum);
}
else
p3DPoint = NULL;
_scanLines[lineIdx].nPointCnt = 0;
_scanLines[lineIdx].nTimeStamp = timeStamp;
_scanLines[lineIdx].p3DPoint = p3DPoint;
}
else if (0 == strncmp("{", linedata.c_str(), 1))
{
float X, Y, Z;
int imageY = 0;
float leftX, leftY;
float rightX, rightY;
int r = -1, g = -1, b = -1;
sscanf_s(linedata.c_str(), "{%f,%f,%f,%f,%f,%f }-{%f,%f}-{%f,%f}", &X, &Y, &Z, &r, &g, &b, &leftX, &leftY, &rightX, &rightY);
int id = _scanLines[lineIdx].nPointCnt;
if (id < ptNum)
{
p3DPoint[id].x = X;
p3DPoint[id].y = Y;
p3DPoint[id].z = Z;
p3DPoint[id].nRGB = 0;
_scanLines[lineIdx].nPointCnt = id + 1;
}
}
}
}
else if (dataFileVer == DATA_VER_OLD)
{
while (getline(inputFile, linedata))
{
if (0 == strncmp("DataElements_", linedata.c_str(), 13))
{
sscanf_s(linedata.c_str(), "DataElements_%d", &dataElements);
if ((dataElements != 3) && (dataElements != 4))
break;
}
if (0 == strncmp("LineV_", linedata.c_str(), 6))
{
double lineV = 0;
sscanf_s(linedata.c_str(), "LineV_%lf", &lineV);
}
else if (0 == strncmp("Line_", linedata.c_str(), 5))
{
int lineIndex;
unsigned int timeStamp;
sscanf_s(linedata.c_str(), "Line_%d_%u", &lineIndex, &timeStamp);
#if 0
if (scanLineListTail == NULL)
firstIndex = lineIndex;
#endif
lineIndex = lineIndex - firstIndex;
if ((lineIndex < 0) || (lineIndex >= lines))
break;
//new Line
//new Line
lineIdx++;
p3DPoint = (SVzNLPointXYZRGBA*)malloc(sizeof(SVzNLPointXYZRGBA) * VZ_LASER_LINE_PT_MAX_NUM);
memset(p3DPoint, 0, sizeof(SVzNLPointXYZRGBA) * VZ_LASER_LINE_PT_MAX_NUM);
_scanLines[lineIdx].nPointCnt = 0;
_scanLines[lineIdx].nTimeStamp = timeStamp;
_scanLines[lineIdx].p3DPoint = p3DPoint;
}
else if (0 == strncmp("(", linedata.c_str(), 1))
{
float X, Y, Z;
int imageY = 0;
if (dataElements == 4)
sscanf_s(linedata.c_str(), "(%f,%f,%f,%d)", &X, &Y, &Z, &imageY);
else
sscanf_s(linedata.c_str(), "(%f,%f,%f)", &X, &Y, &Z);
int id = _scanLines[lineIdx].nPointCnt;
if (id < VZ_LASER_LINE_PT_MAX_NUM)
{
p3DPoint[id].x = X;
p3DPoint[id].y = Y;
p3DPoint[id].z = Z;
p3DPoint[id].nRGB = 0;
_scanLines[lineIdx].nPointCnt = id + 1;
}
}
}
}
inputFile.close();
return _scanLines;
}
SVzNL3DLaserLine* vzReadLaserScanPointFromFile_XYZ(const char* fileName, int* scanLineNum, float* scanV,
int* dataCalib, int* scanMaxStamp, int* canClockUnit)
{
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return NULL;
SVzNL3DLaserLine* _scanLines = NULL;
int lines = 0;
int dataElements = 4;
int firstIndex = -1;
int dataFileVer = DATA_VER_OLD;
std::getline(inputFile, linedata); //第一行
int lineNum = 0;
if (0 == strncmp("LineNum:", linedata.c_str(), 8))
{
dataFileVer = DATA_VER_NEW;
sscanf_s(linedata.c_str(), "LineNum:%d", &lines);
if (lines == 0)
return NULL;
lineNum = lines;
_scanLines = (SVzNL3DLaserLine*)malloc(sizeof(SVzNL3DLaserLine) * (lineNum + 1));
memset(_scanLines, 0, sizeof(SVzNL3DLaserLine) * (lineNum + 1));
if (scanLineNum)
*scanLineNum = lines;
}
else if (0 == strncmp("LineNum_", linedata.c_str(), 8))
{
dataFileVer = DATA_VER_OLD;
sscanf_s(linedata.c_str(), "LineNum_%d", &lines);
if (lines == 0)
return NULL;
lineNum = lines;
_scanLines = (SVzNL3DLaserLine*)malloc(sizeof(SVzNL3DLaserLine) * (lineNum + 1));
memset(_scanLines, 0, sizeof(SVzNL3DLaserLine) * (lineNum + 1));
if (scanLineNum)
*scanLineNum = lines;
}
if (_scanLines == NULL)
return NULL;
int ptNum = 0;
int lineIdx = -1;
int ptIdx = 0;
SVzNL3DPosition* p3DPoint = NULL;
if (dataFileVer == DATA_VER_NEW)
{
while (getline(inputFile, linedata))
{
if (0 == strncmp("ScanSpeed:", linedata.c_str(), 10))
{
double lineV = 0;
sscanf_s(linedata.c_str(), "ScanSpeed:%lf", &lineV);
if (scanV)
*scanV = (float)lineV;
}
else if (0 == strncmp("PointAdjust:", linedata.c_str(), 12))
{
int ptAdjusted = 0;
sscanf_s(linedata.c_str(), "PointAdjust:%d", &ptAdjusted);
if (dataCalib)
*dataCalib = ptAdjusted;
}
else if (0 == strncmp("MaxTimeStamp:", linedata.c_str(), 13))
{
unsigned int maxTimeStamp = 0;
unsigned int timePerStamp = 0;
sscanf_s(linedata.c_str(), "MaxTimeStamp:%u_%u", &maxTimeStamp, &timePerStamp);
if (scanMaxStamp)
*scanMaxStamp = maxTimeStamp;
if (canClockUnit)
*canClockUnit = timePerStamp;
}
else if (0 == strncmp("Line_", linedata.c_str(), 5))
{
int lineIndex;
unsigned int timeStamp;
sscanf_s(linedata.c_str(), "Line_%d_%u_%d", &lineIndex, &timeStamp, &ptNum);
if (firstIndex < 0)
firstIndex = lineIndex;
lineIndex = lineIndex - firstIndex;
if ((lineIndex < 0) || (lineIndex >= lines))
break;
//new Line
lineIdx++;
if (ptNum > 0)
{
p3DPoint = (SVzNL3DPosition*)malloc(sizeof(SVzNL3DPosition) * ptNum);
memset(p3DPoint, 0, sizeof(SVzNL3DPosition) * ptNum);
}
else
p3DPoint = NULL;
_scanLines[lineIdx].nPositionCnt = 0;
_scanLines[lineIdx].nTimeStamp = timeStamp;
_scanLines[lineIdx].p3DPosition = p3DPoint;
}
else if (0 == strncmp("{", linedata.c_str(), 1))
{
float X, Y, Z;
int imageY = 0;
float leftX, leftY;
float rightX, rightY;
sscanf_s(linedata.c_str(), "{%f,%f,%f}-{%f,%f}-{%f,%f}", &X, &Y, &Z, &leftX, &leftY, &rightX, &rightY);
int id = _scanLines[lineIdx].nPositionCnt;
if (id < ptNum)
{
p3DPoint[id].pt3D.x = X;
p3DPoint[id].pt3D.y = Y;
p3DPoint[id].pt3D.z = Z;
_scanLines[lineIdx].nPositionCnt = id + 1;
}
}
}
}
else if (dataFileVer == DATA_VER_OLD)
{
while (getline(inputFile, linedata))
{
if (0 == strncmp("DataElements_", linedata.c_str(), 13))
{
sscanf_s(linedata.c_str(), "DataElements_%d", &dataElements);
if ((dataElements != 3) && (dataElements != 4))
break;
}
if (0 == strncmp("LineV_", linedata.c_str(), 6))
{
double lineV = 0;
sscanf_s(linedata.c_str(), "LineV_%lf", &lineV);
}
else if (0 == strncmp("Line_", linedata.c_str(), 5))
{
int lineIndex;
unsigned int timeStamp;
sscanf_s(linedata.c_str(), "Line_%d_%u", &lineIndex, &timeStamp);
#if 0
if (scanLineListTail == NULL)
firstIndex = lineIndex;
#endif
lineIndex = lineIndex - firstIndex;
if ((lineIndex < 0) || (lineIndex >= lines))
break;
//new Line
//new Line
lineIdx++;
p3DPoint = (SVzNL3DPosition*)malloc(sizeof(SVzNL3DPosition) * VZ_LASER_LINE_PT_MAX_NUM);
memset(p3DPoint, 0, sizeof(SVzNL3DPosition) * VZ_LASER_LINE_PT_MAX_NUM);
_scanLines[lineIdx].nPositionCnt = 0;
_scanLines[lineIdx].nTimeStamp = timeStamp;
_scanLines[lineIdx].p3DPosition = p3DPoint;
}
else if (0 == strncmp("(", linedata.c_str(), 1))
{
float X, Y, Z;
int imageY = 0;
if (dataElements == 4)
sscanf_s(linedata.c_str(), "(%f,%f,%f,%d)", &X, &Y, &Z, &imageY);
else
sscanf_s(linedata.c_str(), "(%f,%f,%f)", &X, &Y, &Z);
int id = _scanLines[lineIdx].nPositionCnt;
if (id < VZ_LASER_LINE_PT_MAX_NUM)
{
p3DPoint[id].pt3D.x = X;
p3DPoint[id].pt3D.y = Y;
p3DPoint[id].pt3D.z = Z;
_scanLines[lineIdx].nPositionCnt = id + 1;
}
}
}
}
inputFile.close();
return _scanLines;
}
SVzNL3DLaserLine* _convertToGridData_XYZRGB(SVzNLXYZRGBDLaserLine* laser3DPoints, int lineNum, double _F, double* camPoseR, int* outLineNum)
{
int min_y = 100000000;
int max_y = -10000000;
int validStartLine = -1;
int validEndLine = -1;
for (int line = 0; line < lineNum; line++)
{
if (laser3DPoints[line].nPointCnt > 0)
{
if (validStartLine < 0)
{
validStartLine = line;
validEndLine = line;
}
else
validEndLine = line;
}
for (int i = 0; i < laser3DPoints[line].nPointCnt; i++)
{
SVzNLPointXYZRGBA* a_pt = &laser3DPoints[line].p3DPoint[i];
if (a_pt->z > 1e-4)
{
double v = _F * a_pt->y / a_pt->z + 2000;
a_pt->nRGB = (int)(v + 0.5);
max_y = max_y < (int)a_pt->nRGB ? (int)a_pt->nRGB : max_y;
min_y = min_y > (int)a_pt->nRGB ? (int)a_pt->nRGB : min_y;
}
}
}
if (min_y == 100000000)
return NULL;
int vldLineNum = validEndLine - validStartLine + 1;
*outLineNum = vldLineNum;
int pt_counter = max_y - min_y + 1;
SVzNL3DLaserLine* gridData = (SVzNL3DLaserLine*)malloc(sizeof(SVzNL3DLaserLine) * (vldLineNum + 1));
memset(gridData, 0, sizeof(SVzNL3DLaserLine) * (vldLineNum + 1));
for (int line = validStartLine; line <= validEndLine; line++)
{
int gridLine = line - validStartLine;
gridData[gridLine].nPositionCnt = pt_counter;
gridData[gridLine].nTimeStamp = laser3DPoints[line].nTimeStamp;
gridData[gridLine].p3DPosition = (SVzNL3DPosition*)malloc(sizeof(SVzNL3DPosition) * pt_counter);
memset(gridData[gridLine].p3DPosition, 0, sizeof(SVzNL3DPosition) * pt_counter);
for (int i = 0; i < laser3DPoints[line].nPointCnt; i++)
{
SVzNLPointXYZRGBA a_pt = laser3DPoints[line].p3DPoint[i];
if (a_pt.z > 1e-4)
{
int pt_id = a_pt.nRGB - min_y;
SVzNL3DPoint tmp_pt = { a_pt.x, a_pt.y, a_pt.z };
SVzNL3DPoint r_pt = _ptRotate(tmp_pt, camPoseR);
gridData[gridLine].p3DPosition[pt_id].pt3D.x = r_pt.x;
gridData[gridLine].p3DPosition[pt_id].pt3D.y = r_pt.y;
gridData[gridLine].p3DPosition[pt_id].pt3D.z = r_pt.z;
}
}
}
return gridData;
}
void _outputScanDataFile_self(char* fileName, SVzNL3DLaserLine* scanData, int lineNum,
float lineV, int maxTimeStamp, int clockPerSecond)
{
std::ofstream sw(fileName);
sw << "LineNum:" << lineNum << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed:" << lineV << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp:" << maxTimeStamp << "_" << clockPerSecond << std::endl;
for (int line = 0; line < lineNum; line++)
{
sw << "Line_" << line << "_" << scanData[line].nTimeStamp << "_" << scanData[line].nPositionCnt << std::endl;
for (int i = 0; i < scanData[line].nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanData[line].p3DPosition[i];
float x = (float)pt3D->pt3D.x;
float y = (float)pt3D->pt3D.y;
float z = (float)pt3D->pt3D.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}" << std::endl;
}
}
sw.close();
}
typedef struct
{
int r;
int g;
int b;
}SG_color;
void _outputScanDataFile_RGBD_obj_XYZ(char* fileName, SVzNL3DLaserLine* scanData, int lineNum,
float lineV, int maxTimeStamp, int clockPerSecond, std::vector<SVzNL3DPoint>& objOps)
{
std::ofstream sw(fileName);
int realLines = lineNum;
if (objOps.size() > 0)
realLines++;
sw << "LineNum:" << realLines << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed:" << lineV << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp:" << maxTimeStamp << "_" << clockPerSecond << std::endl;
int maxLineIndex = 0;
int max_stamp = 0;
SG_color rgb = { 0, 0, 0 };
SG_color objColor[8] = {
{245,222,179},//淡黄色
{210,105, 30},//巧克力色
{240,230,140},//黄褐色
{135,206,235},//天蓝色
{250,235,215},//古董白
{189,252,201},//薄荷色
{221,160,221},//梅红色
{188,143,143},//玫瑰红色
};
int size = 1;
int nTimeStamp = 0;
for (int line = 0; line < lineNum; line++)
{
sw << "Line_" << line << "_" << scanData[line].nTimeStamp << "_" << scanData[line].nPositionCnt << std::endl;
nTimeStamp = scanData[line].nTimeStamp;
for (int i = 0; i < scanData[line].nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanData[line].p3DPosition[i];
int vType = pt3D->nPointIdx & 0xff;
int hType = vType >> 4;
int objId = (pt3D->nPointIdx >> 16) & 0xffff;
vType = vType & 0x0f;
if (LINE_FEATURE_L_JUMP_H2L == vType)
{
rgb = { 255, 97, 0 };
size = 3;
}
else if (LINE_FEATURE_L_JUMP_L2H == vType)
{
rgb = { 255, 255, 0 };
size = 3;
}
else if (LINE_FEATURE_V_SLOPE == vType)
{
rgb = { 255, 0, 255 };
size = 3;
}
else if (LINE_FEATURE_L_SLOPE_H2L == vType)
{
rgb = { 0, 0, 255 };
size = 20;
}
else if ((LINE_FEATURE_LINE_ENDING_0 == vType) || (LINE_FEATURE_LINE_ENDING_1 == vType))
{
rgb = { 255, 0, 0 };
size = 3;
}
else if (LINE_FEATURE_L_SLOPE_L2H == vType) //已经焊接过
{
rgb = { 255, 255, 0 };
size = 20;
}
else if (LINE_FEATURE_L_JUMP_H2L == hType)
{
rgb = { 0, 0, 255 };
size = 3;
}
else if (LINE_FEATURE_L_JUMP_L2H == hType)
{
rgb = { 0, 255, 255 };
size = 3;
}
else if (LINE_FEATURE_V_SLOPE == hType)
{
rgb = { 0, 255, 0 };
size = 3;
}
else if (LINE_FEATURE_L_SLOPE_H2L == hType)
{
rgb = { 85, 107, 47 };
size = 3;
}
else if (LINE_FEATURE_L_SLOPE_L2H == hType)
{
rgb = { 0, 255, 154 };
size = 3;
}
else if ((LINE_FEATURE_LINE_ENDING_0 == hType) || (LINE_FEATURE_LINE_ENDING_1 == hType))
{
rgb = { 255, 0, 0 };
size = 3;
}
else if (objId > 0) //目标
{
rgb = objColor[objId % 8];
size = 5;
}
else
{
rgb = { 200, 200, 200 };
size = 1;
}
float x = (float)pt3D->pt3D.x;
float y = (float)pt3D->pt3D.y;
float z = (float)pt3D->pt3D.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
}
if (objOps.size() > 0)
{
int ptNum = objOps.size();
sw << "Line_" << lineNum << "_" << (nTimeStamp + 1000) << "_" << ptNum << std::endl;
for (int i = 0; i < objOps.size(); i++)
{
if (i == 0)
rgb = { 255, 0, 0 };
else
rgb = { 255, 255, 0 };
size = 25;
float x = (float)objOps[i].x;
float y = (float)objOps[i].y;
float z = (float)objOps[i].z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
if (i == 0)
{
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
}
}
sw.close();
}
void _XOYprojection_nodePos(cv::Mat& img, std::vector<std::vector< SVzNL3DPosition>>& dataLines, std::vector<SVzNL3DPoint>& objOps,
const double x_scale, const double y_scale, const SVzNLRangeD x_range, const SVzNLRangeD y_range)
{
int x_skip = 16;
int y_skip = 16;
cv::Vec3b rgb = cv::Vec3b(0, 0, 0);
cv::Vec3b objColor[8] = {
{245,222,179},//淡黄色
{210,105, 30},//巧克力色
{240,230,140},//黄褐色
{135,206,235},//天蓝色
{250,235,215},//古董白
{189,252,201},//薄荷色
{221,160,221},//梅红色
{188,143,143},//玫瑰红色
};
int size = 1;
for (int line = 0; line < dataLines.size(); line++)
{
std::vector< SVzNL3DPosition>& a_line = dataLines[line];
for (int i = 0; i < a_line.size(); i++)
{
SVzNL3DPosition* pt3D = &a_line[i];
if (pt3D->pt3D.z < 1e-4)
continue;
int vType = pt3D->nPointIdx & 0xff;
int hType = vType >> 4;
int objId = (pt3D->nPointIdx >> 16) & 0xff;
vType = vType & 0x0f;
if (LINE_FEATURE_L_JUMP_H2L == vType)
{
rgb = { 255, 97, 0 };
size = 2;
}
else if (LINE_FEATURE_L_JUMP_L2H == vType)
{
rgb = { 255, 255, 0 };
size = 2;
}
else if (LINE_FEATURE_V_SLOPE == vType)
{
rgb = { 255, 0, 255 };
size = 2;
}
else if (LINE_FEATURE_L_SLOPE_H2L == vType)
{
rgb = { 160, 82, 45 };
size = 2;
}
else if ((LINE_FEATURE_LINE_ENDING_0 == vType) || (LINE_FEATURE_LINE_ENDING_1 == vType))
{
rgb = { 255, 0, 0 };
size = 2;
}
else if (LINE_FEATURE_L_SLOPE_L2H == vType)
{
rgb = { 233, 150, 122 };
size = 2;
}
else if (LINE_FEATURE_L_JUMP_H2L == hType)
{
rgb = { 0, 0, 255 };
size = 2;
}
else if (LINE_FEATURE_L_JUMP_L2H == hType)
{
rgb = { 0, 255, 255 };
size = 2;
}
else if (LINE_FEATURE_V_SLOPE == hType)
{
rgb = { 0, 255, 0 };
size = 2;
}
else if (LINE_FEATURE_L_SLOPE_H2L == hType)
{
rgb = { 85, 107, 47 };
size = 2;
}
else if (LINE_FEATURE_L_SLOPE_L2H == hType)
{
rgb = { 0, 255, 154 };
size = 2;
}
else if ((LINE_FEATURE_LINE_ENDING_0 == hType) || (LINE_FEATURE_LINE_ENDING_1 == hType))
{
rgb = { 255, 0, 0 };
size = 2;
}
else if (objId > 0) //目标
{
rgb = objColor[objId % 8];
size = 1;
}
else
{
rgb = { 60, 60, 60 };
size = 1;
}
double x = pt3D->pt3D.x;
double y = pt3D->pt3D.y;
int px = (int)((x - x_range.min) / x_scale + x_skip);
int py = (int)((y - y_range.min) / y_scale + y_skip);
if (size == 1)
img.at<cv::Vec3b>(py, px) = cv::Vec3b(rgb[2], rgb[1], rgb[0]);
else
cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), -1);
}
}
if (objOps.size() > 0)
{
for (int i = 0; i < objOps.size(); i++)
{
if (i == 0)
{
rgb = { 255, 0, 0 };
size = 20;
}
else
{
rgb = { 255, 255, 0 };
size = 10;
}
int px = (int)((objOps[i].x - x_range.min) / x_scale + x_skip);
int py = (int)((objOps[i].y - y_range.min) / y_scale + y_skip);
cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), -1);
}
}
}
void _genXOYProjectionImage_nodePos(cv::String& fileName, SVzNL3DLaserLine* scanData, int lineNum, std::vector<SVzNL3DPoint>& nodeOps)
{
//统计X和Y的范围
std::vector<std::vector< SVzNL3DPosition>> scan_lines;
SVzNLRangeD x_range = { 0, -1 };
SVzNLRangeD y_range = { 0, -1 };
for (int line = 0; line < lineNum; line++)
{
std::vector< SVzNL3DPosition> a_line;
for (int i = 0; i < scanData[line].nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanData[line].p3DPosition[i];
if (pt3D->pt3D.z < 1e-4)
continue;
a_line.push_back(*pt3D);
if (x_range.max < x_range.min)
{
x_range.min = pt3D->pt3D.x;
x_range.max = pt3D->pt3D.x;
}
else
{
if (x_range.min > pt3D->pt3D.x)
x_range.min = pt3D->pt3D.x;
if (x_range.max < pt3D->pt3D.x)
x_range.max = pt3D->pt3D.x;
}
if (y_range.max < y_range.min)
{
y_range.min = pt3D->pt3D.y;
y_range.max = pt3D->pt3D.y;
}
else
{
if (y_range.min > pt3D->pt3D.y)
y_range.min = pt3D->pt3D.y;
if (y_range.max < pt3D->pt3D.y)
y_range.max = pt3D->pt3D.y;
}
}
scan_lines.push_back(a_line);
}
int imgRows = 992;
int imgCols = 1056;
double y_rows = 960.0;
double x_cols = 1024.0;
//计算投影比例
double x_scale = (x_range.max - x_range.min) / x_cols;
double y_scale = (y_range.max - y_range.min) / y_rows;
if (x_scale > y_scale)
{
x_scale = y_scale;
int nx_cols = (int)((x_range.max - x_range.min) / x_scale) + 1;
if ( (nx_cols % 2) > 0)
nx_cols += 1;
x_cols = nx_cols;
imgCols = x_cols + 32.0;
}
else
{
y_scale = x_scale;
int ny_rows = (int)((y_range.max - y_range.min) / y_scale) + 1;
if ((ny_rows % 2) > 0)
ny_rows += 1;
y_rows = ny_rows;
imgRows = y_rows + 32.0;
}
cv::Mat img = cv::Mat::zeros(imgRows, imgCols, CV_8UC3);
_XOYprojection_nodePos(img, scan_lines, nodeOps, x_scale, y_scale, x_range, y_range);
cv::imwrite(fileName, img);
return;
}
void _outputCalibPara(char* fileName, SSG_planeCalibPara calibPara)
{
std::ofstream sw(fileName);
char dataStr[250];
//调平矩阵
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.planeCalib[0], calibPara.planeCalib[1], calibPara.planeCalib[2]);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.planeCalib[3], calibPara.planeCalib[4], calibPara.planeCalib[5]);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.planeCalib[6], calibPara.planeCalib[7], calibPara.planeCalib[8]);
sw << dataStr << std::endl;
//地面高度
sprintf_s(dataStr, 250, "%g", calibPara.planeHeight);
sw << dataStr << std::endl;
//反向旋转矩阵
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.invRMatrix[0], calibPara.invRMatrix[1], calibPara.invRMatrix[2]);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.invRMatrix[3], calibPara.invRMatrix[4], calibPara.invRMatrix[5]);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, "%g, %g, %g", calibPara.invRMatrix[6], calibPara.invRMatrix[7], calibPara.invRMatrix[8]);
sw << dataStr << std::endl;
sw.close();
}
SSG_planeCalibPara _readCalibPara(char* fileName)
{
//设置初始结果
double initCalib[9] = {
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 };
SSG_planeCalibPara planePara;
for (int i = 0; i < 9; i++)
planePara.planeCalib[i] = initCalib[i];
planePara.planeHeight = -1.0;
for (int i = 0; i < 9; i++)
planePara.invRMatrix[i] = initCalib[i];
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return planePara;
//调平矩阵
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.planeCalib[0], &planePara.planeCalib[1], &planePara.planeCalib[2]);
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.planeCalib[3], &planePara.planeCalib[4], &planePara.planeCalib[5]);
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.planeCalib[6], &planePara.planeCalib[7], &planePara.planeCalib[8]);
//地面高度
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf", &planePara.planeHeight);
//反向旋转矩阵
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.invRMatrix[0], &planePara.invRMatrix[1], &planePara.invRMatrix[2]);
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.invRMatrix[3], &planePara.invRMatrix[4], &planePara.invRMatrix[5]);
std::getline(inputFile, linedata);
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &planePara.invRMatrix[6], &planePara.invRMatrix[7], &planePara.invRMatrix[8]);
inputFile.close();
return planePara;
}
#define TEST_CONVERT_TO_GRID 0
#define TEST_COMPUTE_SIEVE_NODES 1
#define TEST_COMPUTE_CALIB_PARA 0
#define TEST_GROUP 2
int main()
{
#if TEST_CONVERT_TO_GRID
//将数据转换成栅格格式格式
char _scan_dir[256];
int lineNum = 0;
float lineV = 0.0f;
int dataCalib = 0;
int maxTimeStamp = 0;
int clockPerSecond = 0;
sprintf_s(_scan_dir, "F:\\上古\\项目\\筛孔节点检测\\20250303 筛网数据\\");
char _scan_file[256];
double _F = 1295.6; //f
for (int i = 1; i <= 12; i++)
{
sprintf_s(_scan_file, "%s%d_LaserData_Ik256139.txt", _scan_dir, i);
SVzNLXYZRGBDLaserLine* laser3DPoints_RGBD = vzReadLaserScanPointFromFile_XYZRGB(_scan_file, &lineNum, &lineV, &dataCalib, &maxTimeStamp, &clockPerSecond);
if (laser3DPoints_RGBD == NULL)
continue;
#if 0
double rpy[3] = { 0,-18, 0 };
double camPoseR[9];
EulerRpyToRotation1(rpy, camPoseR);
#else
double camPoseR[9] = {
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 };
#endif
int vldLineNum = 0;
SVzNL3DLaserLine* gridData = _convertToGridData_XYZRGB(laser3DPoints_RGBD, lineNum, _F, camPoseR, &vldLineNum);
char _out_file[256];
sprintf_s(_out_file, "%sLaserLine%d_grid.txt", _scan_dir, i);
_outputScanDataFile_self(_out_file, gridData, vldLineNum,
lineV, maxTimeStamp, clockPerSecond);
#if 0
//生成水平扫描数据
int hLineNum = gridData[0].nPositionCnt;
SVzNL3DLaserLine* hScanData = (SVzNL3DLaserLine*)malloc(sizeof(SVzNL3DLaserLine) * hLineNum);
memset(hScanData, 0, sizeof(SVzNL3DLaserLine) * hLineNum);
for (int hLine = 0; hLine < hLineNum; hLine++)
{
hScanData[hLine].nPositionCnt = vldLineNum;
hScanData[hLine].nTimeStamp = hLine * 1000;
hScanData[hLine].p3DPosition = (SVzNL3DPosition*)malloc(sizeof(SVzNL3DPosition) * lineNum);
memset(hScanData[hLine].p3DPosition, 0, sizeof(SVzNL3DPosition) * lineNum);
for (int m = 0; m < vldLineNum; m++)
{
hScanData[hLine].p3DPosition[m].nPointIdx = m;
hScanData[hLine].p3DPosition[m].pt3D.x = gridData[m].p3DPosition[hLine].pt3D.y;
hScanData[hLine].p3DPosition[m].pt3D.y = gridData[m].p3DPosition[hLine].pt3D.x;
hScanData[hLine].p3DPosition[m].pt3D.z = gridData[m].p3DPosition[hLine].pt3D.z;
}
}
sprintf_s(_out_file, "%sLaserLine%d_hScanData.txt", _scan_dir, i);
_outputScanDataFile_removeZeros(_out_file, hScanData, hLineNum,
lineV, maxTimeStamp, clockPerSecond);
#endif
printf("%s: convert done!\n", _scan_file);
}
printf("all converting done!\n", _scan_file);
#endif
#if TEST_COMPUTE_CALIB_PARA
char _calib_datafile[256];
sprintf_s(_calib_datafile, "F:\\上古\\项目\\筛孔节点检测\\20250304 筛网\\LaserLine1_grid.txt");
std::vector<SVzNL3DRangeD> dataROIs;
dataROIs.resize(4);
dataROIs[0].xRange = { -120, -107 };
dataROIs[0].yRange = { -169, -79 };
dataROIs[0].zRange = { 543, 557 };
dataROIs[1].xRange = { -105, -95 };
dataROIs[1].yRange = { 84, 208 };
dataROIs[1].zRange = { 535, 548 };
dataROIs[2].xRange = { 89, 103 };
dataROIs[2].yRange = { -180, -57 };
dataROIs[2].zRange = { 543, 557 };
dataROIs[3].xRange = { 104, 116 };
dataROIs[3].yRange = { 0, 198 };
dataROIs[3].zRange = { 535, 548 };
int lineNum = 0;
float lineV = 0.0f;
int dataCalib = 0;
int maxTimeStamp = 0;
int clockPerSecond = 0;
SVzNL3DLaserLine* laser3DPoints = vzReadLaserScanPointFromFile_XYZ(_calib_datafile, &lineNum, &lineV, &dataCalib, &maxTimeStamp, &clockPerSecond);
if (laser3DPoints)
{
SSG_planeCalibPara calibPara = sg_getSieveBaseCalibPara(
laser3DPoints,
lineNum,
dataROIs);
//结果进行验证
for (int i = 0; i < lineNum; i++)
{
if (i == 14)
int kkk = 1;
//行处理
//调平,去除地面
sg_lineDataR(&laser3DPoints[i], calibPara.planeCalib, calibPara.planeHeight-1);
}
//
char calibFile[250];
sprintf_s(calibFile, "F:\\上古\\项目\\筛孔节点检测\\20250304 筛网\\ground_calib_para.txt");
_outputCalibPara(calibFile, calibPara);
char _out_file[256];
sprintf_s(_out_file, "F:\\上古\\项目\\筛孔节点检测\\20250304 筛网\\LaserLine1_grid_calib.txt");
_outputScanDataFile_self(_out_file, laser3DPoints, lineNum,
lineV, maxTimeStamp, clockPerSecond);
printf("%s: calib done!\n", _calib_datafile);
}
#endif
#if TEST_COMPUTE_SIEVE_NODES
const char* dataPath[TEST_GROUP] = {
"F:\\ShangGu\\项目\\筛孔节点检测\\20250304 筛网\\", //0
"F:\\ShangGu\\项目\\筛孔节点检测\\20250303 筛网数据\\", //1
};
SVzNLRange fileIdx[TEST_GROUP] = {
{1,9},{1,12}
};
SSG_planeCalibPara poseCalibPara;
//初始化成单位阵
poseCalibPara.planeCalib[0] = 1.0;
poseCalibPara.planeCalib[1] = 0.0;
poseCalibPara.planeCalib[2] = 0.0;
poseCalibPara.planeCalib[3] = 0.0;
poseCalibPara.planeCalib[4] = 1.0;
poseCalibPara.planeCalib[5] = 0.0;
poseCalibPara.planeCalib[6] = 0.0;
poseCalibPara.planeCalib[7] = 0.0;
poseCalibPara.planeCalib[8] = 1.0;
poseCalibPara.planeHeight = -1.0;
for (int i = 0; i < 9; i++)
poseCalibPara.invRMatrix[i] = poseCalibPara.planeCalib[i];
SSG_sieveNodeDetectionParam algoParam;
algoParam.sieveDiameter = 5; //
algoParam.sieveHoleSize = 15;
algoParam.slopeParam.LSlopeZWin = 5;
algoParam.slopeParam.minLJumpH = 4; // 30; // algoParam.bagParam.bagH / 8;
algoParam.slopeParam.minEndingGap = 2;
algoParam.slopeParam.validSlopeH = 4;
algoParam.growParam.maxLineSkipNum = 5;
algoParam.growParam.yDeviation_max = algoParam.sieveDiameter * 1.5;
algoParam.growParam.maxSkipDistance = algoParam.sieveDiameter / 2;
algoParam.growParam.zDeviation_max = algoParam.sieveDiameter * 1.5; //袋子高度1/2
algoParam.growParam.minLTypeTreeLen = algoParam.sieveDiameter * 1.5; //mm
algoParam.growParam.minVTypeTreeLen = algoParam.sieveDiameter * 1.5; //mm
char _scan_file[256];
int endGroup = TEST_GROUP - 1;
for (int grp = 0; grp <= 1; grp++)
{
if (0 == grp)
{
char calibFile[250];
sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
poseCalibPara = _readCalibPara(calibFile);
poseCalibPara.planeHeight = poseCalibPara.planeHeight - 1;
}
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx = 102;
int lineNum = 0;
float lineV = 0.0f;
int dataCalib = 0;
int maxTimeStamp = 0;
int clockPerSecond = 0;
sprintf_s(_scan_file, "%sLaserLine%d_grid.txt", dataPath[grp], fidx);
SVzNL3DLaserLine* laser3DPoints = vzReadLaserScanPointFromFile_XYZ(_scan_file, &lineNum, &lineV, &dataCalib, &maxTimeStamp, &clockPerSecond);
if (laser3DPoints == NULL)
continue;
algoParam.filterParam.continuityTh = 20.0; //噪声滤除。当相邻点的z跳变大于此门限时检查是否为噪声。若长度小于outlierLen 视为噪声
algoParam.filterParam.outlierTh = 5;
long t1 = GetTickCount64();
//调平,去除地面
for (int i = 0; i < lineNum; i++)
{
sg_lineDataR(&laser3DPoints[i], poseCalibPara.planeCalib, poseCalibPara.planeHeight);
}
//计算节点位置
std::vector<SVzNL3DPoint> nodePos;
sg_getSieveNodes(
laser3DPoints,
lineNum,
algoParam,
nodePos);
long t2 = GetTickCount64();
char _dbg_file[256];
#if 1
sprintf_s(_dbg_file, "%sresult\\LaserLine%d_result.txt", dataPath[grp], fidx);
_outputScanDataFile_RGBD_obj_XYZ(_dbg_file, laser3DPoints, lineNum, lineV, maxTimeStamp, clockPerSecond, nodePos);
sprintf_s(_dbg_file, "%sresult\\LaserLine%d_result_img.png", dataPath[grp], fidx);
cv::String imgName(_dbg_file);
double rpy[3] = { -30, 15, 0 }; //{ 0,-45, 0 }; //
_genXOYProjectionImage_nodePos(imgName, laser3DPoints, lineNum, nodePos);
#endif
#if 0
//量化成2D图像作为训练样本
cv::Mat project2D_img;
double z_scale = 3.0;
double xy_scale = 2.0;
project2DWithInterpolate(project2D_img, laser3DPoints, lineNum, xy_scale, z_scale);
cv::Mat project2D_color;
cv::applyColorMap(project2D_img, project2D_color, cv::COLORMAP_JET);
sprintf_s(_dbg_file, "%simg2D_JET\\LaserLine%d_img2D.png", dataPath[grp], fidx);
cv::String img2DName(_dbg_file);
cv::imwrite(img2DName, project2D_color);
cv::Mat project2D_color_HOT;
cv::applyColorMap(project2D_img, project2D_color_HOT, cv::COLORMAP_HOT);
sprintf_s(_dbg_file, "%simg2D\\LaserLine%d_img2D.png", dataPath[grp], fidx);
cv::String img2DName_HOT(_dbg_file);
cv::imwrite(img2DName_HOT, project2D_color_HOT);
#endif
printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1));
}
}
#endif
printf("all done!\n");
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件