diff --git a/BQ_assemblyPosition/BQ_assemblyPosition.vcxproj b/BQ_assemblyPosition/BQ_assemblyPosition.vcxproj new file mode 100644 index 0000000..fee28df --- /dev/null +++ b/BQ_assemblyPosition/BQ_assemblyPosition.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + 16.0 + Win32Proj + {0e62eee4-abb5-4364-a794-ccffe8815426} + BQassemblyPosition + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + $(SolutionDir)build\$(Platform)\$(Configuration)\ + ..\..\thirdParty\VzNLSDK\Inc;..\..\thirdParty\opencv320\build\include;..\sourceCode;..\sourceCode\inc;$(IncludePath) + + + false + $(SolutionDir)build\$(Platform)\$(Configuration)\ + ..\..\thirdParty\VzNLSDK\Inc;..\..\thirdParty\opencv320\build\include;..\sourceCode;..\sourceCode\inc;$(IncludePath) + + + + Level3 + true + WIN32;_DEBUG;BQASSEMBLYPOSITION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;BQASSEMBLYPOSITION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;_DEBUG;BQASSEMBLYPOSITION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + ..\..\thirdParty\opencv320\build\include;%(AdditionalIncludeDirectories) + + + Windows + true + false + ..\..\thirdParty\opencv320\build\x64\vc14\lib;..\build\x64\Debug;%(AdditionalLibraryDirectories) + opencv_world320d.lib;baseAlgorithm.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;NDEBUG;BQASSEMBLYPOSITION_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + ..\..\thirdParty\opencv320\build\include;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + false + ..\..\thirdParty\opencv320\build\x64\vc14\lib;..\build\x64\Release;%(AdditionalLibraryDirectories) + opencv_world320.lib;baseAlgorithm.lib;%(AdditionalDependencies) + + + + + + \ No newline at end of file diff --git a/BQ_assemblyPosition_test/BQ_assemblyPosition_test.cpp b/BQ_assemblyPosition_test/BQ_assemblyPosition_test.cpp new file mode 100644 index 0000000..b5a7a67 --- /dev/null +++ b/BQ_assemblyPosition_test/BQ_assemblyPosition_test.cpp @@ -0,0 +1,20 @@ +// BQ_assemblyPosition_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +// + +#include + +int main() +{ + std::cout << "Hello World!\n"; +} + +// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 +// 调试程序: F5 或调试 >“开始调试”菜单 + +// 入门使用技巧: +// 1. 使用解决方案资源管理器窗口添加/管理文件 +// 2. 使用团队资源管理器窗口连接到源代码管理 +// 3. 使用输出窗口查看生成输出和其他消息 +// 4. 使用错误列表窗口查看错误 +// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 +// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 diff --git a/BQ_assemblyPosition_test/BQ_assemblyPosition_test.vcxproj b/BQ_assemblyPosition_test/BQ_assemblyPosition_test.vcxproj new file mode 100644 index 0000000..d84f2c0 --- /dev/null +++ b/BQ_assemblyPosition_test/BQ_assemblyPosition_test.vcxproj @@ -0,0 +1,147 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {bc38d1e5-10cb-438b-ac72-6012303ce139} + BQassemblyPositiontest + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/SG_Algorithm.sln b/SG_Algorithm.sln index 85ce659..c32da6c 100644 --- a/SG_Algorithm.sln +++ b/SG_Algorithm.sln @@ -151,6 +151,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gasFillingPortPosition_test EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BQ_assemblyPosition", "BQ_assemblyPosition\BQ_assemblyPosition.vcxproj", "{0E62EEE4-ABB5-4364-A794-CCFFE8815426}" + ProjectSection(ProjectDependencies) = postProject + {95DC3F1A-902A-490E-BD3B-B10463CF0EBD} = {95DC3F1A-902A-490E-BD3B-B10463CF0EBD} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BQ_assemblyPosition_test", "BQ_assemblyPosition_test\BQ_assemblyPosition_test.vcxproj", "{BC38D1E5-10CB-438B-AC72-6012303CE139}" EndProject diff --git a/baseAlgorithm/baseAlgorithm.vcxproj b/baseAlgorithm/baseAlgorithm.vcxproj index 21bd19d..157bced 100644 --- a/baseAlgorithm/baseAlgorithm.vcxproj +++ b/baseAlgorithm/baseAlgorithm.vcxproj @@ -78,12 +78,12 @@ true - ..\..\thirdParty\VzNLSDK\Inc;..\..\thirdParty\opencv320\build\include;..\sourceCode;..\sourceCode\inc;$(IncludePath) + ..\..\thirdParty\VzNLSDK\Inc;..\..\thirdParty\opencv320\build\include;..\sourceCode;..\sourceCode\inc;F:\ShangGu\ProductDev\AlgoDev\thirdParty\PCL 1.12.0\3rdParty\Eigen\eigen3;$(IncludePath) $(SolutionDir)build\$(Platform)\$(Configuration)\ false - ..\..\thirdParty\VzNLSDK\Inc;..\..\thirdParty\opencv320\build\include;..\sourceCode;..\sourceCode\inc;$(IncludePath) + ..\..\thirdParty\VzNLSDK\Inc;..\..\thirdParty\opencv320\build\include;..\sourceCode;..\sourceCode\inc;F:\ShangGu\ProductDev\AlgoDev\thirdParty\PCL 1.12.0\3rdParty\Eigen\eigen3;$(IncludePath) $(SolutionDir)build\$(Platform)\$(Configuration)\ diff --git a/sourceCode/BQ_assemblyPosition.cpp b/sourceCode/BQ_assemblyPosition.cpp new file mode 100644 index 0000000..81407a0 --- /dev/null +++ b/sourceCode/BQ_assemblyPosition.cpp @@ -0,0 +1,442 @@ +#include +#include "SG_baseDataType.h" +#include "SG_baseAlgo_Export.h" +#include "BQ_assemblyPosition_Export.h" +#include +#include + +//version 1.0.0 : base version release to customer +std::string m_strVersion = "1.0.0"; +const char* wd_BQAssemblyPositionVersion(void) +{ + return m_strVersion.c_str(); +} + +//һƽƽ +//пһƽͲοƽƽ棬ߵƽеƽ +//תΪƽƽ淨ΪֱIJ +SSG_planeCalibPara sx_BQ_getBaseCalibPara( + std::vector< std::vector>& scanLines) +{ + return sg_getPlaneCalibPara2(scanLines); +} + +//̬ƽȥ +void sx_BQ_lineDataR( + std::vector< SVzNL3DPosition>& a_line, + const double* camPoseR, + double groundH) +{ + lineDataRT_vector(a_line, camPoseR, groundH); +} + +int _counterLinePtNum(std::vector& lineData) +{ + int ptNum = 0; + for (int i = 0, i_max = (int)lineData.size(); i < i_max; i++) + { + if ((abs(lineData[i].pt3D.z) > 1e-4) || + (abs(lineData[i].pt3D.x > 1e-4)) || + (abs(lineData[i].pt3D.y > 1e-4))) + ptNum++; + } + return ptNum; +} + +bool compareByAngle(const SWD_polarPt& a, const SWD_polarPt& b) { + return a.angle < b.angle; +} + +SSX_BQAssemblyInfo sx_BQ_computeAssemblyInfoFrom3D( + std::vector< std::vector>& scanLines, + const SSG_cornerParam cornerPara, + const SSG_outlierFilterParam filterParam, + SSG_treeGrowParam growParam, + SSG_planeCalibPara groundCalibPara, + SSX_BQAssemblyPara assemblyParam, + int* errCode) +{ + *errCode = 0; + SSX_BQAssemblyInfo assemblyPose; + memset(&assemblyPose, 0, sizeof(SSX_BQAssemblyInfo)); + int lineNum = (int)scanLines.size(); + if (lineNum == 0) + { + *errCode = SG_ERR_3D_DATA_NULL; + return assemblyPose; + } + + //ʼͽĿհɨȥɨ߽ + int validStartLine = -1; + for (int i = 0; i < lineNum; i++) + { + int linePtNum = _counterLinePtNum(scanLines[i]); + if (linePtNum > 0) + { + validStartLine = i; + break; + } + } + int validEndLine = -1; + for (int i = lineNum - 1; i >= 0; i--) + { + int linePtNum = _counterLinePtNum(scanLines[i]); + if (linePtNum > 0) + { + validEndLine = i; + break; + } + } + if ((validStartLine < 0) || (validEndLine < 0)) + { + *errCode = SG_ERR_3D_DATA_NULL; + return assemblyPose; + } + + int linePtNum = (int)scanLines[0].size(); + bool isGridData = true; + + //ӦתǶ + //ֱȡ + std::vector> jumpFeatures_v_raw; + for (int line = 0; line < lineNum; line++) + { + if (line == 250) + int kkk = 1; + + std::vector& lineData = scanLines[line]; + if (linePtNum != (int)lineData.size()) + isGridData = false; + + //˲˳쳣 + sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], linePtNum, filterParam); + + std::vector line_features; + int dataSize = (int)lineData.size(); + sg_getLineCornerFeature_BQ( + &lineData[0], + dataSize, + line, + groundCalibPara.planeHeight, + cornerPara, //scaleͨȡbagH1/4 + line_features); + jumpFeatures_v_raw.push_back(line_features); + } + + if (false == isGridData)//ݲʽ + { + *errCode = SG_ERR_NOT_GRID_FORMAT; + return assemblyPose; + } + + //ˮƽɨ + std::vector> hLines_raw; + hLines_raw.resize(linePtNum); + for (int i = 0; i < linePtNum; i++) + hLines_raw[i].resize(lineNum); + for (int line = 0; line < lineNum; line++) + { + for (int j = 0; j < linePtNum; j++) + { + scanLines[line][j].nPointIdx = 0; //ԭʼݵ0תʹã + hLines_raw[j][line] = scanLines[line][j]; + hLines_raw[j][line].pt3D.x = scanLines[line][j].pt3D.y; + hLines_raw[j][line].pt3D.y = scanLines[line][j].pt3D.x; + } + } + //ˮƽarcȡ + std::vector> jumpFeatures_h_raw; + int lineNum_h_raw = (int)hLines_raw.size(); + for (int line = 0; line < lineNum_h_raw; line++) + { + if (line == 416) + int kkk = 1; + std::vector& lineData = hLines_raw[line]; + //˲˳쳣 + int ptNum = (int)lineData.size(); + sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], ptNum, filterParam); + + std::vector line_features; + int dataSize = (int)lineData.size(); + sg_getLineCornerFeature_BQ( + &hLines_raw[line][0], + dataSize, + line, + groundCalibPara.planeHeight, + cornerPara, //scaleͨȡbagH1/4 + line_features); + jumpFeatures_h_raw.push_back(line_features); + } + + //˳ + //ֱ߷ + std::vector v_trees; + for (int line = 0; line < lineNum; line++) + { + bool isLastLine = false; + if (line == lineNum - 1) + isLastLine = true; + std::vector& a_lineJumpFeature = jumpFeatures_v_raw[line]; + if (a_lineJumpFeature.size() > 0) + int kkk = 1; + if (line == 202) + int kkk = 1; + sg_lineFeaturesGrowing( + line, + isLastLine, + a_lineJumpFeature, + v_trees, + growParam); + } + + //ˮƽɨ˶ + std::vector h_trees; + for (int line = 0; line < lineNum_h_raw; line++) + { + if (line == 650) + int kkk = 1; + bool isLastLine = false; + if (line == lineNum_h_raw - 1) + isLastLine = true; + std::vector& a_lineJumpFeature = jumpFeatures_h_raw[line]; + sg_lineFeaturesGrowing( + line, + isLastLine, + a_lineJumpFeature, + h_trees, + growParam); + } + + std::vector polarPoints; + for (int i = 0, i_max = (int)v_trees.size(); i < i_max; i++) + { + SSG_featureTree* a_vTree = &v_trees[i]; + //ԭʼϱǣͬʱMaskϱ + for (int j = 0, j_max = (int)a_vTree->treeNodes.size(); j < j_max; j++) + { + int lineIdx = a_vTree->treeNodes[j].jumpPos2D.x; + int ptIdx = a_vTree->treeNodes[j].jumpPos2D.y; + if (scanLines[lineIdx][ptIdx].nPointIdx >= 0) + { + SWD_polarPt a_polarPt; + a_polarPt.lineIdx = lineIdx; + a_polarPt.ptIdx = ptIdx; + a_polarPt.R = 0; + a_polarPt.angle = 0; + a_polarPt.x = scanLines[lineIdx][ptIdx].pt3D.x; + a_polarPt.y = scanLines[lineIdx][ptIdx].pt3D.y; + a_polarPt.z = scanLines[lineIdx][ptIdx].pt3D.z; + polarPoints.push_back(a_polarPt); + scanLines[lineIdx][ptIdx].nPointIdx = -1; + } + } + } + for (int i = 0, i_max = (int)h_trees.size(); i < i_max; i++) + { + SSG_featureTree* a_hTree = &h_trees[i]; + //ԭʼϱǣͬʱMaskϱ + for (int j = 0, j_max = (int)a_hTree->treeNodes.size(); j < j_max; j++) + { + int lineIdx = a_hTree->treeNodes[j].jumpPos2D.y; + int ptIdx = a_hTree->treeNodes[j].jumpPos2D.x; + if (scanLines[lineIdx][ptIdx].nPointIdx >= 0) + { + SWD_polarPt a_polarPt; + a_polarPt.lineIdx = lineIdx; + a_polarPt.ptIdx = ptIdx; + a_polarPt.cptIndex = -1; + a_polarPt.R = 0; + a_polarPt.angle = 0; + a_polarPt.x = scanLines[lineIdx][ptIdx].pt3D.x; + a_polarPt.y = scanLines[lineIdx][ptIdx].pt3D.y; + a_polarPt.z = scanLines[lineIdx][ptIdx].pt3D.z; + polarPoints.push_back(a_polarPt); + scanLines[lineIdx][ptIdx].nPointIdx = -1; + } + } + } + + //㼸 + int contourPtSize = (int)polarPoints.size(); + if (contourPtSize == 0) + { + *errCode = SX_ERR_ZERO_CONTOUR_PT; + return assemblyPose; + } + double center_x = 0; + double center_y = 0; + for (int pi = 0; pi < contourPtSize; pi++) + { + center_x += polarPoints[pi].x; + center_y += polarPoints[pi].y; + } + center_x = center_x / (double)contourPtSize; + center_y = center_y / (double)contourPtSize; + //㼫RTheta + for (int pi = 0; pi < contourPtSize; pi++) + { + double angle = atan2(polarPoints[pi].y - center_y, polarPoints[pi].x - center_x); + angle = (angle / PI) * 180 + 180.0; + double R = sqrt(pow(polarPoints[pi].y - center_y, 2) + pow(polarPoints[pi].x - center_x, 2)); + polarPoints[pi].R = R; + polarPoints[pi].angle = angle; + } + //ǶȴС + std::sort(polarPoints.begin(), polarPoints.end(), compareByAngle); + for (int pi = 0; pi < contourPtSize; pi++) + polarPoints[pi].cptIndex = pi; // index + + //ȡRֵ + double minR = -1, maxR = -1; //СRûз֧minRmaxRСʱΪԲλ8Σûз֧ + int minRPos = -1; + std::vector polarRPeakPts; + int winSize = contourPtSize / 36; //+-10ȷΧ + if (winSize < 5) + winSize = 5; + for (int pi = 0; pi < contourPtSize; pi++) + { + double currR = polarPoints[pi].R; + if (minR < 0) + { + minR = currR; + maxR = currR; + minRPos = pi; + } + else + { + minRPos = minR > currR ? pi : minRPos; + minR = minR > currR ? currR : minR; + maxR = maxR < currR ? currR : maxR; + } + bool isPeak = true; + for (int k = -winSize; k <= winSize; k++) + { + int idx = (pi + k + contourPtSize) % contourPtSize; //Ͳνṹ + if (polarPoints[idx].R > currR) + { + isPeak = false; + break; + } + } + if (true == isPeak) + polarRPeakPts.push_back(polarPoints[pi]); + } + + double ratio_MaxMin = maxR / minR; + bool hasBranch = ratio_MaxMin < 1.25 ? false : true; + + std::vector validPolarRPeakPts; + std::vector polarPeakInfo; + int pkId = 0; + //ԲεļֵƫƣԲҲγɼֵݼֵL=ֱ߶γȹɵŽж + double arcAngleChkLen = 100; //ԲŽǵij߶ + for (int i = 0, i_max = (int)polarRPeakPts.size(); i < i_max; i++) + { + int ptidx = polarRPeakPts[i].cptIndex; + double px, py, pz; + px = polarRPeakPts[i].x; + py = polarRPeakPts[i].y; + + int LL1 = -1; + int halfLL1 = -1; + for (int j = ptidx - 1; j > -contourPtSize; j--) + { + int idx = (j + contourPtSize) % contourPtSize; //Ͳνṹ + double cx = polarPoints[idx].x; + double cy = polarPoints[idx].y; + double len = sqrt(pow(px - cx, 2) + pow(py - cy, 2)); + if (len < arcAngleChkLen) + halfLL1 = idx; + if (len > (assemblyParam.lineLen)) + { + LL1 = idx; + break; + } + } + + int LL2 = -1; + int halfLL2 = -1; + for (int j = ptidx + 1; j < contourPtSize * 2; j++) + { + int idx = j % contourPtSize; //Ͳνṹ + double cx = polarPoints[idx].x; + double cy = polarPoints[idx].y; + double len = sqrt(pow(px - cx, 2) + pow(py - cy, 2)); + if (len < arcAngleChkLen) + halfLL2 = idx; + if (len > (assemblyParam.lineLen)) + { + LL2 = idx; + break; + } + } + + if ((LL1 >= 0) && (LL2 >= 0)) + { + double len1 = sqrt(pow(px - polarPoints[halfLL1].x, 2) + pow(py - polarPoints[halfLL1].y, 2)); + double len2 = sqrt(pow(px - polarPoints[halfLL2].x, 2) + pow(py - polarPoints[halfLL2].y, 2)); + double len3 = sqrt(pow(polarPoints[halfLL1].x - polarPoints[halfLL2].x, 2) + + pow(polarPoints[halfLL1].y - polarPoints[halfLL2].y, 2)); + double cosTheta = (len1 * len1 + len2 * len2 - len3 * len3) / (2 * len1 * len2); + double theta = acos(cosTheta) * 180.0 / PI; + if (theta < 150) + { + SWD_polarPeakInfo a_pkInfo; + a_pkInfo.cptIndex = ptidx; + a_pkInfo.L1_ptIndex = LL1; + a_pkInfo.L2_ptIndex = LL2; + a_pkInfo.cornerAngle = theta; + a_pkInfo.cornerDir = 0; + polarRPeakPts[i].cptIndex = ptidx; + polarRPeakPts[i].pkId = pkId; + pkId++; + validPolarRPeakPts.push_back(polarRPeakPts[i]); + polarPeakInfo.push_back(a_pkInfo); + } + } + } + //ι + if (validPolarRPeakPts.size() != 4) + { + *errCode = SX_ERR_INVLID_RPEAK_NUM; + return assemblyPose; + } + + //ȡXᣬ̱YᣬΪZᣬĵΪO + std::vector sidePts_1; + std::vector sidePts_2; + std::vector sidePts_3; + std::vector sidePts_4; + return assemblyPose; +} + +//Mark㹤λú̬ +SSX_BQAssemblyInfo sx_BQ_computeAssemblyInfoFromMark( + SSX_BQAssemblyInfo originPos, + std::vector originMarkPos, + std::vector currMarkPos, + int* errCode) +{ + *errCode = 0; + SSX_BQAssemblyInfo resultPos; + memset(&resultPos, 0, sizeof(SSX_BQAssemblyInfo)); + if ((originMarkPos.size() < 3) || (currMarkPos.size() < 3)) + { + *errCode = SX_ERR_INVLID_MARK_NUM; + return resultPos; + } + + cv::Mat R, T; //תƽ + cv::Point3d C_origin, C_curr; // + caculateRT(originMarkPos, currMarkPos, R, T, C_origin, C_curr); + + // 5. Pn + pointRT(R, T, C_origin, C_curr, originPos.O, resultPos.O); + pointRT(R, T, C_origin, C_curr, originPos.X, resultPos.X); + pointRT(R, T, C_origin, C_curr, originPos.Y, resultPos.Y); + pointRT(R, T, C_origin, C_curr, originPos.Z, resultPos.Z); + return resultPos; +} + + + diff --git a/sourceCode/BQ_assemblyPosition_Export.h b/sourceCode/BQ_assemblyPosition_Export.h new file mode 100644 index 0000000..d431473 --- /dev/null +++ b/sourceCode/BQ_assemblyPosition_Export.h @@ -0,0 +1,49 @@ +#pragma once + +#include "SG_algo_Export.h" +#include + +#define _OUTPUT_DEBUG_DATA 1 + +typedef struct +{ + int type; // + double lineLen; //ֱ߶γ +}SSX_BQAssemblyPara; + +typedef struct +{ + int type; // + cv::Point3d O; //ĵ + cv::Point3d X; //ϵOX + cv::Point3d Y; //ϵOY + cv::Point3d Z; //ϵOZ +}SSX_BQAssemblyInfo; + +//汾 +SG_APISHARED_EXPORT const char* wd_BQAssemblyPositionVersion(void); + +//һƽƽ +//пһƽͲοƽƽ棬ߵƽеƽ +//תΪƽƽ淨ΪֱIJ +SG_APISHARED_EXPORT SSG_planeCalibPara sx_BQ_getBaseCalibPara( + std::vector< std::vector>& scanLines); + +//̬ƽȥ +SG_APISHARED_EXPORT void sx_BQ_lineDataR( + std::vector< SVzNL3DPosition>& a_line, + const double* camPoseR, + double groundH); + +//ȡǵ㼰λϢ +SG_APISHARED_EXPORT SSX_BQAssemblyInfo sx_BQ_getAssemblyInfo( + std::vector< std::vector>& scanLines, + const SSG_cornerParam cornerPara, + const SSG_outlierFilterParam filterParam, + SSG_treeGrowParam growParam, + SSG_planeCalibPara groundCalibPara, + SSX_BQAssemblyPara assemblyParam, + int* errCode); + + + diff --git a/sourceCode/BQ_workpieceCornerExtraction.cpp b/sourceCode/BQ_workpieceCornerExtraction.cpp index f9512c8..6c8dbc7 100644 --- a/sourceCode/BQ_workpieceCornerExtraction.cpp +++ b/sourceCode/BQ_workpieceCornerExtraction.cpp @@ -163,29 +163,6 @@ typedef struct SVzNL3DPoint edge_link2_ends[2]; }SSX_featureContour; -typedef struct -{ - int pkId; - int lineIdx; - int ptIdx; - int cptIndex; //Բɨϵĵ - //double cornerAngle; //ԵΪĵҵļн - double R; - double angle; - double x; - double y; - double z; -}SWD_polarPt; - -typedef struct -{ - int cptIndex; - int L1_ptIndex; - int L2_ptIndex; - double cornerAngle; - int cornerDir; -}SWD_polarPeakInfo; - typedef struct { double angle; diff --git a/sourceCode/SG_baseAlgo_Export.h b/sourceCode/SG_baseAlgo_Export.h index 7fab3a8..109ed8b 100644 --- a/sourceCode/SG_baseAlgo_Export.h +++ b/sourceCode/SG_baseAlgo_Export.h @@ -538,4 +538,17 @@ SG_APISHARED_EXPORT void wd_seedWatershed( SG_APISHARED_EXPORT void wd_noiseFilter( std::vector< std::vector>& scanLines, const SSG_outlierFilterParam filterParam, - int* errCode); \ No newline at end of file + int* errCode); + +// Eigenʵ֣pts1pts2תƽƾ +//Ҫ +SG_APISHARED_EXPORT void caculateRT( + const std::vector& pts1, + const std::vector& pts2, + cv::Mat& R, cv::Mat& T, + cv::Point3d& C1, cv::Point3d& C2); + +//תƽƺλ +SG_APISHARED_EXPORT void pointRT(const cv::Mat& R, const cv::Mat& T, + const cv::Point3d& originPt, const cv::Point3d& rtOriginPT, //RT(תƽƣǰ + const cv::Point3d& pt, cv::Point3d& rtPt); //RTǰĵ diff --git a/sourceCode/SG_baseDataType.h b/sourceCode/SG_baseDataType.h index 6c05012..b7dec1f 100644 --- a/sourceCode/SG_baseDataType.h +++ b/sourceCode/SG_baseDataType.h @@ -501,4 +501,27 @@ typedef struct { SVzNL3DPoint pt1; SVzNL3DPoint pt2; -}SWD_3DPointPair; \ No newline at end of file +}SWD_3DPointPair; + +typedef struct +{ + int pkId; + int lineIdx; + int ptIdx; + int cptIndex; //Բɨϵĵ + //double cornerAngle; //ԵΪĵҵļн + double R; + double angle; + double x; + double y; + double z; +}SWD_polarPt; + +typedef struct +{ + int cptIndex; + int L1_ptIndex; + int L2_ptIndex; + double cornerAngle; + int cornerDir; +}SWD_polarPeakInfo; diff --git a/sourceCode/SG_baseFunc.cpp b/sourceCode/SG_baseFunc.cpp index 1a61b98..8cfbee9 100644 --- a/sourceCode/SG_baseFunc.cpp +++ b/sourceCode/SG_baseFunc.cpp @@ -7,6 +7,7 @@ #include #include +#include SVzNL3DRangeD sg_getScanDataROI( //ɨROI @@ -2426,3 +2427,86 @@ void pointClout2DProjection( } } } + +//ԿռӦתƽƾ +// Eigenʵ +void caculateRT( + const std::vector& pts1, + const std::vector& pts2, + cv::Mat& R, cv::Mat& T, + cv::Point3d& C1, cv::Point3d& C2) +{ + //1 ĵ + cv::Point3d p1, p2; + int N = pts1.size(); + for (int i = 0; i < N; i++) + { + p1 += pts1[i]; + p2 += pts2[i]; + } + p1 = cv::Point3d(cv::Vec3d(p1) / N); + p2 = cv::Point3d(cv::Vec3d(p2) / N); + C1 = p1; + C2 = p2; + // 2õȥ + std::vector q1(N), q2(N); + for (int i = 0; i < N; i++) + { + q1[i] = pts1[i] - p1; + q2[i] = pts2[i] - p2; + } + + //3Ҫֵֽ W = sum(qi * qiת) compute q1*q2^T + Eigen::Matrix3d W = Eigen::Matrix3d::Zero(); + for (int i = 0; i < N; i++) + W += Eigen::Vector3d(q1[i].x, q1[i].y, q1[i].z) * Eigen::Vector3d(q2[i].x, q2[i].y, q2[i].z).transpose(); + + // 4 W SVD ֵֽ + Eigen::JacobiSVD svd(W, Eigen::ComputeFullU | Eigen::ComputeFullV); + Eigen::Matrix3d U = svd.matrixU(); + Eigen::Matrix3d V = svd.matrixV(); + + // 5ת ƽƾ R t, R= V *M* UT + double det = (U * V.transpose()).determinant(); + Eigen::Matrix3d M; + M << 1, 0, 0, 0, 1, 0, 0, 0, det; + + Eigen::Matrix3d R_ = V * M * (U.transpose()); + + // t = p' - R * p + Eigen::Vector3d t_ = Eigen::Vector3d(p2.x, p2.y, p2.z) - R_ * Eigen::Vector3d(p1.x, p1.y, p1.z); + + // 6ʽת convert to cv::Mat + R = (cv::Mat_(3, 3) << + R_(0, 0), R_(0, 1), R_(0, 2), + R_(1, 0), R_(1, 1), R_(1, 2), + R_(2, 0), R_(2, 1), R_(2, 2) + ); + + T = (cv::Mat_(3, 1) << t_(0, 0), t_(1, 0), t_(2, 0)); + return; +} + +//תƽƺλ +void pointRT(const cv::Mat& R, const cv::Mat& T, + const cv::Point3d& originPt, const cv::Point3d& rtOriginPT, //RT(תƽƣǰ + const cv::Point3d& pt, cv::Point3d& rtPt) //RTǰĵ +{ + Eigen::Matrix3d _R; + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + _R(i, j) = R.at(i, j); + } + } + Eigen::Vector3d _T = Eigen::Vector3d(T.at(0, 0), T.at(1, 0), T.at(2, 0)); + + Eigen::Vector3d vec_origin = Eigen::Vector3d(originPt.x, originPt.y, originPt.z); + Eigen::Vector3d vec_rtOrigin = Eigen::Vector3d(rtOriginPT.x, rtOriginPT.y, rtOriginPT.z); + Eigen::Vector3d vec_pt = Eigen::Vector3d(pt.x, pt.y, pt.z); + Eigen::Vector3d result = _R * (vec_pt - vec_origin) + vec_rtOrigin; + + rtPt.x = result(0); + rtPt.x = result(1); + rtPt.x = result(2); + return; +} diff --git a/sourceCode/SG_errCode.h b/sourceCode/SG_errCode.h index 0d2767c..1266374 100644 --- a/sourceCode/SG_errCode.h +++ b/sourceCode/SG_errCode.h @@ -16,6 +16,7 @@ #define SX_ERR_ZERO_CONTOUR_PT -2005 #define SX_ERR_INVLID_RPEAK_NUM -2006 #define SX_ERR_INVLID_RPEAK_PAIR -2007 +#define SX_ERR_INVLID_MARK_NUM -2008 //ץȡ #define SX_ERR_INVLID_CUTTING_Z -2101 @@ -23,3 +24,4 @@ // #define SX_BAG_TRAY_EMPTY -2201 + diff --git a/sourceCode/WD_bottleCapQualityCheck.cpp b/sourceCode/WD_bottleCapQualityCheck.cpp new file mode 100644 index 0000000..fa07438 --- /dev/null +++ b/sourceCode/WD_bottleCapQualityCheck.cpp @@ -0,0 +1,12 @@ +#include +#include "SG_baseDataType.h" +#include "SG_baseAlgo_Export.h" +#include "WD_bottleCapQualityCheck_Export.h" +#include +#include + +void wd_getBottleCapQualtiy( + std::vector< std::vector>& scanLines) +{ + return; +} \ No newline at end of file diff --git a/sourceCode/WD_bottleCapQualityCheck_Export.h b/sourceCode/WD_bottleCapQualityCheck_Export.h new file mode 100644 index 0000000..fa598a1 --- /dev/null +++ b/sourceCode/WD_bottleCapQualityCheck_Export.h @@ -0,0 +1,14 @@ +#pragma once + +#if defined(SG_API_LIBRARY) +# define SG_APISHARED_EXPORT __declspec(dllexport) +#else +# define SG_APISHARED_EXPORT __declspec(dllimport) +#endif + +#include "SG_baseDataType.h" +#include +#include + +SG_APISHARED_EXPORT void wd_getBottleCapQualtiy( + std::vector< std::vector>& scanLines);