// bagPositioning_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include #include #include #include #include #include "direct.h" #include #include "SG_bagPositioning_Export.h" #include #include SVzNL3DPoint _ptRotate(SVzNL3DPoint pt3D, double matrix3d[9]) { SVzNL3DPoint _r_pt; _r_pt.x = pt3D.x * matrix3d[0] + pt3D.y * matrix3d[1] + pt3D.z * matrix3d[2]; _r_pt.y = pt3D.x * matrix3d[3] + pt3D.y * matrix3d[4] + pt3D.z * matrix3d[5]; _r_pt.z = pt3D.x * matrix3d[6] + pt3D.y * matrix3d[7] + pt3D.z * matrix3d[8]; return _r_pt; } #define DATA_VER_OLD 0 #define DATA_VER_NEW 1 #define DATA_VER_FROM_CUSTOM 2 #define VZ_LASER_LINE_PT_MAX_NUM 4096 SVzNLXYZRGBDLaserLine* vzReadLaserScanPointFromFile_XYZRGB(const char* fileName, int* scanLineNum, float* scanV, int* dataCalib, int* scanMaxStamp, int* canClockUnit) { SVzNLXYZRGBDLaserLine* _scanLines = NULL; return _scanLines; } SVzNL3DLaserLine* vzReadLaserScanPointFromFile_XYZ(const char* fileName, int* scanLineNum, float* scanV, int* dataCalib, int* scanMaxStamp, int* canClockUnit) { SVzNL3DLaserLine* _scanLines = NULL; return _scanLines; } SVzNL3DLaserLine* _convertToGridData_XYZRGB(SVzNLXYZRGBDLaserLine* laser3DPoints, int lineNum, double _F, double* camPoseR, int* outLineNum) { SVzNL3DLaserLine* gridData = nullptr; return gridData; } 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 _outputScanDataFile_self(char* fileName, SVzNL3DLaserLine* scanData, int lineNum, float lineV, int maxTimeStamp, int clockPerSecond) { } typedef struct { int r; int g; int b; }SG_color; void _outputScanDataFile_RGBD_obj(char* fileName, SVzNL3DLaserLine* scanData, int lineNum, float lineV, int maxTimeStamp, int clockPerSecond, std::vector& objOps) { } void _outputScanDataFile_RGBD_sideBagObj(char* fileName, SVzNL3DLaserLine* scanData, int lineNum, float lineV, int maxTimeStamp, int clockPerSecond, std::vector& objOps) { } void EulerRpyToRotation1(double rpy[3], double matrix3d[9]) { double cos0 = cos(rpy[0]*PI/180); double sin0 = sin(rpy[0]*PI/180); double cos1 = cos(rpy[1]*PI/180); double sin1 = sin(rpy[1]*PI/180); double cos2 = cos(rpy[2]*PI/180); double sin2 = sin(rpy[2]*PI/180); matrix3d[0] = cos2 * cos1; matrix3d[1] = cos2 * sin1 * sin0 - sin2 * cos0; matrix3d[2] = cos2 * sin1 * cos0 + sin2 * sin0; matrix3d[3] = sin2 * cos1; matrix3d[4] = sin2 * sin1 * sin0 + cos2 * cos0; matrix3d[5] = sin2 * sin1 * cos0 - cos2 * sin0; matrix3d[6] = -sin1; matrix3d[7] = cos1 * sin0; matrix3d[8] = cos1 * cos0; return; } void _rotateCloudPts(SVzNL3DLaserLine* scanData, int lineNum, double matrix3d[9], std::vector>& rotateLines, SVzNLRangeD* rx_range, SVzNLRangeD* ry_range) { rx_range->min = 0; rx_range->max = -1; ry_range->min = 0; ry_range->max = -1; for (int line = 0; line < lineNum; line++) { std::vector< SVzNL3DPosition> linePts; for (int i = 0; i < scanData[line].nPositionCnt; i++) { SVzNL3DPosition* pt3D = &scanData[line].p3DPosition[i]; if (pt3D->pt3D.z < 1e-4) continue; SVzNL3DPosition r_pt; r_pt.pt3D = _ptRotate(pt3D->pt3D, matrix3d); r_pt.nPointIdx = pt3D->nPointIdx; if (rx_range->max < rx_range->min) { rx_range->min = r_pt.pt3D.x; rx_range->max = r_pt.pt3D.x; } else { if (rx_range->min > r_pt.pt3D.x) rx_range->min = r_pt.pt3D.x; if (rx_range->max < r_pt.pt3D.x) rx_range->max = r_pt.pt3D.x; } if (ry_range->max < ry_range->min) { ry_range->min = r_pt.pt3D.y; ry_range->max = r_pt.pt3D.y; } else { if (ry_range->min > r_pt.pt3D.y) ry_range->min = r_pt.pt3D.y; if (ry_range->max < r_pt.pt3D.y) ry_range->max = r_pt.pt3D.y; } linePts.push_back(r_pt); } rotateLines.push_back(linePts); } } void _XOYprojection(cv::Mat& img, std::vector>& dataLines, std::vector& objOps, const double x_scale, const double y_scale, const SVzNLRangeD x_range, const SVzNLRangeD y_range, bool drawDirAngle) { int x_skip = 16; int y_skip = 16; cv::Vec3b rgb = cv::Vec3b(0, 0, 0); cv::Vec3b objColor[8] = { {245,222,179},//淡黄色 {210,105, 30},//巧克力色 {240,230,140},//黄褐色 {135,206,235},//天蓝色 {250,235,215},//古董白 {189,252,201},//薄荷色 {221,160,221},//梅红色 {188,143,143},//玫瑰红色 }; int size = 1; for (int line = 0; line < dataLines.size(); line++) { std::vector< SVzNL3DPosition>& a_line = dataLines[line]; for (int i = 0; i < a_line.size(); i++) { SVzNL3DPosition* pt3D = &a_line[i]; if (pt3D->pt3D.z < 1e-4) continue; int vType = pt3D->nPointIdx & 0xff; int hType = vType >> 4; int objId = (pt3D->nPointIdx >> 16) & 0xff; vType = vType & 0x0f; if (LINE_FEATURE_L_JUMP_H2L == vType) { rgb = { 255, 97, 0 }; size = 2; } else if (LINE_FEATURE_L_JUMP_L2H == vType) { rgb = { 255, 255, 0 }; size = 2; } else if (LINE_FEATURE_V_SLOPE == vType) { rgb = { 255, 0, 255 }; size = 2; } else if (LINE_FEATURE_L_SLOPE_H2L == vType) { rgb = { 160, 82, 45 }; size = 2; } else if ((LINE_FEATURE_LINE_ENDING_0 == vType) || (LINE_FEATURE_LINE_ENDING_1 == vType)) { rgb = { 255, 0, 0 }; size = 2; } else if (LINE_FEATURE_L_SLOPE_L2H == vType) { rgb = { 233, 150, 122 }; size = 2; } else if (LINE_FEATURE_L_JUMP_H2L == hType) { rgb = { 0, 0, 255 }; size = 2; } else if (LINE_FEATURE_L_JUMP_L2H == hType) { rgb = { 0, 255, 255 }; size = 2; } else if (LINE_FEATURE_V_SLOPE == hType) { rgb = { 0, 255, 0 }; size = 2; } else if (LINE_FEATURE_L_SLOPE_H2L == hType) { rgb = { 85, 107, 47 }; size = 2; } else if (LINE_FEATURE_L_SLOPE_L2H == hType) { rgb = { 0, 255, 154 }; size = 2; } else if ((LINE_FEATURE_LINE_ENDING_0 == hType) || (LINE_FEATURE_LINE_ENDING_1 == hType)) { rgb = { 255, 0, 0 }; size = 2; } else if (objId > 0) //目标 { rgb = objColor[objId % 8]; size = 1; } else { rgb = { 60, 60, 60 }; size = 1; } double x = pt3D->pt3D.x; double y = pt3D->pt3D.y; int px = (int)((x - x_range.min) / x_scale + x_skip); int py = (int)((y - y_range.min) / y_scale + y_skip); if (size == 1) img.at(py, px) = cv::Vec3b(rgb[2], rgb[1], rgb[0]); else cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), -1); } } if (objOps.size() > 0) { for (int i = 0; i < objOps.size(); i++) { if (i == 0) { rgb = { 255, 0, 0 }; size = 20; } else { rgb = { 255, 255, 0 }; size = 10; } int px = (int)((objOps[i].centerPos.x - x_range.min) / x_scale + x_skip); int py = (int)((objOps[i].centerPos.y - y_range.min) / y_scale + y_skip); cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), -1); if (true == drawDirAngle) { //画线 double R = 100; const double deg2rad = PI / 180.0; const double yaw = objOps[i].centerPos.z_yaw * deg2rad; double cy = cos(yaw); double sy = sin(yaw); double x1 = objOps[i].centerPos.x + R * cy; double y1 = objOps[i].centerPos.y - R * sy; double x2 = objOps[i].centerPos.x - R * cy; double y2 = objOps[i].centerPos.y + R * sy; int px1 = (int)((x1 - x_range.min) / x_scale + x_skip); int py1 = (int)((y1 - y_range.min) / y_scale + y_skip); int px2 = (int)((x2 - x_range.min) / x_scale + x_skip); int py2 = (int)((y2 - y_range.min) / y_scale + y_skip); cv::line(img, cv::Point(px1, py1), cv::Point(px2, py2), cv::Scalar(rgb[2], rgb[1], rgb[0]), 2); } } } } void _XOYprojection_sideBagInfo(cv::Mat& img, std::vector>& dataLines, std::vector& objOps, const double x_scale, const double y_scale, const SVzNLRangeD x_range, const SVzNLRangeD y_range) { int x_skip = 16; int y_skip = 16; cv::Vec3b rgb = cv::Vec3b(0, 0, 0); cv::Vec3b objColor[8] = { {245,222,179},//淡黄色 {210,105, 30},//巧克力色 {240,230,140},//黄褐色 {135,206,235},//天蓝色 {250,235,215},//古董白 {189,252,201},//薄荷色 {221,160,221},//梅红色 {188,143,143},//玫瑰红色 }; int size = 1; for (int line = 0; line < dataLines.size(); line++) { std::vector< SVzNL3DPosition>& a_line = dataLines[line]; for (int i = 0; i < a_line.size(); i++) { SVzNL3DPosition* pt3D = &a_line[i]; if (pt3D->pt3D.z < 1e-4) continue; int vType = pt3D->nPointIdx & 0xff; int hType = vType >> 4; int objId = (pt3D->nPointIdx >> 16) & 0xffff; vType = vType & 0x0f; if (LINE_FEATURE_L_JUMP_H2L == vType) { rgb = { 255, 97, 0 }; size = 2; } else if (LINE_FEATURE_L_JUMP_L2H == vType) { rgb = { 255, 255, 0 }; size = 2; } else if (LINE_FEATURE_V_SLOPE == vType) { rgb = { 255, 0, 255 }; size = 2; } else if (LINE_FEATURE_L_SLOPE_H2L == vType) { rgb = { 160, 82, 45 }; size = 2; } else if ((LINE_FEATURE_LINE_ENDING_0 == vType) || (LINE_FEATURE_LINE_ENDING_1 == vType)) { rgb = { 255, 0, 0 }; size = 2; } else if (LINE_FEATURE_L_SLOPE_L2H == vType) { rgb = { 233, 150, 122 }; size = 2; } else if (LINE_FEATURE_L_JUMP_H2L == hType) { rgb = { 0, 0, 255 }; size = 2; } else if (LINE_FEATURE_L_JUMP_L2H == hType) { rgb = { 0, 255, 255 }; size = 2; } else if (LINE_FEATURE_V_SLOPE == hType) { rgb = { 0, 255, 0 }; size = 2; } else if (LINE_FEATURE_L_SLOPE_H2L == hType) { rgb = { 85, 107, 47 }; size = 2; } else if (LINE_FEATURE_L_SLOPE_L2H == hType) { rgb = { 0, 255, 154 }; size = 2; } else if ((LINE_FEATURE_LINE_ENDING_0 == hType) || (LINE_FEATURE_LINE_ENDING_1 == hType)) { rgb = { 255, 0, 0 }; size = 2; } else if ( (objId > 0) &&( objId< 1000)) //目标 { rgb = objColor[objId % 8]; size = 3; } else { rgb = { 150, 150, 150 }; size = 1; } double x = pt3D->pt3D.x; double y = pt3D->pt3D.y; int px = (int)((x - x_range.min) / x_scale + x_skip); int py = (int)((y - y_range.min) / y_scale + y_skip); if (size == 1) img.at(py, px) = cv::Vec3b(rgb[2], rgb[1], rgb[0]); else cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), -1); } } if (objOps.size() > 0) { for (int i = 0; i < objOps.size(); i++) { if (i == 0) { rgb = { 255, 0, 0 }; size = 20; } else { rgb = { 255, 255, 0 }; size = 10; } int px = (int)((objOps[i].graspPos.x - x_range.min) / x_scale + x_skip); int py = (int)((objOps[i].graspPos.y - y_range.min) / y_scale + y_skip); cv::circle(img, cv::Point(px, py), size, cv::Scalar(rgb[2], rgb[1], rgb[0]), -1); //画ROI size = 3; cv::Point2d vec2d[4]; vec2d[0].x = objOps[i].objROI.left; vec2d[0].y = objOps[i].objROI.top; vec2d[1].x = objOps[i].objROI.right; vec2d[1].y = objOps[i].objROI.top; vec2d[2].x = objOps[i].objROI.right; vec2d[2].y = objOps[i].objROI.bottom; vec2d[3].x = objOps[i].objROI.left; vec2d[3].y = objOps[i].objROI.bottom; cv::Point vec[4]; for (int j = 0; j < 4; j++) { vec[j].x = (int)((vec2d[j].x - x_range.min) / x_scale + x_skip); vec[j].y = (int)((vec2d[j].y - y_range.min) / y_scale + y_skip); } for (int j = 0; j < 4; j++) { int nxtIdx = (j + 1) % 4; cv::line(img, vec[j], vec[nxtIdx], cv::Scalar(rgb[2], rgb[1], rgb[0]), size); } //画倾角 double r = 50; double angle = objOps[i].graspPos.z_yaw; angle = -angle * PI / 180; cv::Point2d line_pt[2]; line_pt[0].x = (int)(r * cos(angle) + px); line_pt[0].y = (int)(-r * sin(angle) + py); line_pt[1].x = (int)(-r * cos(angle) + px); line_pt[1].y = (int)(r * sin(angle) + py); cv::line(img, line_pt[0], line_pt[1], cv::Scalar(rgb[2], rgb[1], rgb[0]), size); } } } void _genXOYProjectionImage(cv::String& fileName, SVzNL3DLaserLine* scanData, int lineNum, std::vector& objOps, double rpy[3]) { //统计X和Y的范围 std::vector> scan_lines; SVzNLRangeD x_range = {0, -1}; SVzNLRangeD y_range = {0, -1}; for (int line = 0; line < lineNum; line++) { std::vector< SVzNL3DPosition> a_line; for (int i = 0; i < scanData[line].nPositionCnt; i++) { SVzNL3DPosition* pt3D = &scanData[line].p3DPosition[i]; if (pt3D->pt3D.z < 1e-4) continue; a_line.push_back(*pt3D); if (x_range.max < x_range.min) { x_range.min = pt3D->pt3D.x; x_range.max = pt3D->pt3D.x; } else { if(x_range.min > pt3D->pt3D.x) x_range.min = pt3D->pt3D.x; if(x_range.max < pt3D->pt3D.x) x_range.max = pt3D->pt3D.x; } if (y_range.max < y_range.min) { y_range.min = pt3D->pt3D.y; y_range.max = pt3D->pt3D.y; } else { if (y_range.min > pt3D->pt3D.y) y_range.min = pt3D->pt3D.y; if (y_range.max < pt3D->pt3D.y) y_range.max = pt3D->pt3D.y; } } scan_lines.push_back(a_line); } int imgRows = 992; int imgCols = 1056; double y_rows = 960.0; double x_cols = 1024.0; cv::Mat img = cv::Mat::zeros(imgRows, imgCols, CV_8UC3); //计算投影比例 double x_scale = (x_range.max - x_range.min) / x_cols; double y_scale = (y_range.max - y_range.min) / y_rows; _XOYprojection(img, scan_lines, objOps, x_scale, y_scale, x_range, y_range, true); //旋转视角显示 double matrix3d[9]; EulerRpyToRotation1(rpy, matrix3d); std::vector r_objOps; r_objOps.insert(r_objOps.end(), objOps.begin(), objOps.end()); for (int i = 0; i < objOps.size(); i++) { SVzNL3DPoint c_pt = { objOps[i].centerPos .x, objOps[i].centerPos .y, objOps[i].centerPos .z}; SVzNL3DPoint r_c_pt = _ptRotate(c_pt, matrix3d); r_objOps[i].centerPos.x = r_c_pt.x; r_objOps[i].centerPos.y = r_c_pt.y; r_objOps[i].centerPos.z = r_c_pt.z; } std::vector> rotateLines; SVzNLRangeD rx_range, ry_range; _rotateCloudPts(scanData, lineNum, matrix3d, rotateLines, &rx_range, &ry_range); cv::Mat r_img = cv::Mat::zeros(imgRows, imgCols, CV_8UC3); //计算投影比例 double rx_scale = (rx_range.max - rx_range.min) / x_cols; double ry_scale = (ry_range.max - ry_range.min) / y_rows; _XOYprojection(r_img, rotateLines, r_objOps, rx_scale, ry_scale, rx_range, ry_range, false); cv::Mat dis_img; cv::hconcat(img, r_img, dis_img); cv::imwrite(fileName, dis_img); return; } void _genXOYProjectionImage_sideBagInfo(cv::String& fileName, SVzNL3DLaserLine* scanData, int lineNum, std::vector& objOps, double rpy[3]) { //统计X和Y的范围 std::vector> scan_lines; SVzNLRangeD x_range = { 0, -1 }; SVzNLRangeD y_range = { 0, -1 }; for (int line = 0; line < lineNum; line++) { std::vector< SVzNL3DPosition> a_line; for (int i = 0; i < scanData[line].nPositionCnt; i++) { SVzNL3DPosition* pt3D = &scanData[line].p3DPosition[i]; if (pt3D->pt3D.z < 1e-4) continue; a_line.push_back(*pt3D); if (x_range.max < x_range.min) { x_range.min = pt3D->pt3D.x; x_range.max = pt3D->pt3D.x; } else { if (x_range.min > pt3D->pt3D.x) x_range.min = pt3D->pt3D.x; if (x_range.max < pt3D->pt3D.x) x_range.max = pt3D->pt3D.x; } if (y_range.max < y_range.min) { y_range.min = pt3D->pt3D.y; y_range.max = pt3D->pt3D.y; } else { if (y_range.min > pt3D->pt3D.y) y_range.min = pt3D->pt3D.y; if (y_range.max < pt3D->pt3D.y) y_range.max = pt3D->pt3D.y; } } scan_lines.push_back(a_line); } double x_scale = 1.0; double y_scale = 1.0; int x_rows = int((x_range.max - x_range.min) / x_scale); int y_rows = int((y_range.max - y_range.min) / y_scale); if (x_rows % 2 > 0) x_rows += 1; if (y_rows % 2 > 0) y_rows += 1; int imgRows = y_rows + 32; int imgCols = x_rows + 32; cv::Mat img = cv::Mat::zeros(imgRows, imgCols, CV_8UC3); //计算投影比例 _XOYprojection_sideBagInfo(img, scan_lines, objOps, x_scale, y_scale, x_range, y_range); #if 0 //旋转视角显示 double matrix3d[9]; EulerRpyToRotation1(rpy, matrix3d); std::vector r_objOps; r_objOps.insert(r_objOps.end(), objOps.begin(), objOps.end()); for (int i = 0; i < objOps.size(); i++) { SVzNL3DPoint c_pt = { objOps[i].graspPos.x, objOps[i].graspPos.y, objOps[i].graspPos.z }; SVzNL3DPoint r_c_pt = _ptRotate(c_pt, matrix3d); r_objOps[i].graspPos.x = r_c_pt.x; r_objOps[i].graspPos.y = r_c_pt.y; r_objOps[i].graspPos.z = r_c_pt.z; } std::vector> rotateLines; SVzNLRangeD rx_range, ry_range; _rotateCloudPts(scanData, lineNum, matrix3d, rotateLines, &rx_range, &ry_range); cv::Mat r_img = cv::Mat::zeros(imgRows, imgCols, CV_8UC3); //计算投影比例 double rx_scale = (rx_range.max - rx_range.min) / x_cols; double ry_scale = (ry_range.max - ry_range.min) / y_rows; _XOYprojection_sideBagInfo(r_img, rotateLines, r_objOps, rx_scale, ry_scale, rx_range, ry_range); cv::Mat dis_img; cv::hconcat(img, r_img, dis_img); cv::imwrite(fileName, dis_img); #else cv::Mat rot; cv::rotate(img, rot, cv::ROTATE_90_CLOCKWISE); // 顺时针90°旋转 cv::flip(rot, img, 1); // 左右翻转 cv::imwrite(fileName, img); #endif return; } //量化成640*640左右大小的图像。 void project2DWithInterpolate(cv::Mat& img, SVzNL3DLaserLine* scanData, int lineNum, double fixed_xy_scale, double z_scale) { double namedSize = 640.0;//目标图像最大尺度为640像素 SVzNLRangeD x_range = { 0, -1 }; SVzNLRangeD y_range = { 0, -1 }; SVzNLRangeD z_range = { 0, -1 }; for (int line = 0; line < lineNum; line++) { for (int i = 0; i < scanData[line].nPositionCnt; i++) { SVzNL3DPosition* pt3D = &scanData[line].p3DPosition[i]; if (pt3D->pt3D.z < 1e-4) continue; if (x_range.max < x_range.min) { x_range.min = pt3D->pt3D.x; x_range.max = pt3D->pt3D.x; } else { if (x_range.min > pt3D->pt3D.x) x_range.min = pt3D->pt3D.x; if (x_range.max < pt3D->pt3D.x) x_range.max = pt3D->pt3D.x; } if (y_range.max < y_range.min) { y_range.min = pt3D->pt3D.y; y_range.max = pt3D->pt3D.y; } else { if (y_range.min > pt3D->pt3D.y) y_range.min = pt3D->pt3D.y; if (y_range.max < pt3D->pt3D.y) y_range.max = pt3D->pt3D.y; } if (z_range.max < z_range.min) { z_range.min = pt3D->pt3D.z; z_range.max = pt3D->pt3D.z; } else { if (z_range.min > pt3D->pt3D.z) z_range.min = pt3D->pt3D.z; if (z_range.max < pt3D->pt3D.z) z_range.max = pt3D->pt3D.z; } } } double xy_scale = fixed_xy_scale; if (fixed_xy_scale < 1e-4) { double x_scale = (x_range.max - x_range.min) / namedSize; double y_scale = (y_range.max - y_range.min) / namedSize; double xy_scale; if (x_scale < y_scale) xy_scale = y_scale; else xy_scale = x_scale; } int img_rows = (int)((y_range.max - y_range.min) / xy_scale)+1; if(img_rows %2 >0) img_rows +=1; int img_cols = (int)((x_range.max - x_range.min) / xy_scale)+ 1; if (img_cols % 2 > 0) img_cols += 1; img = cv::Mat::zeros(img_rows, img_cols, CV_8UC1); int polateWin = 5; for (int line = 0; line < lineNum; line++) { //同时进行垂直插值 int pre_py = -1; SVzNL3DPosition* pre_pt3D = NULL; int pre_i = -1; for (int i = 0; i < scanData[line].nPositionCnt; i++) { SVzNL3DPosition* pt3D = &scanData[line].p3DPosition[i]; if (pt3D->pt3D.z < 1e-4) continue; double x = pt3D->pt3D.x; double y = pt3D->pt3D.y; int px = (int)((x - x_range.min) / xy_scale); int py = (int)((y - y_range.min) / xy_scale); int value = (int)((pt3D->pt3D.z - z_range.min) / z_scale); if (value > 254) value = 254; value = 255 - value; img.at(py, px) = (uchar)value; //检查是否需要插值 if ( (py > pre_py + 1)&& (py <= pre_py + polateWin + 1) && (pre_py >= 0) && (pre_i >= 0) && (i == pre_i + 1)) //3D点连续,量化点不连续,插值 { double dist = double(py - pre_py); for (int iy = pre_py + 1; iy < py; iy++) { double k1 = (double)(iy - pre_py) / dist; double k0 = 1 - k1; double inter_x = pre_pt3D->pt3D.x * k0 + pt3D->pt3D.x * k1; double inter_y = pre_pt3D->pt3D.y * k0 + pt3D->pt3D.y * k1; double inter_z = pre_pt3D->pt3D.z * k0 + pt3D->pt3D.z * k1; int polate_px = (int)((inter_x - x_range.min) / xy_scale); int polate_py = (int)((inter_y - y_range.min) / xy_scale); int polate_value = (int)((inter_z - z_range.min) / z_scale); if (polate_value > 254) polate_value = 254; polate_value = 255 - polate_value; img.at(polate_py, polate_px) = (uchar)polate_value; } } pre_i = i; pre_py = py; pre_pt3D = pt3D; } } //水平插值 for (int y = 0; y < img.rows; y++) { int pre_x = -1; uchar pre_value = 0; for (int x = 0; x < img.cols; x++) { uchar value = img.at(y, x); if (value > 0) { if ((x > pre_x + 1) && (x <= pre_x + polateWin + 1) &&(pre_x >= 0)) //水平不连续,插值 { double dist = double(x - pre_x); for (int ix = pre_x + 1; ix < x; ix++) { double k1 = (double)(ix - pre_x) / dist; double k0 = 1 - k1; double inter_data = (double)pre_value * k0 + (double)value * k1; if (inter_data > 255) inter_data = 255; uchar polate_value = (uchar)inter_data; img.at(y, ix) = polate_value; } } pre_x = x; pre_value = value; } } } } void _outputScanDataFile_removeZeros(char* fileName, SVzNL3DLaserLine* scanData, int lineNum, float lineV, int maxTimeStamp, int clockPerSecond) { std::ofstream sw(fileName); sw << "LineNum:" << lineNum << std::endl; sw << "DataType: 0" << std::endl; sw << "ScanSpeed:" << lineV << std::endl; sw << "PointAdjust: 1" << std::endl; sw << "MaxTimeStamp:" << maxTimeStamp << "_" << clockPerSecond << std::endl; for (int line = 0; line < lineNum; line++) { int realNum = 0; for (int i = 0; i < scanData[line].nPositionCnt; i++) { if (scanData[line].p3DPosition[i].pt3D.z > 1e-4) realNum++; } sw << "Line_" << line << "_" << scanData[line].nTimeStamp << "_" << realNum << std::endl; for (int i = 0; i < scanData[line].nPositionCnt; i++) { if (scanData[line].p3DPosition[i].pt3D.z > 1e-4) { 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 TEST_CONVERT_TO_GRID 0 #define TEST_COMPUTE_GRASP_POINT 1 #define TEST_COMPUTE_CALIB_PARA 1 #define TEST_GROUP 16 int main() { /** * 计算调平参数 */ char _calib_datafile[256]; sprintf_s(_calib_datafile, "F:\\上古\\编织袋数据\\点云8_广东1213-1215数据\\LaserLine10_grid.txt"); int lineNum = 0; float lineV = 0.0f; int dataCalib = 0; int maxTimeStamp = 0; int clockPerSecond = 0; SVzNL3DLaserLine* laser3DPoints = vzReadLaserScanPointFromFile_XYZ(_calib_datafile, &lineNum, &lineV, &dataCalib, &maxTimeStamp, &clockPerSecond); if (laser3DPoints) { SSG_planeCalibPara calibPara = sg_getBagBaseCalibPara(laser3DPoints, lineNum); //结果进行验证 for (int i = 0; i < lineNum; i++) { //调平,去除地面 sg_lineDataR(&laser3DPoints[i], calibPara.planeCalib, calibPara.planeHeight); } // char calibFile[250]; sprintf_s(calibFile, "F:\\上古\\编织袋数据\\点云8_广东1213-1215数据\\ground_calib_para.txt"); _outputCalibPara(calibFile, calibPara); char _out_file[256]; sprintf_s(_out_file, "F:\\上古\\编织袋数据\\点云8_广东1213-1215数据\\LaserLine10_grid_calib.txt"); _outputScanDataFile_self(_out_file, laser3DPoints, lineNum, lineV, maxTimeStamp, clockPerSecond); printf("%s: calib done!\n", _calib_datafile); } /** * 计算抓取点 */ const char* dataPath = "F:\\ShangGu\\编织袋数据\\点云1\\"; 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]; SG_bagPositionParam algoParam; algoParam.bagParam.bagL = 650; //袋子长65cm algoParam.bagParam.bagW = 450; //袋子宽40cm algoParam.bagParam.bagH = 160; //袋子高16cm algoParam.cornerParam.cornerTh = 30; //45度角 algoParam.cornerParam.scale = 15; // 30; // algoParam.bagParam.bagH / 8; algoParam.cornerParam.minEndingGap = algoParam.bagParam.bagW / 4; algoParam.cornerParam.jumpCornerTh_1 = 60; algoParam.cornerParam.jumpCornerTh_2 = 15; algoParam.growParam.maxLineSkipNum = 5; algoParam.growParam.yDeviation_max = 20.0; algoParam.growParam.maxSkipDistance = 20.0; algoParam.growParam.zDeviation_max = 80.0; //袋子高度1/2 algoParam.growParam.minLTypeTreeLen = 50.0; //mm algoParam.growParam.minVTypeTreeLen = 50.0; //mm char calibFile[250]; sprintf_s(calibFile, "F:\\上古\\编织袋数据\\点云8_广东1213-1215数据\\ground_calib_para.txt"); poseCalibPara = _readCalibPara(calibFile); algoParam.filterParam.continuityTh = 20.0; //噪声滤除。当相邻点的z跳变大于此门限时,检查是否为噪声。若长度小于outlierLen, 视为噪声 algoParam.filterParam.outlierTh = 5; long t1 = GetTickCount64(); std::vector objOps; sg_getBagPosition(laser3DPoints, lineNum, algoParam, poseCalibPara, objOps); long t2 = GetTickCount64(); char _dbg_file[256]; sprintf_s(_dbg_file, "%sresult\\LaserLine%d_result.txt", dataPath[grp], fidx); _outputScanDataFile_RGBD_obj(_dbg_file, laser3DPoints, lineNum, lineV, maxTimeStamp, clockPerSecond, objOps); sprintf_s(_dbg_file, "%sresult\\LaserLine%d_result_img.png", dataPath[grp], fidx); cv::String imgName(_dbg_file); double rpy[3] = { -30, 15, 0 }; //{ 0,-45, 0 }; // _genXOYProjectionImage(imgName, laser3DPoints, lineNum, objOps, rpy); printf("%s: %d(ms)!\n", _scan_file, (int)(t2 - t1)); }