algoLib/rodAndBarDetection_test/rodAndBarDetection_test.cpp
jerryzeng 2d837cb108 rodAndBarDetection version 1.3.3 :
筑裕钢筋焊缝提取算法改进中间版本
2026-06-03 17:25:45 +08:00

1765 lines
55 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.

// gasFillingPortPosition_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>
#include <VZNL_Types.h>
#include "direct.h"
#include <string>
#include "rodAndBarDetection_Export.h"
#include <opencv2/opencv.hpp>
#include <Windows.h>
#include <limits>
#include <SG_baseAlgo_Export.h>
#include <cmath>
typedef struct
{
int r;
int g;
int b;
}SG_color;
typedef struct
{
int nPointIdx;
double x;
double y;
double z;
float r;
float g;
float b;
} SPointXYZRGB;
bool fileExists(const char* path) {
FILE* f = fopen(path, "r");
if (f != NULL) {
fclose(f);
return true;
}
return false;
}
// 点乘 dot
double _dotMultiply(const SVzNL3DPoint& a, const SVzNL3DPoint& b)
{
return (a.x * b.x + a.y * b.y + a.z * b.z);
}
// 模长
double _length(const SVzNL3DPoint& a)
{
return sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
}
// 计算两个向量夹角(返回 角度)
float _computeVecAngle(const SVzNL3DPoint& a, const SVzNL3DPoint& b)
{
float l = _length(a) * _length(b);
if (l < 1e-6f)
return 0.0f; // 避免除零
float cosTheta = _dotMultiply(a, b) / l;
cosTheta = cosTheta > 1.0 ? 1.0 : cosTheta;
cosTheta = cosTheta < -1.0 ? -1.0 : cosTheta;
float rad = acosf(cosTheta);
float degree = rad * 180.0f / (float)M_PI;
return degree;
}
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 wdReadLaserScanPointFromFile_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 wd_gridScan_GetROIData(std::vector<std::vector< SVzNL3DPosition>>& scanData, SVzNLRangeD roi_y, std::vector<std::vector< SVzNL3DPosition>>& roiData)
{
int lineNum = (int)scanData.size();
int linePtNum = (int)scanData[0].size();
int globalPtStart = INT_MAX;
int globalPtEnd = 0;
int lineStart = INT_MAX;
int lineEnd = 0;
for (int line = 0; line < lineNum; line++)
{
std::vector< SVzNL3DPosition >& lineData = scanData[line];
int ptSize = (int)lineData.size();
int vldNum = 0;
int ptStart = INT_MAX;
int ptEnd = 0;
for (int i = 0; i < ptSize; i++)
{
if (lineData[i].pt3D.z > 1e-4)
{
if ((lineData[i].pt3D.y < roi_y.min) || (lineData[i].pt3D.y > roi_y.max))
lineData[i].pt3D = { 0.0, 0.0, 0.0 };
}
if (lineData[i].pt3D.z > 1e-4)
{
if (ptStart > i)
ptStart = i;
ptEnd = i;
vldNum++;
}
}
if (vldNum > 0)
{
if (globalPtStart > ptStart)
globalPtStart = ptStart;
if (globalPtEnd < ptEnd)
globalPtEnd = ptEnd;
if (lineStart > line)
lineStart = line;
lineEnd = line;
}
}
int vldLineNum = lineEnd - lineStart + 1;
int vldPtNum = globalPtEnd - globalPtStart + 1;
roiData.resize(vldLineNum);
for (int line = 0; line < vldLineNum; line++)
{
roiData[line].resize(vldPtNum);
for (int i = 0; i < vldPtNum; i++)
roiData[line][i] = scanData[line + lineStart][i + globalPtStart];
}
return;
}
void _outputScanDataFile(char* fileName, std::vector<std::vector< SVzNL3DPosition>>& scanData,
float lineV, int maxTimeStamp, int clockPerSecond)
{
std::ofstream sw(fileName);
int lineNum = (int)scanData.size();
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++)
{
int nPositionCnt = (int)scanData[line].size();
sw << "Line_" << line << "_0_" << nPositionCnt << std::endl;
for (int i = 0; i < nPositionCnt; i++)
{
SVzNL3DPosition& pt3D = scanData[line][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();
}
void _readRodParas(char* fileName, std::vector<SSX_rodParam>& rodParas)
{
std::ifstream inputFile(fileName);
std::string linedata;
if (inputFile.is_open() == false)
return;
std::vector<int> indices;
int maxIdx = 0;
std::vector< SSX_rodParam> paras;
while (getline(inputFile, linedata))
{
int idx;
float len, dia;
sscanf_s(linedata.c_str(), "%d_L_%f_D_%f", &idx, &len, &dia);
SSX_rodParam a_para = { dia , len };
indices.push_back(idx);
paras.push_back(a_para);
maxIdx = maxIdx < idx ? idx : maxIdx;
}
if (maxIdx == 0)
return;
rodParas.resize(maxIdx + 1);
for (int i = 0; i < (int)indices.size(); i++)
{
int idx = indices[i];
rodParas[idx] = paras[i];
}
return;
}
void _outputChanneltInfo(char* fileName, std::vector<SSX_rodPoseInfo>& screwInfo)
{
std::ofstream sw(fileName);
char dataStr[250];
int objNum = (int)screwInfo.size();
for (int i = 0; i < objNum; i++)
{
sprintf_s(dataStr, 250, "螺杆_%d: center_( %g, %g, %g ), dir_( %g, %g, %g )",
i + 1, screwInfo[i].center.x, screwInfo[i].center.y, screwInfo[i].center.z,
screwInfo[i].axialDir.x, screwInfo[i].axialDir.y, screwInfo[i].axialDir.z);
sw << dataStr << std::endl;
}
sw.close();
}
void _outputPlatePiseInfo(char* fileName, SSX_platePoseInfo& centerInfo)
{
std::ofstream sw(fileName);
char dataStr[250];
sprintf_s(dataStr, 250, "定位盘: \n");
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " holeLT_(% g, % g, % g)\n", centerInfo.holeLT.x, centerInfo.holeLT.y, centerInfo.holeLT.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " holeRB_(% g, % g, % g)\n", centerInfo.holeRB.x, centerInfo.holeRB.y, centerInfo.holeRB.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " center_(% g, % g, % g)\n", centerInfo.center.x, centerInfo.center.y, centerInfo.center.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " normalDir_(% g, % g, % g)\n", centerInfo.normalDir.x, centerInfo.normalDir.y, centerInfo.normalDir.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " xDir_(% g, % g, % g)\n", centerInfo.xDir.x, centerInfo.xDir.y, centerInfo.xDir.z);
sw << dataStr << std::endl;
sprintf_s(dataStr, 250, " yDir_(% g, % g, % g)\n", centerInfo.yDir.x, centerInfo.yDir.y, centerInfo.yDir.z);
sw << dataStr << std::endl;
sw.close();
}
void _outputRodtInfo(char* fileName, std::vector<SSX_rodPositionInfo>& rodInfo)
{
std::ofstream sw(fileName);
char dataStr[250];
int objNum = (int)rodInfo.size();
for (int i = 0; i < objNum; i++)
{
sprintf_s(dataStr, 250, "螺杆_%d: center_( %g, %g, %g ), dir_axia( %g, %g, %g ), dir_normal_( %g, %g, %g )",
i + 1, rodInfo[i].center.x, rodInfo[i].center.y, rodInfo[i].center.z,
rodInfo[i].axialDir.x, rodInfo[i].axialDir.y, rodInfo[i].axialDir.z,
rodInfo[i].normalDir.x, rodInfo[i].normalDir.y, rodInfo[i].normalDir.z);
sw << dataStr << std::endl;
}
sw.close();
}
void _outputWeldSeamInfo(char* fileName, std::vector<SSX_weldSeamInfo>& weldSeamInfo)
{
std::ofstream sw(fileName);
char dataStr[250];
int objNum = (int)weldSeamInfo.size();
for (int i = 0; i < objNum; i++)
{
sprintf_s(dataStr, 250, "螺杆_%d: center_( %g, %g, %g ), dir_normal_( %g, %g, %g ), x_dir_(",
i + 1, weldSeamInfo[i].center.x, weldSeamInfo[i].center.y, weldSeamInfo[i].center.z,
weldSeamInfo[i].normalDir.x, weldSeamInfo[i].normalDir.y, weldSeamInfo[i].normalDir.z);
sw << dataStr << std::endl;
}
sw.close();
}
void _outputRGBDScan_RGBD(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
std::vector<SSX_rodPoseInfo>& screwInfo
)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
int objNum = (int)screwInfo.size();
if (objNum > 0)
realLines += 1;
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 == 1)
{
rgb = objColor[pt3D->nPointIdx];
size = 3;
}
else if (pt3D->nPointIdx == 2)
{
rgb = { 250, 0, 0 };
size = 3;
}
else if (pt3D->nPointIdx == 4)
{
rgb = { 250, 250, 0 };
size = 6;
}
else //if (pt3D->nPointIdx == 0)
{
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 (objNum > 0)
{
sw << "Line_" << lineIdx << "_0_" << objNum << std::endl;
rgb = { 250, 0, 0 };
size = 8;
for (int i = 0; i < objNum; i++)
{
float x = (float)screwInfo[i].center.x;
float y = (float)screwInfo[i].center.y;
float z = (float)screwInfo[i].center.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
//多输出一个修正显示工具bug
float x = (float)screwInfo[0].center.x;
float y = (float)screwInfo[0].center.y;
float z = (float)screwInfo[0].center.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
//输出法向
size = 1;
double len1 = 30;
double len2 = 200;
lineIdx = 0;
for (int i = 0; i < objNum; i++)
{
SVzNL3DPoint pt0 = { screwInfo[i].center.x - len1 * screwInfo[i].axialDir.x,
screwInfo[i].center.y - len1 * screwInfo[i].axialDir.y,
screwInfo[i].center.z - len1 * screwInfo[i].axialDir.z };
SVzNL3DPoint pt1 = { screwInfo[i].center.x + len2 * screwInfo[i].axialDir.x,
screwInfo[i].center.y + len2 * screwInfo[i].axialDir.y,
screwInfo[i].center.z + len2 * screwInfo[i].axialDir.z };
//显示法向量
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt1.x << "," << pt1.y << "," << pt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
}
sw.close();
}
void _outputRGBDScan_RGBD_centerPose(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
SSX_platePoseInfo& poseInfo
)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
realLines += 1;
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 == 2)
{
rgb = { 135,206,235 };
size = 5;
}
else if (pt3D->nPointIdx == 3)
{
rgb = { 250, 0, 0 };
size = 5;
}
else //if (pt3D->nPointIdx == 0)
{
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;
}
}
{
sw << "Line_" << lineIdx << "_0_3" << std::endl;
rgb = { 250, 0, 0 };
size = 8;
float x = (float)poseInfo.center.x;
float y = (float)poseInfo.center.y;
float z = (float)poseInfo.center.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
x = (float)poseInfo.holeLT.x;
y = (float)poseInfo.holeLT.y;
z = (float)poseInfo.holeLT.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
x = (float)poseInfo.holeRB.x;
y = (float)poseInfo.holeRB.y;
z = (float)poseInfo.holeRB.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
//输出法向
size = 1;
double len = 110;
lineIdx = 0;
{
SVzNL3DPoint pt0 = { poseInfo.center.x, // - len * poseInfo.normalDir.x,
poseInfo.center.y, // - len * poseInfo.normalDir.y,
poseInfo.center.z }; // - len * poseInfo.normalDir.z };
SVzNL3DPoint pt1 = { poseInfo.center.x + len * poseInfo.normalDir.x,
poseInfo.center.y + len * poseInfo.normalDir.y,
poseInfo.center.z + len * poseInfo.normalDir.z };
SVzNL3DPoint basePt = poseInfo.center;
SVzNL3DPoint pt2 = { poseInfo.center.x + len * poseInfo.xDir.x,
poseInfo.center.y + len * poseInfo.xDir.y,
poseInfo.center.z + len * poseInfo.xDir.z };
SVzNL3DPoint pt3 = { poseInfo.center.x + len * poseInfo.yDir.x,
poseInfo.center.y + len * poseInfo.yDir.y,
poseInfo.center.z + len * poseInfo.yDir.z };
//显示法向量
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt1.x << "," << pt1.y << "," << pt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
rgb = { 0, 250, 0 };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)basePt.x << "," << (float)basePt.y << "," << (float)basePt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt2.x << "," << pt2.y << "," << pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
rgb = { 0, 0, 250 };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)basePt.x << "," << (float)basePt.y << "," << (float)basePt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt3.x << "," << pt3.y << "," << pt3.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
rgb = { 0, 250, 0 };
basePt = { poseInfo.holeLT.x - len * poseInfo.xDir.x,
poseInfo.holeLT.y - len * poseInfo.xDir.y,
poseInfo.holeLT.z - len * poseInfo.xDir.z };
pt2 = { poseInfo.holeLT.x + len * poseInfo.xDir.x,
poseInfo.holeLT.y + len * poseInfo.xDir.y,
poseInfo.holeLT.z + len * poseInfo.xDir.z };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)basePt.x << "," << (float)basePt.y << "," << (float)basePt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt2.x << "," << pt2.y << "," << pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
basePt = { poseInfo.holeRB.x - len * poseInfo.xDir.x,
poseInfo.holeRB.y - len * poseInfo.xDir.y,
poseInfo.holeRB.z - len * poseInfo.xDir.z };
pt2 = { poseInfo.holeRB.x + len * poseInfo.xDir.x,
poseInfo.holeRB.y + len * poseInfo.xDir.y,
poseInfo.holeRB.z + len * poseInfo.xDir.z };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)basePt.x << "," << (float)basePt.y << "," << (float)basePt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << pt2.x << "," << pt2.y << "," << pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
}
sw.close();
}
void _outputRGBDScan_RGBD_rodInfo(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
std::vector<SSX_rodPositionInfo>& rodInfo
)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
int objNum = (int)rodInfo.size();
if (objNum > 0)
realLines += 1;
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 centerFlag = pt3D->nPointIdx >> 4;
if (centerFlag > 0)
{
rgb = { 180, 0, 0 };
size = 2;
}
else
{
rgb = objColor[pt3D->nPointIdx % 8];
size = 2;
}
}
else //if (pt3D->nPointIdx == 0)
{
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 (objNum > 0)
{
sw << "Line_" << lineIdx << "_0_" << objNum << std::endl;
size = 12;
for (int i = 0; i < objNum; i++)
{
if(i == 0)
rgb = { 250, 255, 0 };
else
rgb = { 250, 0, 0 };
float x = (float)rodInfo[i].center.x;
float y = (float)rodInfo[i].center.y;
float z = (float)rodInfo[i].center.z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
//输出法向
size = 8;
double len = 60;
lineIdx = 0;
for (int i = 0; i < objNum; i++)
{
if (i == 0)
rgb = { 250, 255, 0 };
else
rgb = { 250, 0, 0 };
SVzNL3DPoint pt0 = { rodInfo[i].center.x, rodInfo[i].center.y, rodInfo[i].center.z };
SVzNL3DPoint pt1 = { rodInfo[i].center.x + len * rodInfo[i].axialDir.x,
rodInfo[i].center.y + len * rodInfo[i].axialDir.y,
rodInfo[i].center.z + len * rodInfo[i].axialDir.z };
SVzNL3DPoint pt2 = { rodInfo[i].center.x + len * rodInfo[i].normalDir.x,
rodInfo[i].center.y + len * rodInfo[i].normalDir.y,
rodInfo[i].center.z + len * rodInfo[i].normalDir.z };
//显示轴向量
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)rodInfo[i].startPt.x << "," << (float)rodInfo[i].startPt.y << "," << (float)rodInfo[i].startPt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << (float)rodInfo[i].endPt.x << "," << (float)rodInfo[i].endPt.y << "," << (float)rodInfo[i].endPt.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
//显示法向量
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << (float)pt2.x << "," << (float)pt2.y << "," << (float)pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
lineIdx++;
}
sw.close();
}
void _outputRGBDScan_RGBD_weldSeam(
char* fileName,
std::vector<std::vector<SVzNL3DPosition>>& scanLines,
std::vector<SSX_weldSeamInfo>& weldSeamInfo
)
{
int lineNum = (int)scanLines.size();
std::ofstream sw(fileName);
int realLines = lineNum;
int objNum = (int)weldSeamInfo.size();
if (objNum > 0)
realLines += 1;
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 centerFlag = pt3D->nPointIdx >> 4;
if (centerFlag > 0)
{
if (centerFlag <= 2)
{
rgb = { 180, 0, 0 };
size = 2;
}
else if(centerFlag == 4)
{
rgb = { 0, 250, 0 };
size = 4;
}
}
else
{
rgb = objColor[pt3D->nPointIdx % 8];
size = 2;
}
}
else //if (pt3D->nPointIdx == 0)
{
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 (objNum > 0)
{
std::vector<SVzNL3DPoint> weldPoints;
for (int i = 0; i < objNum; i++)
{
if (weldSeamInfo[i].weldType == KeWD_WELD_POINT)
weldPoints.push_back(weldSeamInfo[i].center);
else
{
weldPoints.push_back(weldSeamInfo[i].startPt);
weldPoints.push_back(weldSeamInfo[i].center);
weldPoints.push_back(weldSeamInfo[i].endPt);
}
}
sw << "Line_" << lineIdx << "_0_" << (int)weldPoints.size() << std::endl;
size = 15;
for (int i = 0; i < (int)weldPoints.size(); i++)
{
rgb = { 250, 0, 0 };
float x = (float)weldPoints[i].x;
float y = (float)weldPoints[i].y;
float z = (float)weldPoints[i].z;
sw << "{" << x << "," << y << "," << z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << rgb.r << "," << rgb.g << "," << rgb.b << "," << size << " }" << std::endl;
}
//输出法向
size = 4;
double len1 = 20;
double len2 = 20;
lineIdx = 0;
for (int i = 0; i < objNum; i++)
{
SVzNL3DPoint pt0, pt1;
if (weldSeamInfo[i].weldType == KeWD_WELD_POINT)
{
pt0 = weldSeamInfo[i].center;
pt1 = { weldSeamInfo[i].center.x + len1 * weldSeamInfo[i].axialDir.x,
weldSeamInfo[i].center.y + len1 * weldSeamInfo[i].axialDir.y,
weldSeamInfo[i].center.z + len1 * weldSeamInfo[i].axialDir.z };
}
else
{
pt0 = weldSeamInfo[i].startPt;
pt1 = weldSeamInfo[i].endPt;
}
SVzNL3DPoint pt2 = { weldSeamInfo[i].center.x, weldSeamInfo[i].center.y, weldSeamInfo[i].center.z };
SVzNL3DPoint pt3 = { weldSeamInfo[i].center.x + len2 * weldSeamInfo[i].normalDir.x,
weldSeamInfo[i].center.y + len2 * weldSeamInfo[i].normalDir.y,
weldSeamInfo[i].center.z + len2 * weldSeamInfo[i].normalDir.z };
//显示轴向量
rgb = { 0, 0, 250 };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt0.x << "," << (float)pt0.y << "," << (float)pt0.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << (float)pt1.x << "," << (float)pt1.y << "," << (float)pt1.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
//显示法向量
rgb = { 250, 0, 0 };
sw << "Poly_" << lineIdx << "_2" << std::endl;
sw << "{" << (float)pt2.x << "," << (float)pt2.y << "," << (float)pt2.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
sw << "{" << (float)pt3.x << "," << (float)pt3.y << "," << (float)pt3.z << "}-";
sw << "{0,0}-{0,0}-";
sw << "{" << (int)rgb.r << "," << (int)rgb.g << "," << (int)rgb.b << "," << size << "}" << std::endl;
lineIdx++;
}
lineIdx++;
}
sw.close();
}
#define SCREW_TEST_GROUP 10
void screwTest(void)
{
const char* dataPath[SCREW_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/螺杆测量/数据/模拟数据/", //0
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云2/上方两根/", //1
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云3/", //2
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云4/位置1/", //3
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云4/位置2/", //4
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云4/位置2未动螺杆拧进去100mm左右/", //5
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云4/位置2向前100mm螺杆拧进去100mm左右/", //6
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云20260621/另一根螺杆/", //7
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云20260621/拍照点1/", //8
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/螺杆点云20260621/拍照点1xyz移动10mm/", //9
};
SVzNLRange fileIdx[SCREW_TEST_GROUP] = {
{1,4},{1,30},{1,11},
{1,20}, {1,20}, {1,5}, {1,21},
{1,10}, {1,10}, {1,10}
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 9; grp < SCREW_TEST_GROUP; grp++)
{
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =3;
char _scan_file[256];
if(0 == grp)
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
else if( (grp>= 7)&&(grp <= 9))
sprintf_s(_scan_file, "%sLaserline_%d.txt", dataPath[grp], fidx);
else
sprintf_s(_scan_file, "%s%d_LaserData_Jl26C299.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
//转成plyTxt格式
//sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx);
//wdSavePlyTxt(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
double rodDiameter;
if (grp == 0)
rodDiameter = 10.0;
else
rodDiameter = 28.0; //现场螺杆直径28mm
//double rodDiameter = 10.0;
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 30; //45度角
cornerParam.scale = rodDiameter/4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
SSG_outlierFilterParam filterParam;
filterParam.continuityTh = 20.0; //噪声滤除。当相邻点的z跳变大于此门限时检查是否为噪声。若长度小于outlierLen 视为噪声
filterParam.outlierTh = 5;
SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 30;
growParam.yDeviation_max = 5.0;
growParam.maxSkipDistance = 30.0;
growParam.zDeviation_max = 50;//
growParam.minLTypeTreeLen = 50; //mm, 螺杆长度
growParam.minVTypeTreeLen = 50; //mm
bool isHorizonScan = true; //true:激光线平行槽道false:激光线垂直槽道
int errCode = 0;
std::vector<SSX_rodPoseInfo> screwInfo;
sx_hexHeadScrewMeasure(
scanLines,
isHorizonScan, //true:激光线平行槽道false:激光线垂直槽道
cornerParam,
filterParam,
growParam,
rodDiameter,
screwInfo,
&errCode);
long t2 = (long)GetTickCount64();
//输出测试结果
char _out_file[256];
sprintf_s(_out_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD(_out_file, scanLines, screwInfo);
sprintf_s(_out_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputChanneltInfo(_out_file, screwInfo);
if (screwInfo.size() > 0)
{
SVzNL3DPoint zAxis = { 0, 0, 1.0 };
float angle = _computeVecAngle(screwInfo[0].axialDir, zAxis);
printf("%s: %d(ms), errCode=%d, {%f, %f, %f}, 与Z轴夹角=%f \n", _scan_file, (int)(t2 - t1), errCode,
(float)screwInfo[0].center.x, (float)screwInfo[0].center.y, (float)screwInfo[0].center.z, angle);
}
else
printf("%s: %d(ms), errCode=%d\n", _scan_file, (int)(t2 - t1), errCode);
}
}
}
#define LOCATING_PALTE_TEST_GROUP 1
void locatingPlateTest(void)
{
const char* dataPath[LOCATING_PALTE_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/定位盘点云/", //0
};
SVzNLRange fileIdx[LOCATING_PALTE_TEST_GROUP] = {
{1,17},
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 0; grp < LOCATING_PALTE_TEST_GROUP; grp++)
{
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =2;
char _scan_file[256];
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
//转成plyTxt格式
//sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx);
//wdSavePlyTxt(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
double rodDiameter = 10.0;
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 60; //45度角
cornerParam.scale = rodDiameter / 4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
int errCode = 0;
SSX_platePoseInfo centerPose = sx_getLocationPlatePose(
scanLines,
cornerParam,
& errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1));
//输出测试结果
sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD_centerPose(_scan_file, scanLines, centerPose);
sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputPlatePiseInfo(_scan_file, centerPose);
}
}
}
#define NEW_LOCATING_PALTE_TEST_GROUP 1
void newLocatingPlateTest(void)
{
const char* dataPath[NEW_LOCATING_PALTE_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/螺杆测量/配天现场点云/定位盘点云20260621/", //0
};
SVzNLRange fileIdx[NEW_LOCATING_PALTE_TEST_GROUP] = {
{12,13},
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 0; grp < NEW_LOCATING_PALTE_TEST_GROUP; grp++)
{
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =2;
char _scan_file[256];
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
//转成plyTxt格式
//sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx);
//wdSavePlyTxt(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 45; //45度角
cornerParam.scale = 5.0; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
int errCode = 0;
SSX_platePoseInfo centerPose = sx_getLocationPlatePose_new(
scanLines,
cornerParam,
&errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms),errCode=%d\n", _scan_file, (int)(t2 - t1), errCode);
//输出测试结果
sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD_centerPose(_scan_file, scanLines, centerPose);
sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputPlatePiseInfo(_scan_file, centerPose);
}
}
}
;
void _removeNullData(std::vector<std::vector< SVzNL3DPosition>>& scanLines, double _F, std::vector<std::vector< SVzNLPointXYZRGBA>>& scanData)
{
std::vector< SVzNLPointXYZRGBA> validPoints;
for (int line = 0; line < (int)scanLines.size(); line++)
{
for (int j = 0; j < (int)scanLines[line].size(); j++)
{
if (scanLines[line][j].pt3D.z > 1e-4)
{
SVzNLPointXYZRGBA a_pt;
double v = _F * scanLines[line][j].pt3D.y / scanLines[line][j].pt3D.z + 2000;
a_pt.nRGB = (int)(v + 0.5);
a_pt.x = scanLines[line][j].pt3D.x;
a_pt.y = scanLines[line][j].pt3D.y;
a_pt.z = scanLines[line][j].pt3D.z;
validPoints.push_back(a_pt);
}
}
}
std::vector< SVzNLPointXYZRGBA> a_line;
SVzNLPointXYZRGBA pre_pt;
pre_pt.x = 0;
pre_pt.y = 0;
pre_pt.z = 0;
pre_pt.nRGB = -1;
for (int i = 0; i < validPoints.size(); i++)
{
if (validPoints[i].nRGB < (pre_pt.nRGB - 10))
{
if (a_line.size() > 0)
scanData.push_back(a_line);
a_line.clear();
}
a_line.push_back(validPoints[i]);
pre_pt = validPoints[i];
}
if(a_line.size() > 0)
scanData.push_back(a_line);
return;
}
void _convertToGridData_XYZRGB(std::vector<std::vector< SVzNLPointXYZRGBA>>& scanData, double _F, std::vector<std::vector< SVzNL3DPosition>>& gridData)
{
int lineNum = (int)scanData.size();
int min_y = 100000000;
int max_y = -10000000;
int validStartLine = -1;
int validEndLine = -1;
for (int line = 0; line < lineNum; line++)
{
if (scanData[line].size() > 0)
{
if (validStartLine < 0)
{
validStartLine = line;
validEndLine = line;
}
else
validEndLine = line;
}
for (int i = 0; i < (int)scanData[line].size(); i++)
{
SVzNLPointXYZRGBA& a_pt = scanData[line][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;
int vldLineNum = validEndLine - validStartLine + 1;
gridData.resize(vldLineNum);
int pt_counter = max_y - min_y + 1;
for (int i = 0; i < vldLineNum; i++)
{
gridData[i].resize(pt_counter);
for (int j = 0; j < pt_counter; j++)
{
gridData[i][j].nPointIdx = j;
gridData[i][j].pt3D.x = 0;
gridData[i][j].pt3D.y = 0;
gridData[i][j].pt3D.z = 0;
}
}
for (int line = validStartLine; line <= validEndLine; line++)
{
int gridLine = line - validStartLine;
for (int i = 0; i < (int)scanData[line].size(); i++)
{
SVzNLPointXYZRGBA& a_pt = scanData[line][i];
if (a_pt.z > 1e-4)
{
int pt_id = a_pt.nRGB - min_y;
gridData[gridLine][pt_id].pt3D.x = a_pt.x;
gridData[gridLine][pt_id].pt3D.y = a_pt.y;
gridData[gridLine][pt_id].pt3D.z = a_pt.z;
}
}
}
return;
}
#define ROD_POSITION_TEST_GROUP 5
#define TEST_CONVERT_TO_GRID 0
#define TEST_COMPUTE_CALIB_PARA 0
#define TEST_COMPUTE_ROD_POSITION 1
void rodPositionTest(void)
{
#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:/ShangGu/项目/冠钦项目/矩森棒材抓取/空料框及内剩一根棒材/");
char _scan_src_file[256];
double _F = 1219.15; //f
for (int i = 1; i <= 3; i++)
{
//read ply txt
sprintf_s(_scan_src_file, "%sLaserDataRAW_%d.txt", _scan_dir, i);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_src_file, scanLines);
std::vector<std::vector< SVzNLPointXYZRGBA>> scanData;
_removeNullData(scanLines, _F, scanData);
std::vector<std::vector< SVzNL3DPosition>> gridData;
_convertToGridData_XYZRGB(scanData, _F, gridData);
char _out_file[256];
sprintf_s(_out_file, "%sLaserData_%d.txt", _scan_dir, i);
_outputScanDataFile(_out_file, gridData, 0.0f, 0, 0);
printf("%s: convert done!\n", _scan_src_file);
}
printf("all converted done!\n", _scan_src_file);
#endif
#if TEST_COMPUTE_CALIB_PARA
const char* calibDataPath = "F:/ShangGu/项目/冠钦项目/矩森棒材抓取/空料框及内剩一根棒材/调平/位置1/";
char _calib_datafile[256];
sprintf_s(_calib_datafile, "%sGroundData_1.txt", calibDataPath);
int lineNum = 0;
float lineV = 0.0f;
int dataCalib = 0;
int maxTimeStamp = 0;
int clockPerSecond = 0;
std::vector<std::vector< SVzNL3DPosition>> scanData;
wdReadLaserScanPointFromFile_XYZ_vector(_calib_datafile, scanData);
lineNum = (int)scanData.size();
if (scanData.size() > 0)
{
SSG_planeCalibPara calibPara = sx_rodPosition_getBaseCalibPara(scanData);
//结果进行验证
for (int i = 0; i < lineNum; i++)
{
if (i == 14)
int kkk = 1;
//行处理
//调平,去除地面
sx_rodPosition_lineDataR(scanData[i], calibPara.planeCalib, -1);
}
//
char calibFile[250];
sprintf_s(calibFile, "%sground_calib_para.txt", calibDataPath);
_outputCalibPara(calibFile, calibPara);
char _out_file[256];
sprintf_s(_out_file, "%sGroundData_1_calib_verify.txt", calibDataPath);
_outputScanDataFile(_out_file, scanData, lineV, maxTimeStamp, clockPerSecond);
#if 0
for (int fidx = fileIdx[cvtGrp].nMin; fidx <= fileIdx[cvtGrp].nMax; fidx++)
{
//fidx =4;
char _scan_file[256];
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[cvtGrp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
vzReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
if (scanLines.size() == 0)
continue;
lineNum = (int)scanLines.size();
for (int i = 0; i < lineNum; i++)
{
//调平,去除地面
wd_lineDataR(scanLines[i], calibPara.planeCalib, -1);
}
sprintf_s(_scan_file, "%sLaserData_%d_calib_verify.txt", dataPath[cvtGrp], fidx);
int headNullLines = 0;
_outputScanDataFile_vector(_scan_file, scanLines, false, &headNullLines);
}
#endif
printf("%s: calib done!\n", _calib_datafile);
}
#endif
#if TEST_COMPUTE_ROD_POSITION
const char* dataPath[ROD_POSITION_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/测试数据/", //0
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/空料框及内剩一根棒材/", //1
"F:/ShangGu/项目/冠钦项目/矩森棒材抓取/其它尺寸棒材点云/", //2
"F:/ShangGu/项目/冠钦项目/胶布圆棒抓取/模拟测试数据/", //3
"F:/ShangGu/项目/冠钦项目/胶布圆棒抓取/模拟测试数据2/", //4
};
SVzNLRange fileIdx[ROD_POSITION_TEST_GROUP] = {
{1,8}, {1,3}, {1,31},
{1,5},{1,11}
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 0; grp <= 2; 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];
sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
poseCalibPara = _readCalibPara(calibFile);
sprintf_s(calibFile, "%sparameter.txt", dataPath[grp]);
std::vector<SSX_rodParam> rodParas;
if (grp <= 2)
_readRodParas(calibFile, rodParas);
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =5;
char _scan_file[256];
if( (3 == grp) ||(4 == grp))
sprintf_s(_scan_file, "%s%d_LaserData_Hi229156.txt", dataPath[grp], fidx);
else
sprintf_s(_scan_file, "%sLaserData_%d.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
//转成plyTxt格式
//sprintf_s(_scan_file, "%s%d_ply_Hi229229.txt", dataPath[grp], fidx);
//wdSavePlyTxt(_scan_file, scanLines);
long t1 = (long)GetTickCount64();//统计时间
SSX_rodParam rodParam;
if (grp <= 2)
{
rodParam = rodParas[fidx];
}
else
{
rodParam.diameter = 68.0; //圆棒直径
rodParam.len = 187;
}
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 45; //45度角
cornerParam.scale = rodParam.diameter / 4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
SSG_outlierFilterParam filterParam;
filterParam.continuityTh = 5.0; //噪声滤除。当相邻点的z跳变大于此门限时检查是否为噪声。若长度小于outlierLen 视为噪声
filterParam.outlierTh = 5;
SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 5;
growParam.yDeviation_max = 10.0;
growParam.maxSkipDistance = 10.0;
growParam.zDeviation_max = 10.0;//
growParam.minLTypeTreeLen = rodParam.len * 0.75; //mm, 螺杆长度
growParam.minVTypeTreeLen = rodParam.len * 0.75; //mm
bool isHorizonScan = true; //true:激光线平行槽道false:激光线垂直槽道
int errCode = 0;
std::vector<SSX_rodPositionInfo> rodInfo;
sx_rodPositioning(
scanLines,
poseCalibPara,
cornerParam,
filterParam,
growParam,
rodParam,
rodInfo,
&errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms),errCode=%d\n", _scan_file, (int)(t2 - t1),errCode);
//输出测试结果
sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD_rodInfo(_scan_file, scanLines, rodInfo);
sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputRodtInfo(_scan_file, rodInfo);
}
}
#endif
}
int counterValidPts(std::vector<SVzNL3DPosition>& lineData)
{
int num = 0;
for (int i = 0; i < (int)lineData.size(); i++)
{
if (lineData[i].pt3D.z > 1e-4)
num++;
else
{
lineData[i].pt3D = { 0, 0, 0 };
}
}
return num;
}
#define WELD_SEAM_TEST_GROUP 4
void rodWeldSeamPosition_test(void)
{
const char* dataPath[WELD_SEAM_TEST_GROUP] = {
"F:/ShangGu/项目/冠钦项目/筑裕视觉钢结构焊接/视觉照片1/", //0
"F:/ShangGu/项目/冠钦项目/筑裕视觉钢结构焊接/视觉照片2/", //1
"F:/ShangGu/项目/冠钦项目/筑裕视觉钢结构焊接/数据3/特征点1/", //2
"F:/ShangGu/项目/冠钦项目/筑裕视觉钢结构焊接/数据3/特征点2/", //3
};
SVzNLRange fileIdx[WELD_SEAM_TEST_GROUP] = {
{1,20},{1,20},{1,27}, { 1,21 },
};
const char* ver = wd_rodAndBarDetectionVersion();
printf("ver:%s\n", ver);
for (int grp = 2; grp < WELD_SEAM_TEST_GROUP; 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];
//sprintf_s(calibFile, "%sground_calib_para.txt", dataPath[grp]);
//poseCalibPara = _readCalibPara(calibFile);
for (int fidx = fileIdx[grp].nMin; fidx <= fileIdx[grp].nMax; fidx++)
{
//fidx =1;
char _scan_file[256];
sprintf_s(_scan_file, "%s%d_LaserData_groundAdjusted.txt", dataPath[grp], fidx);
std::vector<std::vector< SVzNL3DPosition>> scanLines;
wdReadLaserScanPointFromFile_XYZ_vector(_scan_file, scanLines);
if ((grp == 2) || (grp == 3)) //计算调平矩阵
{
#if 0
std::vector<cv::Point3f> validPts;
std::vector<std::vector< SVzNL3DPosition>> copy_scanLines;
copy_scanLines.resize(scanLines.size());
for (int line = 0; line < (int)scanLines.size(); line++)
{
std::vector< SVzNL3DPosition>& a_line = scanLines[line];
copy_scanLines[line].resize(a_line.size());
for (int j = 0; j < (int)a_line.size(); j++)
{
copy_scanLines[line][j] = a_line[j];
if (a_line[j].pt3D.z > 1e-4)
{
cv::Point3f a_pt = cv::Point3f((float)a_line[j].pt3D.x, (float)a_line[j].pt3D.y, (float)a_line[j].pt3D.z);
validPts.push_back(a_pt);
}
}
}
std::vector<cv::Point3f> out_inliers;
Plane res = ransacFitPlane(validPts, out_inliers);
if (res.C < 0)
{
res.A = -res.A;
res.B = -res.B;
res.C = -res.C;
res.D = -res.D;
}
float meanH = 0;
int counter = 0;
for (int i = 0; i < (int)out_inliers.size(); i++)
{
meanH += out_inliers[i].z;
counter++;
}
//计算投影向量
SVzNL3DPoint vec_1 = { res.A, res.B, res.C };
SVzNL3DPoint vec_2 = { 0, 0, 1.0 };
SSG_planeCalibPara calibPara = wd_computeRTMatrix(vec_1, vec_2);
for (int m = 0; m < 9; m++)
{
poseCalibPara.planeCalib[m] = calibPara.planeCalib[m];
poseCalibPara.invRMatrix[m] = calibPara.invRMatrix[m];
}
poseCalibPara.planeHeight = meanH / counter;
char _out_file[256];
sprintf_s(_out_file, "%s%d_calib_para.txt", dataPath[grp], fidx);
_outputCalibPara(_out_file, poseCalibPara);
sprintf_s(_out_file, "%s%d_LaserData_groundAdjusted.txt", dataPath[grp], fidx);
//if (false == fileExists(_out_file))
{
//输出调平效果
int firstValidLine = -1;
int lastValidLine = -1;
for (int line = 0; line < (int)copy_scanLines.size(); line++)
{
//行处理
//调平,去除地面
double cuttingZ = poseCalibPara.planeHeight - 100;
sx_rodPosition_lineDataR(copy_scanLines[line], poseCalibPara.planeCalib, cuttingZ);
int ptsNum = counterValidPts(copy_scanLines[line]);
if (ptsNum > 10)
{
if (firstValidLine < 0)
firstValidLine = line;
lastValidLine = line;
}
}
if ((lastValidLine > 0) && (lastValidLine < copy_scanLines.size() - 1))
{
copy_scanLines.erase(copy_scanLines.begin() + lastValidLine + 1, copy_scanLines.end());
}
if(firstValidLine > 1)
{
copy_scanLines.erase(copy_scanLines.begin(), copy_scanLines.begin() + firstValidLine - 1);
}
_outputScanDataFile(_out_file, copy_scanLines, 0.0f, 0, 0);
}
#endif
}
long t1 = (long)GetTickCount64();//统计时间
SSX_rodParam rodParam;
rodParam.diameter = 16.0; //钢筋直径
rodParam.len = 50;
SSG_cornerParam cornerParam;
cornerParam.cornerTh = 60; //45度角
cornerParam.scale = rodParam.diameter / 4; // algoParam.bagParam.bagH / 8; // 15; // algoParam.bagParam.bagH / 8;
cornerParam.minEndingGap = 20; // algoParam.bagParam.bagW / 4;
cornerParam.minEndingGap_z = 5.0;
cornerParam.jumpCornerTh_1 = 15; //水平角度,小于此角度视为水平
cornerParam.jumpCornerTh_2 = 60;
SSG_outlierFilterParam filterParam;
filterParam.continuityTh = 4.0; //噪声滤除。当相邻点的z跳变大于此门限时检查是否为噪声。若长度小于outlierLen 视为噪声
filterParam.outlierTh = 4;
SSG_treeGrowParam growParam;
growParam.maxLineSkipNum = 5;
growParam.yDeviation_max = 5.0;
growParam.maxSkipDistance = 20.0;
growParam.zDeviation_max = 5.0;//
growParam.minLTypeTreeLen = 50; //mm, 螺杆长度
growParam.minVTypeTreeLen = 50; //mm
bool isHorizonScan = true; //true:激光线平行槽道false:激光线垂直槽道
double weldSeanRange = 100; //焊缝距钢筋交叉点的范围(最大值)
int errCode = 0;
std::vector<SSX_weldSeamInfo> weldSeamInfo;
sx_rebarWeldSeamPositioning(
scanLines,
poseCalibPara,
cornerParam,
filterParam,
growParam,
rodParam,
weldSeanRange,
weldSeamInfo,
&errCode);
long t2 = (long)GetTickCount64();
printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1));
if (errCode == 0)
{
//输出测试结果
sprintf_s(_scan_file, "%sresult\\%d_result.txt", dataPath[grp], fidx);
_outputRGBDScan_RGBD_weldSeam(_scan_file, scanLines, weldSeamInfo);
sprintf_s(_scan_file, "%sresult\\%d_screw_info.txt", dataPath[grp], fidx);
_outputWeldSeamInfo(_scan_file, weldSeamInfo);
}
}
}
}
typedef enum
{
keSG_测试_配天螺杆定位 = 0,
keSG_测试_配天定位盘定位,
keSG_测试_配天新定位盘定位,
keSG_测试_棒材抓取,
keSG_测试_筑裕钢筋焊缝定位,
} ESG_testMode;
int main()
{
//ESG_testMode testMode = keSG_测试_配天螺杆定位;
//ESG_testMode testMode = keSG_测试_配天定位盘定位;
//ESG_testMode testMode = keSG_测试_配天新定位盘定位;
//ESG_testMode testMode = keSG_测试_棒材抓取;
ESG_testMode testMode = keSG_测试_筑裕钢筋焊缝定位;
if(keSG_测试_配天螺杆定位 == testMode)
screwTest();
else if(keSG_测试_配天定位盘定位 == testMode)
locatingPlateTest();
else if (keSG_测试_配天新定位盘定位 == testMode)
newLocatingPlateTest();
else if(keSG_测试_棒材抓取 == testMode)
rodPositionTest();
else if(keSG_测试_筑裕钢筋焊缝定位 == testMode)
rodWeldSeamPosition_test();
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件