algoLib/lapWeldDetection_test/lapWeldDetection_test.cpp
2026-08-14 15:28:22 +08:00

1153 lines
32 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.

// glovePositioning_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <VZNL_Types.h>
#include "direct.h"
#include <string>
#include "SG_baseAlgo_Export.h"
#include "SX_lapWeldDetection_Export.h"
#include <opencv2/opencv.hpp>
#include <Windows.h>
typedef struct
{
int r;
int g;
int b;
}SG_color;
void vzReadLaserScanPointFromFile_plyTxt(const char* fileName, std::vector< SVzNL3DPoint>& scanData, bool exchangeXY)
{
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return;
while (std::getline(inputFile, linedata))
{
if (linedata.empty())
continue;
double X, Y, Z;
sscanf_s(linedata.c_str(), "%lf, %lf, %lf", &X, &Y, &Z);
SVzNL3DPoint a_pt;
if (true == exchangeXY)
{
a_pt.x = Y; //将扫描线调整为Y方向扫描方向为X方向
a_pt.y = X;
}
else
{
a_pt.x = X;
a_pt.y = Y;
}
a_pt.z = Z;
scanData.push_back(a_pt);
}
return;
}
void _outputScanDataFile_vector(char* fileName, std::vector<std::vector<SVzNL3DPosition>>& scanLines, bool removeZeros, int* headNullLines)
{
std::ofstream sw(fileName);
int lineNum = (int)scanLines.size();
if (lineNum == 0)
return;
sw << "LineNum:" << lineNum << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed: 0" << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp: 0_0" << std::endl;
int lineIdx = 0;
int null_lines = 0;
bool counterNull = true;
for (int line = 0; line < lineNum; line++)
{
int linePtNum = (int)scanLines[line].size();
if (linePtNum == 0)
continue;
if (true == removeZeros)
{
int vldPtNum = 0;
for (int i = 0; i < linePtNum; i++)
{
if (scanLines[line][i].pt3D.z > 1e-4)
vldPtNum++;
}
linePtNum = vldPtNum;
}
sw << "Line_" << lineIdx << "_0_" << linePtNum << std::endl;
lineIdx++;
bool isNull = true;
for (int i = 0; i < linePtNum; i++)
{
SVzNL3DPoint* pt3D = &scanLines[line][i].pt3D;
if ((pt3D->z > 1e-4) && (isNull == true))
isNull = false;
if ((true == removeZeros) && (pt3D->z < 1e-4))
continue;
float x = (float)pt3D->x;
float y = (float)pt3D->y;
float z = (float)pt3D->z;
sw << "{ " << x << "," << y << "," << z << " }-";
sw << "{0,0}-{0,0}" << std::endl;
}
if (true == counterNull)
{
if (true == isNull)
null_lines++;
else
counterNull = false;
}
}
*headNullLines = null_lines;
sw.close();
}
//输出水平扫描数据
void _outputScanDataFile_vector_h(char* fileName, std::vector<std::vector<SVzNL3DPosition>>& scanLines)
{
std::ofstream sw(fileName);
int lineNum = (int)scanLines[0].size();
if (lineNum == 0)
return;
sw << "LineNum:" << lineNum << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed: 0" << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp: 0_0" << std::endl;
int linePtNum = (int)scanLines.size();
int lineIdx = 0;
for (int line = 0; line < lineNum; line++)
{
sw << "Line_" << lineIdx << "_0_" << linePtNum << std::endl;
lineIdx++;
bool isNull = true;
for (int i = 0; i < linePtNum; i++)
{
SVzNL3DPoint* pt3D = &scanLines[i][line].pt3D;
float x = (float)pt3D->y;
float y = (float)pt3D->x;
float z = (float)pt3D->z;
sw << "{ " << x << "," << y << "," << z << " }-";
sw << "{0,0}-{0,0}" << std::endl;
}
}
sw.close();
}
void _outputRGBDScanLapWeld_RGBD(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
std::vector< std::vector<SVzNL3DPoint>> weldOPs,
bool outDebugInfo)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
if (weldOPs.size() > 0)
realLines++;
sw << "LineNum:" << realLines << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed: 0" << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp: 0_0" << 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 lineIdx = 0;
for (int line = 0; line < lineNum; line++)
{
int linePtNum = (int)scanLines[line].size();
if (linePtNum == 0)
continue;
sw << "Line_" << lineIdx << "_0_" << linePtNum << std::endl;
lineIdx++;
for (int i = 0; i < linePtNum; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->nPointIdx > 0)
int kkk = 1;
int featureType_v = pt3D->nPointIdx & 0xffff;
int featureType_h = featureType_v >> 4;
featureType_v &= 0xff;
if (true == outDebugInfo)
{
if (LINE_FEATURE_L_JUMP_H2L == featureType_v)
{
rgb = { 255, 97, 0 };
size = 5;
}
else if (LINE_FEATURE_L_JUMP_L2H == featureType_v)
{
rgb = { 0, 250, 0 };
size = 5;
}
else if (LINE_FEATURE_L_JUMP_H2L == featureType_h)
{
rgb = objColor[6];
size = 5;
}
else if (LINE_FEATURE_L_JUMP_L2H == featureType_h)
{
rgb = { 97, 255, 0 };
size = 5;
}
else
{
rgb = { 200, 200, 200 };
size = 1;
}
}
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 (weldOPs.size() > 0)
{
int weldNum = (int)weldOPs.size();
int linePtNum = 0;
for (int i = 0; i < weldNum; i++)
linePtNum += (int)weldOPs[i].size();
sw << "Line_" << lineNum << "_0_" << linePtNum + 1 << std::endl;
rgb = { 255, 0, 0 };
size = 25;
for (int i = 0; i < weldNum; i++)
{
for (int j = 0; j < (int)weldOPs[i].size(); j++)
{
float x = (float)weldOPs[i][j].x;
float y = (float)weldOPs[i][j].y;
float z = (float)weldOPs[i][j].z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
}
//加一个点用于跳过显示工具bug
float x = (float)weldOPs[0][0].x;
float y = (float)weldOPs[0][0].y;
float z = (float)weldOPs[0][0].z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
double exLen = 5.0;
rgb = objColor[0];
size = 3;
int polyIndx = 0;
for (int i = 0; i < weldNum; i++)
{
for (int j = 0; j < (int)weldOPs[i].size()-1; j++)
{
SVzNL3DPoint pt0 = weldOPs[i][j];
SVzNL3DPoint pt1 = weldOPs[i][j +1];
double len = sqrt(pow(pt0.x - pt1.x, 2) + pow(pt0.y - pt1.y, 2));
double k1 = exLen / len;
if (j > 0)
k1 = 0;
sw << "Poly_" << polyIndx << "_2" << std::endl;
polyIndx++;
double x = -k1 * (pt1.x - pt0.x) + pt0.x;
double y = -k1 * (pt1.y - pt0.y) + pt0.y;
double z = -k1 * (pt1.z - pt0.z) + pt0.z;
sw << "{" << (float)x << "," << (float)y << "," << (float)z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
double k2 = exLen / len;
if (j < (int)weldOPs[i].size() - 2)
k2 = 0;
x = -k2 * (pt0.x - pt1.x) + pt1.x;
y = -k2 * (pt0.y - pt1.y) + pt1.y;
z = -k2 * (pt0.z - pt1.z) + pt1.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
}
}
}
sw.close();
}
void _outputScanDataFile_ptr(char* fileName, SVzNL3DLaserLine* scanData, int lineNum)
{
std::ofstream sw(fileName);
sw << "LineNum:" << lineNum << std::endl;
sw << "DataType: 0" << std::endl;
sw << "ScanSpeed: 0" << std::endl;
sw << "PointAdjust: 1" << std::endl;
sw << "MaxTimeStamp: 0_0" << 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();
}
#define DATA_VER_OLD 0
#define DATA_VER_NEW 1
#define DATA_VER_FROM_CUSTOM 2
#define VZ_LASER_LINE_PT_MAX_NUM 4096
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;
}
void vzReadLaserScanPointFromFile_XYZ_vector(const char* fileName, std::vector<std::vector< SVzNL3DPosition>>& scanData)
{
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return;
std::vector< SVzNL3DPosition> a_line;
int ptIdx = 0;
while (getline(inputFile, linedata))
{
if (0 == strncmp("Line_", linedata.c_str(), 5))
{
int ptSize = (int)a_line.size();
if (ptSize > 0)
{
scanData.push_back(a_line);
}
a_line.clear();
ptIdx = 0;
}
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);
SVzNL3DPosition a_pt;
a_pt.pt3D.x = X;
a_pt.pt3D.y = Y;
a_pt.pt3D.z = Z;
a_pt.nPointIdx = ptIdx;
ptIdx++;
a_line.push_back(a_pt);
}
}
//last line
int ptSize = (int)a_line.size();
if (ptSize > 0)
{
scanData.push_back(a_line);
a_line.clear();
}
inputFile.close();
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;
}
void _getRoiClouds(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
int startLine,
int endLine,
int startPtIdx,
int endPtIdx,
std::vector< std::vector<SVzNL3DPosition>>& roiScanLines)
{
for (int i = startLine; i < endLine; i++)
{
if (i >= scanLines.size())
break;
std::vector<SVzNL3DPosition> cut_line;
std::vector<SVzNL3DPosition>& a_line = scanLines[i];
for (int j = startPtIdx; j < endPtIdx; j++)
{
SVzNL3DPosition a_pt;
if (j >= a_line.size())
{
a_pt.nPointIdx = 0;
a_pt.pt3D = { 0,0,0 };
}
else
a_pt = a_line[j];
cut_line.push_back(a_pt);
}
roiScanLines.push_back(cut_line);
}
return;
}
void _convertToGridData(std::vector< std::vector<SVzNL3DPosition>>& scanLines,
std::vector< std::vector<SVzNL3DPosition>>& gridScanLines,
double y_step)
{
double y_min = scanLines[0][0].pt3D.y;
double y_max = y_min;
int lineNum = (int)scanLines.size();
for (int line = 0; line < lineNum; line++)
{
std::vector<SVzNL3DPosition>& a_line = scanLines[line];
int ptNum = (int)a_line.size();
for (int i = 0; i < ptNum; i++)
{
if (y_min > a_line[i].pt3D.y)
y_min = a_line[i].pt3D.y;
if (y_max < a_line[i].pt3D.y)
y_max = a_line[i].pt3D.y;
}
}
double half_step = y_step / 2;
int gridPtNum = (int)((y_max - y_min + half_step) / y_step) + 1;
for (int line = 0; line < lineNum; line++)
{
std::vector<SVzNL3DPosition> grid_line;
grid_line.resize(gridPtNum);
for (int i = 0; i < gridPtNum; i++)
grid_line[i] = { 0, {0.0, 0.0, 0.0} };
std::vector<SVzNL3DPosition>& a_line = scanLines[line];
int ptNum = (int)a_line.size();
for (int i = 0; i < ptNum; i++)
{
int ptIdx = (int)((a_line[i].pt3D.y + half_step - y_min) / y_step);
grid_line[ptIdx] = a_line[i];
}
gridScanLines.push_back(grid_line);
}
return;
}
int counterLinePtNum_XYZ(std::vector< SVzNL3DPosition>& lineData)
{
int num = 0;
for (int i = 0; i < (int)lineData.size(); i++)
{
if (lineData[i].pt3D.z > 1e-4)
num++;
}
return num;
}
void _removeZeroLines_XYZ(std::vector<std::vector< SVzNL3DPosition>>& scanData)
{
int lineNum = (int)scanData.size();
int firstLine = -1;
int lastLine = 0;
for (int line = 0; line < lineNum; line++)
{
int num = counterLinePtNum_XYZ(scanData[line]);
if ((num > 0) && (firstLine < 0))
firstLine = line;
if (num > 0)
lastLine = line;
}
if (firstLine < 0)
{
scanData.clear();
return;
}
if ((lastLine < (lineNum - 1)) && (lastLine > 0))
scanData.erase(scanData.begin() + lastLine + 1, scanData.end());
scanData.erase(scanData.begin(), scanData.begin() + firstLine);
return;
}
#define CONVERT_TO_GRID 0
#define TEST_COMPUTE_CALIB_PARA 0
#define TEST_COMPUTE_POSITION 1
#define TEST_GROUP 2
void lapWeldTest()
{
const char* dataPath[TEST_GROUP] = {
"F:\\ShangGu\\项目\\钢板搭接焊缝检测\\数据\\", //0
"F:\\ShangGu\\项目\\钢板搭接焊缝检测\\模拟数据\\",
};
SVzNLRange fileIdx[TEST_GROUP] = {
{1,6}, {1,1}
};
#if CONVERT_TO_GRID
int convertGrp = 0;
for (int fidx = fileIdx[convertGrp].nMin; fidx <= fileIdx[convertGrp].nMax; fidx++)
{
char _scan_file[256];
sprintf_s(_scan_file, "%sglove_%d.txt", dataPath[convertGrp], fidx);
std::vector< SVzNL3DPoint> scanData;
bool exchangeXY = true;
vzReadLaserScanPointFromFile_plyTxt(_scan_file, scanData, exchangeXY);
//将数据恢复为按扫描线存储格式
std::vector< std::vector<SVzNL3DPosition>> scanLines;
wd_getScanLines(scanData, scanLines);
double y_step;
if ((fidx == 4) || (fidx == 5))
y_step = 0.106;
else
y_step = 0.091;
std::vector< std::vector<SVzNL3DPosition>> grid_scanLines;
_convertToGridData(scanLines, grid_scanLines, y_step);
sprintf_s(_scan_file, "%sglove_%d_scanLine.txt", dataPath[convertGrp], fidx);
int headNullLines = 0;
_outputScanDataFile_vector(_scan_file, grid_scanLines, false, &headNullLines);
printf("%s: head null lines = %d\n", _scan_file, headNullLines);
#if 1
sprintf_s(_scan_file, "%sglove_%d_scanLine_h.txt", dataPath[convertGrp], fidx);
_outputScanDataFile_vector_h(_scan_file, grid_scanLines);
#endif
}
#endif
#if TEST_COMPUTE_CALIB_PARA
char _calib_datafile[256];
sprintf_s(_calib_datafile, "F:\\ShangGu\\项目\\钢板搭接焊缝检测\\数据\\scanData_ground_1.txt");
int lineNum = 0;
float lineV = 0.0f;
int dataCalib = 0;
int maxTimeStamp = 0;
int clockPerSecond = 0;
std::vector<std::vector< SVzNL3DPosition>> scanData;
vzReadLaserScanPointFromFile_XYZ_vector(_calib_datafile, scanData);
lineNum = (int)scanData.size();
if (scanData.size() > 0)
{
SSG_planeCalibPara calibPara = sx_getBaseCalibPara( scanData);
//结果进行验证
for (int i = 0; i < lineNum; i++)
{
if (i == 14)
int kkk = 1;
//行处理
//调平,去除地面
sx_lineDataR(scanData[i], calibPara.planeCalib, -1); // calibPara.planeHeight);
}
//
char calibFile[250];
sprintf_s(calibFile, "F:\\ShangGu\\项目\\钢板搭接焊缝检测\\数据\\ground_calib_para.txt");
_outputCalibPara(calibFile, calibPara);
char _out_file[256];
sprintf_s(_out_file, "F:\\ShangGu\\项目\\钢板搭接焊缝检测\\数据\\scanData_ground_1_calib.txt");
int headNullLines = 0;
_outputScanDataFile_vector(_out_file, scanData, false, &headNullLines);
printf("%s: calib done!\n", _calib_datafile);
}
#endif
#if TEST_COMPUTE_POSITION
for (int grp = 0; grp <= 1; grp++)
{
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];
char calibFile[250];
if (grp == 0)
{
sprintf_s(calibFile, "F:\\ShangGu\\项目\\钢板搭接焊缝检测\\数据\\ground_calib_para.txt");
poseCalibPara = _readCalibPara(calibFile);
}
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =1;
char _scan_file[256];
sprintf_s(_scan_file, "%sscanData_%d.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
for (int i = 0, i_max = (int)scanLines.size(); i < i_max; i++)
{
if (i == 14)
int kkk = 1;
//行处理
//调平,去除地面
sx_lineDataR(scanLines[i], poseCalibPara.planeCalib, -1);
}
#if 0
char _out_file[256];
sprintf_s(_out_file, "%sscanData_%d_calib.txt", dataPath[grp], fidx);
int headNullLines = 0;
_outputScanDataFile_vector(_out_file, scanLines, false, &headNullLines);
#endif
SSX_lapWeldParam lapWeldParam;
lapWeldParam.lapHeight = 1.5;
lapWeldParam.weldMinLen = 80.0;
lapWeldParam.weldRefPoints = 3;
lapWeldParam.scanMode = keSX_ScanMode_V;
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 25; //45度角
cornerParam.scale = 4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 6;// algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = lapWeldParam.lapHeight; // algoParam.bagParam.bagH / 4;
cornerParam.jumpCornerTh_1 = 10;
cornerParam.jumpCornerTh_2 = 25;
SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 10;
growParam.yDeviation_max = 3.0;
growParam.maxSkipDistance = 5.0;
growParam.zDeviation_max = 1.0;// algoParam.bagParam.bagH / 2; //袋子高度1/2
growParam.minLTypeTreeLen = lapWeldParam.weldMinLen; //mm
growParam.minVTypeTreeLen = lapWeldParam.weldMinLen; //mm
int errCode = 0;
std::vector<std::vector<SVzNL3DPoint>> weldOps;
sx_getLapWeldPostion(
scanLines,
cornerParam,
growParam,
lapWeldParam,
poseCalibPara,
weldOps,
&errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1));
//输出测试结果
sprintf_s(_scan_file, "%sresult\\LaserLine%d_result.txt", dataPath[grp], fidx);
_outputRGBDScanLapWeld_RGBD(_scan_file, scanLines, weldOps, false);
}
}
#endif
}
#define TEST_BQ_CALIB_PARA 0
#define TEST_BQ_WELD_SEAM 1
#define BQ_TEST_GROUP 1
void BQ_thinWeldSeamTest()
{
const char* dataPath[BQ_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦_博清科技/焊缝识别/数据/", //0
};
SVzNLRange fileIdx[BQ_TEST_GROUP] = {
{1,4},
};
const char* ver = wd_weldSeamAlgoVersion();
printf("ver :%s\n", ver);
#if TEST_BQ_CALIB_PARA
char _calib_datafile[256];
sprintf_s(_calib_datafile, "F:/ShangGu/项目/冠钦_博清科技/焊缝识别/数据/1_LaserData_Jl26C077.txt");
int lineNum = 0;
float lineV = 0.0f;
int dataCalib = 0;
int maxTimeStamp = 0;
int clockPerSecond = 0;
std::vector<std::vector< SVzNL3DPosition>> scanData;
vzReadLaserScanPointFromFile_XYZ_vector(_calib_datafile, scanData);
_removeZeroLines_XYZ(scanData);
//高度过滤,保留顶板
double hTh = 490.0;
for (int line = 0; line < (int)scanData.size(); line++)
{
for (int j = 0; j < (int)scanData[line].size(); j++)
{
if (scanData[line][j].pt3D.z > hTh)
scanData[line][j].pt3D = { 0.0, 0.0, 0.0 };
}
}
lineNum = (int)scanData.size();
if (scanData.size() > 0)
{
SSG_planeCalibPara calibPara = sx_getBaseCalibPara(scanData);
//结果进行验证
for (int i = 0; i < lineNum; i++)
{
if (i == 14)
int kkk = 1;
//行处理
//调平,去除地面
sx_lineDataR(scanData[i], calibPara.planeCalib, -1); // calibPara.planeHeight);
}
char calibFile[250];
sprintf_s(calibFile, "F:/ShangGu/项目/冠钦_博清科技/焊缝识别/数据/ground_calib_para.txt");
_outputCalibPara(calibFile, calibPara);
char _out_file[256];
sprintf_s(_out_file, "F:/ShangGu/项目/冠钦_博清科技/焊缝识别/数据/scanData_ground_1_calib.txt");
int headNullLines = 0;
_outputScanDataFile_vector(_out_file, scanData, false, &headNullLines);
printf("%s: calib done!\n", _calib_datafile);
#if 1
for (int grp = 0; grp < 1; grp++)
{
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
char _scan_file[256];
sprintf_s(_scan_file, "%s%d_LaserData_Jl26C077.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
_removeZeroLines_XYZ(scanLines);
if (scanLines.size() == 0)
continue;
lineNum = (int)scanLines.size();
for (int i = 0; i < lineNum; i++)
sx_lineDataR(scanLines[i], calibPara.planeCalib, -1);//调平,去除地面
sprintf_s(_scan_file, "%s%d_ground_calibrated.txt", dataPath[grp], fidx);
int headNullLines = 0;
_outputScanDataFile_vector(_scan_file, scanLines, false, &headNullLines);
printf("%s: calib done!\n", _scan_file);
}
}
#endif
}
#endif
#if TEST_BQ_WELD_SEAM
//for (int group = 0; group < TEST_GROUPS; group++)
for (int grp = 0; grp < BQ_TEST_GROUP; grp++)
{
SSG_planeCalibPara groundCalibPara;
//初始化成单位阵
groundCalibPara.planeCalib[0] = 1.0;
groundCalibPara.planeCalib[1] = 0.0;
groundCalibPara.planeCalib[2] = 0.0;
groundCalibPara.planeCalib[3] = 0.0;
groundCalibPara.planeCalib[4] = 1.0;
groundCalibPara.planeCalib[5] = 0.0;
groundCalibPara.planeCalib[6] = 0.0;
groundCalibPara.planeCalib[7] = 0.0;
groundCalibPara.planeCalib[8] = 1.0;
groundCalibPara.planeHeight = -1.0;
for (int i = 0; i < 9; i++)
groundCalibPara.invRMatrix[i] = groundCalibPara.planeCalib[i];
char calibFile[250];
sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
groundCalibPara = _readCalibPara(calibFile);
double para_chkWidth_wide = 2.5f;
SSG_cornerParam cornerPara;
SVzNLRangeD gapParam;
SWD_valleyParam valleyParam;
valleyParam.chkWin_width = 2.5; //mm, 检测2.5mm宽的V型
valleyParam.maxWidth = 20.0; //最大宽度20mm用于过滤虚假信号
valleyParam.minHeight = 1.0;
SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 50;
growParam.yDeviation_max = 1.0;
growParam.maxSkipDistance = 30.0;
growParam.zDeviation_max = 5.0;//
growParam.minLTypeTreeLen = 50; //mm,
growParam.minVTypeTreeLen = 50; //mm
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
char _scan_file[256];
sprintf_s(_scan_file, "%s%d_LaserData_Jl26C077.txt", dataPath[grp], fidx);
printf("process: %s......\n", _scan_file);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
_removeZeroLines_XYZ(scanLines);
if (scanLines.size() == 0)
continue;
//统计时间
long t1 = (long)GetTickCount64();//统计时间
std::vector<SSG_gapFeatureTree> trees;
for (int i = 0; i < (int)scanLines.size(); i++)
{
std::vector<SVzNL3DPosition>& a_line = scanLines[i];
std::vector< SSG_basicFeatureGap> line_valleys;
sx_lineDataR(scanLines[i], groundCalibPara.planeCalib, -1);//调平,去除地面
#if 0
sg_getLineGapFeature(
a_line, //扫描线
i, //当前扫描线序号
cornerPara,
gapParam,
line_valleys);
#else
wd_getLineVFlaws(
a_line,
i,
valleyParam,
line_valleys);
#endif
bool isLastLine = i == ((int)scanLines.size() - 1) ? true : false;
sg_lineGapsGrowing(
i,
isLastLine,
line_valleys,
trees,
growParam);
}
int weldRefPoints = 3;
int errCode = 0;
std::vector<SVzNL3DPoint> weldOps;
std::vector<SVzNL3DPosition> weldRawPoints;
BQ_getWeldSeamPose(
trees,
weldRefPoints, //焊缝中间参考点位置
weldOps, //焊缝位置
weldRawPoints,
&errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1));
//生成debug信息
for (int line = 0; line < (int)scanLines.size(); line++)
{
for (int j = 0; j < (int)scanLines[line].size(); j++)
scanLines[line][j].nPointIdx = 0;
}
for (int i = 0; i < (int)trees.size(); i++)
{
for (int j = 0; j < (int)trees[i].treeNodes.size(); j++)
{
SSG_basicFeatureGap& a_node = trees[i].treeNodes[j];
scanLines[a_node.lineIdx][a_node.gapPeak.nPointIdx].nPointIdx = 2;
}
}
for (int i = 0; i < (int)weldRawPoints.size(); i++)
{
int lineIdx = weldRawPoints[i].nPointIdx >> 16;
int ptIdx = weldRawPoints[i].nPointIdx & 0xffff;
scanLines[lineIdx][ptIdx].nPointIdx = 1;
}
char outFileName[256];
//输出测试结果
sprintf_s(outFileName, "%sresult\\LaserLine%d_result.txt", dataPath[grp], fidx);
std::vector< std::vector<SVzNL3DPoint>> multiSeam;
multiSeam.push_back(weldOps);
_outputRGBDScanLapWeld_RGBD(outFileName, scanLines, multiSeam, true);
}
}
#endif
}
typedef enum
{
keSG_焊缝定位_搭接焊缝 = 0,
keSG_焊缝定位_长直细焊缝,
}ESG_testMode;
int main()
{
//ESG_testMode testMode = keSG_焊缝定位_搭接焊缝;
ESG_testMode testMode = keSG_焊缝定位_长直细焊缝;
if (keSG_焊缝定位_搭接焊缝 == testMode)
lapWeldTest();
else if (keSG_焊缝定位_长直细焊缝 == testMode)
BQ_thinWeldSeamTest();
return 0;
}