algoLib/sourceCode/SG_baseFunc.cpp

2166 lines
54 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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

#include "SG_baseDataType.h"
#include "SG_baseAlgo_Export.h"
#include <vector>
#include <corecrt_math_defines.h>
#include <cmath>
#include <unordered_map>
//¼ÆËãɨÃèROI
SVzNL3DRangeD sg_getScanDataROI(
SVzNL3DLaserLine* laser3DPoints,
int lineNum)
{
SVzNL3DRangeD roi;
roi.xRange = { 0, -1 };
roi.yRange = { 0, -1 };
roi.zRange = { 0, -1 };
for (int line = 0; line < lineNum; line++)
{
for (int i = 0; i < laser3DPoints[line].nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &laser3DPoints[line].p3DPosition[i];
if (pt3D->pt3D.z < 1e-4)
continue;
if (roi.xRange.max < roi.xRange.min)
{
roi.xRange.min = pt3D->pt3D.x;
roi.xRange.max = pt3D->pt3D.x;
}
else
{
if (roi.xRange.min > pt3D->pt3D.x)
roi.xRange.min = pt3D->pt3D.x;
if (roi.xRange.max < pt3D->pt3D.x)
roi.xRange.max = pt3D->pt3D.x;
}
//y
if (roi.yRange.max < roi.yRange.min)
{
roi.yRange.min = pt3D->pt3D.y;
roi.yRange.max = pt3D->pt3D.y;
}
else
{
if (roi.yRange.min > pt3D->pt3D.y)
roi.yRange.min = pt3D->pt3D.y;
if (roi.yRange.max < pt3D->pt3D.y)
roi.yRange.max = pt3D->pt3D.y;
}
//z
if (roi.zRange.max < roi.zRange.min)
{
roi.zRange.min = pt3D->pt3D.z;
roi.zRange.max = pt3D->pt3D.z;
}
else
{
if (roi.zRange.min > pt3D->pt3D.z)
roi.zRange.min = pt3D->pt3D.z;
if (roi.zRange.max < pt3D->pt3D.z)
roi.zRange.max = pt3D->pt3D.z;
}
}
}
return roi;
}
//¼ÆËãɨÃèROI: vecotr¸ñʽ
SVzNL3DRangeD sg_getScanDataROI_vector(std::vector< std::vector<SVzNL3DPosition>>& scanLines)
{
SVzNL3DRangeD roi;
roi.xRange = { 0, -1 };
roi.yRange = { 0, -1 };
roi.zRange = { 0, -1 };
int lineNum = (int)scanLines.size();
for (int line = 0; line < lineNum; line++)
{
int nPositionCnt = (int)scanLines[line].size();
for (int i = 0; i < nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->pt3D.z < 1e-4)
continue;
if (roi.xRange.max < roi.xRange.min)
{
roi.xRange.min = pt3D->pt3D.x;
roi.xRange.max = pt3D->pt3D.x;
}
else
{
if (roi.xRange.min > pt3D->pt3D.x)
roi.xRange.min = pt3D->pt3D.x;
if (roi.xRange.max < pt3D->pt3D.x)
roi.xRange.max = pt3D->pt3D.x;
}
//y
if (roi.yRange.max < roi.yRange.min)
{
roi.yRange.min = pt3D->pt3D.y;
roi.yRange.max = pt3D->pt3D.y;
}
else
{
if (roi.yRange.min > pt3D->pt3D.y)
roi.yRange.min = pt3D->pt3D.y;
if (roi.yRange.max < pt3D->pt3D.y)
roi.yRange.max = pt3D->pt3D.y;
}
//z
if (roi.zRange.max < roi.zRange.min)
{
roi.zRange.min = pt3D->pt3D.z;
roi.zRange.max = pt3D->pt3D.z;
}
else
{
if (roi.zRange.min > pt3D->pt3D.z)
roi.zRange.min = pt3D->pt3D.z;
if (roi.zRange.max < pt3D->pt3D.z)
roi.zRange.max = pt3D->pt3D.z;
}
}
}
return roi;
}
//¼ÆËãµãÔÆµÄROIºÍscale: vecotr¸ñʽ
SWD_pointCloudPara wd_getPointCloudPara(std::vector< std::vector<SVzNL3DPosition>>& scanLines)
{
SWD_pointCloudPara para;
para.xRange = { 0, -1 };
para.yRange = { 0, -1 };
para.zRange = { 0, -1 };
para.scale_x = -1; //³õʼֵ
para.scale_y = -1;
int lineNum = (int)scanLines.size();
double x_scale = 0;
int x_scale_cnt = 0;
double y_scale = 0;
double y_scale_cnt = 0;
for (int line = 0; line < lineNum; line++)
{
int nPositionCnt = (int)scanLines[line].size();
for (int i = 0; i < nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->pt3D.z < 1e-4)
continue;
if (i > 0)
{
if (scanLines[line][i - 1].pt3D.z > 1e-4)
{
y_scale += abs(pt3D->pt3D.y - scanLines[line][i - 1].pt3D.y);
y_scale_cnt++;
}
}
if (line > 0)
{
if (scanLines[line - 1][i].pt3D.z > 1e-4)
{
x_scale += abs(pt3D->pt3D.x - scanLines[line-1][i].pt3D.x);
x_scale_cnt++;
}
}
if (para.xRange.max < para.xRange.min)
{
para.xRange.min = pt3D->pt3D.x;
para.xRange.max = pt3D->pt3D.x;
}
else
{
if (para.xRange.min > pt3D->pt3D.x)
para.xRange.min = pt3D->pt3D.x;
if (para.xRange.max < pt3D->pt3D.x)
para.xRange.max = pt3D->pt3D.x;
}
//y
if (para.yRange.max < para.yRange.min)
{
para.yRange.min = pt3D->pt3D.y;
para.yRange.max = pt3D->pt3D.y;
}
else
{
if (para.yRange.min > pt3D->pt3D.y)
para.yRange.min = pt3D->pt3D.y;
if (para.yRange.max < pt3D->pt3D.y)
para.yRange.max = pt3D->pt3D.y;
}
//z
if (para.zRange.max < para.zRange.min)
{
para.zRange.min = pt3D->pt3D.z;
para.zRange.max = pt3D->pt3D.z;
}
else
{
if (para.zRange.min > pt3D->pt3D.z)
para.zRange.min = pt3D->pt3D.z;
if (para.zRange.max < pt3D->pt3D.z)
para.zRange.max = pt3D->pt3D.z;
}
}
}
if (x_scale_cnt > 0)
para.scale_x = x_scale / (double)x_scale_cnt;
if (y_scale_cnt > 0)
para.scale_y = y_scale / (double)y_scale_cnt;
return para;
}
void lineFitting(std::vector< SVzNL3DPoint>& inliers, double* _k, double* _b)
{
//×îС¶þ³ËÄâºÏÖ±Ïß²ÎÊý
double xx_sum = 0;
double x_sum = 0;
double y_sum = 0;
double xy_sum = 0;
int num = 0;
for (int i = 0; i < inliers.size(); i++)
{
x_sum += inliers[i].x; //xµÄÀÛ¼ÓºÍ
y_sum += inliers[i].y; //yµÄÀÛ¼ÓºÍ
xx_sum += inliers[i].x * inliers[i].x; //xµÄƽ·½ÀÛ¼ÓºÍ
xy_sum += inliers[i].x * inliers[i].y; //x£¬yµÄÀÛ¼ÓºÍ
num++;
}
*_k = (num * xy_sum - x_sum * y_sum) / (num * xx_sum - x_sum * x_sum); //¸ù¾Ý¹«Ê½Çó½âk
*_b = (-x_sum * xy_sum + xx_sum * y_sum) / (num * xx_sum - x_sum * x_sum);//¸ù¾Ý¹«Ê½Çó½âb
}
SVzNL2DPointD sx_getFootPoint(double x0, double y0, double k, double b)
{
double A = k;
double B = -1;
double C = b;
SVzNL2DPointD foot;
foot.x = (B * B * x0 - A * B * y0 - A * C) / (A * A + B * B);
foot.y = (-A * B * x0 + A * A * y0 - B * C) / (A * A + B * B);
return foot;
}
#if 0
void icvprCcaByTwoPass(const cv::Mat& binImg, cv::Mat& lableImg)
{
// connected component analysis (4-component)
// use two-pass algorithm
// 1. first pass: label each foreground pixel with a label
// 2. second pass: visit each labeled pixel and merge neighbor labels
//
// foreground pixel: binImg(x,y) = 1
// background pixel: binImg(x,y) = 0
if (binImg.empty() ||
binImg.type() != CV_8UC1)
{
return;
}
// 1. first pass
lableImg.release();
binImg.convertTo(lableImg, CV_32SC1);
int label = 1; // start by 2
std::vector<int> labelSet;
labelSet.push_back(0); // background: 0
labelSet.push_back(1); // foreground: 1
int rows = binImg.rows - 1;
int cols = binImg.cols - 1;
for (int i = 1; i < rows; i++)
{
int* data_preRow = lableImg.ptr<int>(i - 1);
int* data_curRow = lableImg.ptr<int>(i);
for (int j = 1; j < cols; j++)
{
if (data_curRow[j] == 1)
{
std::vector<int> neighborLabels;
neighborLabels.reserve(2);
int leftPixel = data_curRow[j - 1];
int upPixel = data_preRow[j];
if (leftPixel > 1)
{
neighborLabels.push_back(leftPixel);
}
if (upPixel > 1)
{
neighborLabels.push_back(upPixel);
}
if (neighborLabels.empty())
{
labelSet.push_back(++label); // assign to a new label
data_curRow[j] = label;
labelSet[label] = label;
}
else
{
std::sort(neighborLabels.begin(), neighborLabels.end());
int smallestLabel = neighborLabels[0];
data_curRow[j] = smallestLabel;
// save equivalence
for (size_t k = 1; k < neighborLabels.size(); k++)
{
int tempLabel = neighborLabels[k];
int& oldSmallestLabel = labelSet[tempLabel];
if (oldSmallestLabel > smallestLabel)
{
labelSet[oldSmallestLabel] = smallestLabel;
oldSmallestLabel = smallestLabel;
}
else if (oldSmallestLabel < smallestLabel)
{
labelSet[smallestLabel] = oldSmallestLabel;
}
}
}
}
}
}
// update equivalent labels
// assigned with the smallest label in each equivalent label set
for (size_t i = 2; i < labelSet.size(); i++)
{
int curLabel = labelSet[i];
int preLabel = labelSet[curLabel];
while (preLabel != curLabel)
{
curLabel = preLabel;
preLabel = labelSet[preLabel];
}
labelSet[i] = curLabel;
}
// 2. second pass
for (int i = 0; i < rows; i++)
{
int* data = lableImg.ptr<int>(i);
for (int j = 0; j < cols; j++)
{
int& pixelLabel = data[j];
pixelLabel = labelSet[pixelLabel];
}
}
}
#endif
#if 0
//BresenhamËã·¨
void line(int x0, int y0, int x1, int y1, TGAImage& image, TGAColor color) {
bool steep = false;
if (std::abs(x1 - x0) < std::abs(y1 - y0)) {
std::swap(x0, y0);
std::swap(x1, y1);
steep = true;
}
if (x0 > x1) {
std::swap(x0, x1);
std::swap(y0, y1);
}
int dx = x1 - x0;
int dy = y1 - y0;
int deltaY = std::abs(dy << 1);
int middle = dx;
int y = y0;
for (int x = x0; x <= x1; ++x) {
if (steep) {
image.set(y, x, color);
}
else {
image.set(x, y, color);
}
deltaY += std::abs(dy << 1);
if (deltaY >= middle) {
y += (y1 > y0 ? 1 : -1);
middle += std::abs(dx << 1);
}
}
}
#endif
//BresenhamËã·¨
void drawLine(
int x0,
int y0,
int x1,
int y1,
std::vector<SVzNL2DPoint>& pts)
{
// ¼ÆËãdxºÍdyµÄ¾ø¶ÔÖµ
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
// È·¶¨²½½ø·½Ïò
int sx = (x0 < x1) ? 1 : -1; // x·½Ïò²½½ø
int sy = (y0 < y1) ? 1 : -1; // y·½Ïò²½½ø
// ³õʼ»¯Îó²î±äÁ¿£¬½áºÏdxºÍdyµÄ·ûºÅ
int err = dx - dy;
while (true) {
SVzNL2DPoint a_pt = { x0, y0 };
pts.push_back(a_pt);
// µ½´ïÖÕµãʱÍ˳öÑ­»·
if (x0 == x1 && y0 == y1) break;
int e2 = 2 * err; // µ±Ç°Îó²îµÄÁ½±¶
// ¸ù¾ÝÎó²î¾ö¶¨²½½ø·½Ïò
if (e2 > -dy) { // Îó²îÇãÏòÓÚx·½Ïò²½½ø
err -= dy;
x0 += sx;
}
if (e2 < dx) { // Îó²îÇãÏòÓÚy·½Ïò²½½ø
err += dx;
y0 += sy;
}
}
}
/// <summary>
/// Á½²½·¨±ê×¢
/// </summary>
/// <param name="bwImg"> Ä¿±êµãΪ¡°1¡±£¬ ¿Õ°×µãΪ¡°0¡±</param>
/// <param name="labImg"> ±ê×¢½á¹û¡£Ã¿¸öµãΪrgnID, ID´Ó2¿ªÊ¼ </param>
/// <param name="labelRgns"></param>
#if 0
void SG_TwoPassLabel(
const cv::Mat& bwImg,
cv::Mat& labImg,
std::vector<SSG_Region>& labelRgns,
int connectivity)
{
assert(bwImg.type() == CV_8UC1);
bwImg.convertTo(labImg, CV_32SC1);
int rows = bwImg.rows - 1;
int cols = bwImg.cols - 1;
//¶þֵͼÏñÏñËØÖµÎª0»ò1£¬ÎªÁ˲»³åÍ»£¬label´Ó2¿ªÊ¼
int label = 2;
std::vector<int> labelSet;
labelSet.push_back(0);
labelSet.push_back(1);
//µÚÒ»´ÎɨÃè
int* data_prev = (int*)labImg.data;
int* data_cur = (int*)(labImg.data + labImg.step);
int left, up;//Ö¸ÕëÖ¸ÏòµÄÏñËØµãµÄ×ó·½µãºÍÉÏ·½µã
int neighborLabels[2];
for (int i = 1; i < rows; i++)// ºöÂÔµÚÒ»Ðк͵ÚÒ»ÁÐ,Æäʵ¿ÉÒÔ½«labImgµÄ¿í¸ß¼Ó1£¬È»ºóÔÚ³õʼ»¯Îª0¾Í¿ÉÒÔÁË
{
data_cur++;
data_prev++;
for (int j = 1; j < cols; j++, data_cur++, data_prev++)
{
if ((i == 1409) && (j == 432))
int kkk = 1;
if (*data_cur != 1)//µ±Ç°µã²»Îª1£¬É¨ÃèÏÂÒ»¸öµã
continue;
left = *(data_cur - 1);
up = *data_prev;
int count = 0;
for (int curLabel : {left, up})
{
if (curLabel > 1)
neighborLabels[count++] = curLabel;
}
if (!count)//¸³ÓèÒ»¸öеÄlabel
{
labelSet.push_back(label);
*data_cur = label;
label++;
continue;
}
//½«µ±Ç°µã±ê¼ÇÉèΪ×óµãºÍÉϵãlabelµÄ×îСֵ
int smallestLabel = neighborLabels[0];
if (count == 2 && neighborLabels[1] < smallestLabel)
smallestLabel = neighborLabels[1];
*data_cur = smallestLabel;
//ÉèÖÃµÈ¼Û±í£¬ÕâÀï¿ÉÄÜÓеãÄÑÀí½â
//×óµãÓпÉÄܱÈÉϵãС£¬Ò²ÓпÉÄܱÈÉϵã´ó£¬Á½ÖÖÇé¿ö¶¼Òª¿¼ÂÇ,ÀýÈç
//0 0 1 0 1 0 x x 2 x 3 x
//1 1 1 1 1 1 -> 4 4 2 2 2 2
//Òª½«labelSetÖÐ3µÄλÖÃÉèÖÃΪ2
for (int k = 0; k < count; k++)
{
int neiLabel = neighborLabels[k];
int oldSmallestLabel = labelSet[neiLabel];
if (oldSmallestLabel > smallestLabel)
{
if ((oldSmallestLabel == 117) && (smallestLabel == 113))
int kkk = 1;
labelSet[oldSmallestLabel] = smallestLabel;
}
else if (oldSmallestLabel < smallestLabel)
{
if ((smallestLabel == 117) && (oldSmallestLabel == 113))
int kkk = 1;
if (labelSet[smallestLabel] != oldSmallestLabel)
{
}
labelSet[smallestLabel] = oldSmallestLabel;
}
}
}
data_cur++;
data_prev++;
}
//ÉÏÃæÒ»²½ÖÐ,ÓеÄlabelSetµÄλÖû¹Î´ÉèΪ×îСֵ£¬ÀýÈç
//0 0 1 0 1 x x 2 x 3
//0 1 1 1 1 -> x 4 2 2 2
//1 1 1 0 1 5 4 2 x 2
//ÉÏÃæÕⲨ²Ù×÷ÖУ¬°ÑlabelSet[4]ÉèΪ2£¬µ«labelSet[5]ÈÔΪ4
//ÕâÀï¿ÉÒÔ½«labelSet[5]ÉèΪ2
for (size_t i = 2; i < labelSet.size(); i++)
{
int curLabel = labelSet[i];
int prelabel = labelSet[curLabel];
while (prelabel != curLabel)
{
curLabel = prelabel;
prelabel = labelSet[prelabel];
}
labelSet[i] = curLabel;
}
//µÚ¶þ´ÎɨÃ裬ÓÃlabelSet½øÐиüУ¬×îºóÒ»ÁÐ
std::vector<SSG_Region*> labelInfo;
labelInfo.resize(labelSet.size(), nullptr);
data_cur = (int*)labImg.data;
for (int i = 0; i < labImg.rows; i++)
{
for (int j = 0; j < labImg.cols; j++)
{
*data_cur = labelSet[*data_cur];
if (*data_cur > 1) //ÓÐЧlabel
{
//ͳ¼ÆRegionÐÅÏ¢
SSG_Region* info_cur = (SSG_Region*)labelInfo[*data_cur];
if (nullptr == info_cur)
{
SSG_Region new_rgn = { {j,j,i,i}, 1, *data_cur };
labelRgns.push_back(new_rgn); //push_back()ºó£¬vectorÖÐÄÚ´æµ¥Ôª¿ÉÄܻᱻ¸Ä¶¯
for (int m = 0; m < labelRgns.size(); m++)
{
info_cur = &labelRgns[m];
labelInfo[info_cur->labelID] = info_cur;
}
}
else
{
assert(*data_cur == info_cur->labelID);
if (info_cur->roi.left > j)
info_cur->roi.left = j;
if (info_cur->roi.right < j)
info_cur->roi.right = j;
if (info_cur->roi.top > i)
info_cur->roi.top = i;
if (info_cur->roi.bottom < i)
info_cur->roi.bottom = i;
info_cur->ptCounter++;
}
}
data_cur++;
}
}
return;
}
#else
// ²éÕÒº¯Êý£¨´øÂ·¾¶Ñ¹Ëõ£©
int find(int x, std::vector<int>& parent) {
if (parent[x] != x) {
parent[x] = find(parent[x], parent);
}
return parent[x];
}
// ºÏ²¢º¯Êý£¨°´ÖȺϲ¢µ½½ÏС¸ù£©
void unionSet(int x, int y, std::vector<int>& parent) {
int rootX = find(x, parent);
int rootY = find(y, parent);
if (rootX != rootY) {
if (rootX < rootY) {
parent[rootY] = rootX;
}
else {
parent[rootX] = rootY;
}
}
}
/**
* @brief Á¬Í¨Óò±ê×¢º¯Êý
* @param image ÊäÈë¶þֵͼÏñ£¬0±íʾ±³¾°£¬·Ç0Ϊǰ¾°
* @param labels Êä³ö±êÇ©¾ØÕó
* @param connectivity Á¬Í¨ÐÔ£¨4»ò8£©
*/
void SG_TwoPassLabel(
const cv::Mat& bwImg,
cv::Mat& labImg,
std::vector<SSG_Region>& labelRgns,
int connectivity)
{
assert(bwImg.type() == CV_8UC1);
bwImg.convertTo(labImg, CV_32SC1);
if (bwImg.rows == 0)
return;
int rows = bwImg.rows - 1;
int cols = bwImg.cols - 1;
// ³õʼ»¯²¢²é¼¯£¨×î´ó¿ÉÄܱêÇ©ÊýΪÏñËØ×ÜÊý£©
int max_label = rows * cols;
std::vector<int> parent(max_label + 1);
for (int i = 0; i <= max_label; ++i) {
parent[i] = i;
}
//µÚÒ»´ÎɨÃè
int label_cnt = 2; // µ±Ç°×î´ó±êÇ©,¶þֵͼÏñÏñËØÖµÎª0»ò1£¬ÎªÁ˲»³åÍ»£¬label´Ó2¿ªÊ¼
int* data_prev = (int*)labImg.data;
int* data_cur = (int*)(labImg.data + labImg.step);
// µÚÒ»±éɨÃ裺ÁÙʱ±êÇ©·ÖÅä
for (int i = 1; i < rows; i++)
{
data_cur++;
data_prev++;
for (int j = 1; j < cols; j++, data_cur++, data_prev++)
{
if (*data_cur != 1)//µ±Ç°µã²»Îª1£¬É¨ÃèÏÂÒ»¸öµã
continue;
int left = *(data_cur - 1);
int up = *data_prev;
int up_left = *(data_prev-1);
int up_right = *(data_prev + 1);
std::vector<int> neighbors;
auto add_neighbor = [&](int neiLabel) {
if (neiLabel != 0) {
neighbors.push_back(find(neiLabel, parent));
}
};
// ¼ì²éÒÑ´¦ÀíÁÚÓò
if(up > 1)
add_neighbor(up); // ÉÏ
if( (left > 1) && (left != up))
add_neighbor(left); // ×ó
if (connectivity == 8)
{
if( (up_left > 1) && (up_left != up) && (up_left != left))
add_neighbor(up_left); // ×óÉÏ
if( (up_right > 1) && (up_right != up) && (up_right != left) && (up_right != up_left))
add_neighbor(up_right); // ÓÒÉÏ
}
if (neighbors.empty()) { // ÐÂÁ¬Í¨Óò
*data_cur = label_cnt++;
}
else { // ºÏ²¢ÁÚÓò
int min_root = *std::min_element(neighbors.begin(), neighbors.end());
*data_cur = min_root;
for (int root : neighbors)
{
if (root != min_root)
{
unionSet(root, min_root, parent);
}
}
}
}
data_cur++;
data_prev++;
}
for (int i = 2; i < label_cnt; i++)
parent[i] = find(parent[i], parent);
data_cur = (int*)labImg.data;
for (int i = 0; i < labImg.rows; i++)
{
for (int j = 0; j < labImg.cols; j++)
{
if (*data_cur > 1)
{
*data_cur = parent[*data_cur];
}
data_cur++;
}
}
std::vector<SSG_Region*> labelInfo;
labelInfo.resize(label_cnt, nullptr);
// £¨¿ÉÑ¡£©ÖØÐÂÓ³ÉäΪÁ¬Ðø±êÇ©
std::unordered_map<int, int> label_map;
int new_label = 2;
data_cur = (int*)labImg.data;
for (int i = 0; i < labImg.rows; i++)
{
for (int j = 0; j < labImg.cols; j++)
{
if (j == 69)
int kkk = 1;
int lbl = *data_cur;
if (lbl > 1)
{
if (label_map.find(lbl) == label_map.end())
{
label_map[lbl] = new_label++;
}
*data_cur = label_map[lbl];
//ͳ¼ÆRegionÐÅÏ¢
SSG_Region* info_cur = (SSG_Region*)labelInfo[*data_cur];
if (nullptr == info_cur)
{
SSG_Region new_rgn = { {j,j,i,i}, 1, *data_cur };
labelRgns.push_back(new_rgn); //push_back()ºó£¬vectorÖÐÄÚ´æµ¥Ôª¿ÉÄܻᱻ¸Ä¶¯
for (int m = 0; m < labelRgns.size(); m++)
{
info_cur = &labelRgns[m];
labelInfo[info_cur->labelID] = info_cur;
}
}
else
{
assert(*data_cur == info_cur->labelID);
if (info_cur->roi.left > j)
info_cur->roi.left = j;
if (info_cur->roi.right < j)
info_cur->roi.right = j;
if (info_cur->roi.top > i)
info_cur->roi.top = i;
if (info_cur->roi.bottom < i)
info_cur->roi.bottom = i;
info_cur->ptCounter++;
}
}
data_cur++;
}
}
}
#endif
//¼ÆËãÃæ²ÎÊý: z = Ax + By + C
//res: [0]=A, [1]= B, [2]=-1.0, [3]=C,
void vzCaculateLaserPlane(std::vector<cv::Point3f> Points3ds, std::vector<double>& res)
{
//×îС¶þ³Ë·¨ÄâºÏÆ½Ãæ
//»ñÈ¡cv::MatµÄ×ø±êϵÒÔ×ÝÏòΪxÖᣬºáÏòΪyÖᣬ¶øcvPointµÈÔòÏà·´
//ϵÊý¾ØÕó
cv::Mat A = cv::Mat::zeros(3, 3, CV_64FC1);
//
cv::Mat B = cv::Mat::zeros(3, 1, CV_64FC1);
//½á¹û¾ØÕó
cv::Mat X = cv::Mat::zeros(3, 1, CV_64FC1);
double x2 = 0, xiyi = 0, xi = 0, yi = 0, zixi = 0, ziyi = 0, zi = 0, y2 = 0;
for (int i = 0; i < Points3ds.size(); i++)
{
x2 += (double)Points3ds[i].x * (double)Points3ds[i].x;
y2 += (double)Points3ds[i].y * (double)Points3ds[i].y;
xiyi += (double)Points3ds[i].x * (double)Points3ds[i].y;
xi += (double)Points3ds[i].x;
yi += (double)Points3ds[i].y;
zixi += (double)Points3ds[i].z * (double)Points3ds[i].x;
ziyi += (double)Points3ds[i].z * (double)Points3ds[i].y;
zi += (double)Points3ds[i].z;
}
A.at<double>(0, 0) = x2;
A.at<double>(1, 0) = xiyi;
A.at<double>(2, 0) = xi;
A.at<double>(0, 1) = xiyi;
A.at<double>(1, 1) = y2;
A.at<double>(2, 1) = yi;
A.at<double>(0, 2) = xi;
A.at<double>(1, 2) = yi;
A.at<double>(2, 2) = (double)((int)Points3ds.size());
B.at<double>(0, 0) = zixi;
B.at<double>(1, 0) = ziyi;
B.at<double>(2, 0) = zi;
//¼ÆËãÆ½ÃæÏµÊý
X = A.inv() * B;
//A
res.push_back(X.at<double>(0, 0));
//B
res.push_back(X.at<double>(1, 0));
//ZµÄϵÊýΪ-1
res.push_back(-1.0);
//C
res.push_back(X.at<double>(2, 0));
return;
}
// º¯Êý£º´ÓÆ½Ãæ·¨ÏòÁ¿¼ÆËãÅ·À­½Ç£¨ZYX˳Ðò£©
SSG_EulerAngles planeNormalToEuler(double A, double B, double C) {
SSG_EulerAngles angles = { 0, 0, 0 };
// 1. ¹éÒ»»¯·¨ÏòÁ¿
double length = std::sqrt(A * A + B * B + C * C);
if (length < 1e-7)
return angles;
double nx = A / length;
double ny = B / length;
double nz = C / length;
// 2. ¼ÆË㸩Ñö½Ç£¨ÈÆYÖᣩ
angles.pitch = std::asin(nx) * (180.0 / M_PI); // תΪ¶ÈÊý
// 3. ¼ÆËãRoll£¨ÈÆXÖᣩ
const double cos_pitch = std::sqrt(1 - nx * nx); // µÈ¼ÛÓÚcos(pitch)
if (cos_pitch > 1e-7) {
// µ±cos_pitch·ÇÁãʱ£¬ÓÃatan2¼ÆËãRoll
angles.roll = std::asin(-ny/ cos_pitch) * (180.0 / M_PI);
}
else {
// µ±Pitch½Ó½ü¡À¦Ð/2ʱ£¬RollÎÞ·¨È·¶¨£¬ÉèΪ0
angles.roll = 0.0;
}
// 4. ¼ÙÉèyawΪ0£¨ÈÆZÖᣩ
angles.yaw= 0.0;
return angles;
}
// ¶¨Òå3x3Ðýת¾ØÕó½á¹¹Ìå
struct RotationMatrix {
double data[3][3]; // ÐÐÓÅÏÈ´æ´¢ [row][col]
};
// ½«½Ç¶Èת»»Îª»¡¶È
inline double degreesToRadians(double degrees) {
return degrees * M_PI / 180.0;
}
// ´ÓÅ·À­½Ç¼ÆËãÐýת¾ØÕó (ZYX˳Ðò: Æ«º½Z -> ¸©ÑöY -> ºá¹öX)
RotationMatrix eulerToRotationMatrix(double yaw_deg, double pitch_deg, double roll_deg) {
RotationMatrix R;
// ½Ç¶Èת»¡¶È
double yaw = degreesToRadians(yaw_deg);
double pitch = degreesToRadians(pitch_deg);
double roll = degreesToRadians(roll_deg);
// Ô¤¼ÆËãÈý½Çº¯Êý
double cy = cos(yaw);
double sy = sin(yaw);
double cp = cos(pitch);
double sp = sin(pitch);
double cr = cos(roll);
double sr = sin(roll);
// ¼ÆËãÐýת¾ØÕóÔªËØ£¨ZYX˳Ðò = Rz * Ry * Rx£©
R.data[0][0] = cy * cp;
R.data[0][1] = cy * sp * sr - sy * cr;
R.data[0][2] = cy * sp * cr + sy * sr;
R.data[1][0] = sy * cp;
R.data[1][1] = sy * sp * sr + cy * cr;
R.data[1][2] = sy * sp * cr - cy * sr;
R.data[2][0] = -sp;
R.data[2][1] = cp * sr;
R.data[2][2] = cp * cr;
return R;
}
// ¶¨ÒåÈýάÏòÁ¿½á¹¹Ìå
struct Vector3 {
double x, y, z;
Vector3(double x_, double y_, double z_) : x(x_), y(y_), z(z_) {}
};
// ¶¨ÒåËÄÔªÊý½á¹¹Ìå
struct Quaternion {
double w, x, y, z;
Quaternion(double w_, double x_, double y_, double z_)
: w(w_), x(x_), y(y_), z(z_) {}
};
// ¼ÆËãÁ½¸öÏòÁ¿µÄÐýתËÄÔªÊý
Quaternion rotationBetweenVectors(const Vector3& a, const Vector3& b) {
// ¹éÒ»»¯ÊäÈëÏòÁ¿
const double eps = 1e-7;
double a_len = std::sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
double b_len = std::sqrt(b.x * b.x + b.y * b.y + b.z * b.z);
if (a_len < eps || b_len < eps) {
// ÁãÏòÁ¿ÎÞ·¨¶¨ÒåÐýת£¬·µ»Øµ¥Î»ËÄÔªÊý
return Quaternion(1.0, 0.0, 0.0, 0.0);
}
Vector3 a_norm(a.x / a_len, a.y / a_len, a.z / a_len);
Vector3 b_norm(b.x / b_len, b.y / b_len, b.z / b_len);
double cos_theta = a_norm.x * b_norm.x + a_norm.y * b_norm.y + a_norm.z * b_norm.z;
// ´¦Àí¹²ÏßÇé¿ö
if (cos_theta > 1.0 - eps) {
// ÏòÁ¿·½ÏòÏàͬ£¬ÎÞÐèÐýת
return Quaternion(1.0, 0.0, 0.0, 0.0);
}
else if (cos_theta < -1.0 + eps) {
// ÏòÁ¿·½ÏòÏà·´£¬ÈÆÈÎÒâ´¹Ö±ÖáÐýת180¶È
Vector3 axis(1.0, 0.0, 0.0); // ĬÈÏÑ¡ÔñXÖá
if (std::abs(a_norm.y) < eps && std::abs(a_norm.z) < eps) {
// Èç¹ûa½Ó½üXÖᣬÔòÑ¡ÔñYÖá×÷ΪÐýתÖá
axis = Vector3(0.0, 1.0, 0.0);
}
return Quaternion(0.0, axis.x, axis.y, axis.z); // 180¶ÈÐýת
}
// ¼ÆËãÐýתÖáºÍ°ë½Ç
Vector3 axis = Vector3(
a_norm.y * b_norm.z - a_norm.z * b_norm.y,
a_norm.z * b_norm.x - a_norm.x * b_norm.z,
a_norm.x * b_norm.y - a_norm.y * b_norm.x
);
double axis_len = std::sqrt(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z);
if (axis_len < eps) { // ·ÀÖ¹³ýÁã
return Quaternion(1.0, 0.0, 0.0, 0.0);
}
axis.x /= axis_len;
axis.y /= axis_len;
axis.z /= axis_len;
double half_cos = std::sqrt(0.5 * (1.0 + cos_theta));
double half_sin = std::sqrt(0.5 * (1.0 - cos_theta));
return Quaternion(
half_cos,
half_sin * axis.x,
half_sin * axis.y,
half_sin * axis.z
);
}
void quaternionToMatrix(const Quaternion& q, double mat[3][3]) {
double xx = q.x * q.x, yy = q.y * q.y, zz = q.z * q.z;
double xy = q.x * q.y, xz = q.x * q.z, yz = q.y * q.z;
double wx = q.w * q.x, wy = q.w * q.y, wz = q.w * q.z;
mat[0][0] = 1 - 2 * (yy + zz);
mat[0][1] = 2 * (xy - wz);
mat[0][2] = 2 * (xz + wy);
mat[1][0] = 2 * (xy + wz);
mat[1][1] = 1 - 2 * (xx + zz);
mat[1][2] = 2 * (yz - wx);
mat[2][0] = 2 * (xz - wy);
mat[2][1] = 2 * (yz + wx);
mat[2][2] = 1 - 2 * (xx + yy);
}
//¼ÆËãÒ»¸öÆ½Ãæµ÷ƽ²ÎÊý¡£
//Êý¾ÝÊäÈëÖпÉÒÔÓÐÒ»¸öµØÆ½ÃæºÍ²Î¿¼µ÷Æ½Æ½Ãæ£¬ÒÔ×î¸ßµÄÆ½Ãæ½øÐе÷ƽ
//Ðýת¾ØÕóΪµ÷ƽ²ÎÊý£¬¼´½«Æ½Ãæ·¨Ïòµ÷ÕûΪ´¹Ö±ÏòÁ¿µÄ²ÎÊý
SSG_planeCalibPara sg_getPlaneCalibPara(
SVzNL3DLaserLine* laser3DPoints,
int lineNum)
{
//ÉèÖóõʼ½á¹û
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;
//ͳ¼Æz·¶Î§
SVzNLRangeD zRange = { 0, -1 }; //< Z·¶Î§
for (int line = 0; line < lineNum; line++)
{
for (int i = 0; i < laser3DPoints[line].nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &laser3DPoints[line].p3DPosition[i];
if (pt3D->pt3D.z < 1e-4)
continue;
//z
if (zRange.max < zRange.min)
{
zRange.min = pt3D->pt3D.z;
zRange.max = pt3D->pt3D.z;
}
else
{
if (zRange.min > pt3D->pt3D.z)
zRange.min = pt3D->pt3D.z;
if (zRange.max < pt3D->pt3D.z)
zRange.max = pt3D->pt3D.z;
}
}
}
//ÔÚZ·½Ïò½øÐÐͳ¼Æ£¬È¡µÚÒ»¸ö¼«Öµ
//ÒÔmmΪµ¥Î»£¬¼ò»¯Á¿»¯
int zHistSize = (int)(zRange.max - zRange.min) + 1;
if (zHistSize == 0)
return planePara;
std::vector<int> zHist;
zHist.resize(zHistSize);
int totalPntSize = 0;
for (int line = 0; line < lineNum; line++)
{
for (int i = 0; i < laser3DPoints[line].nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &laser3DPoints[line].p3DPosition[i];
if (pt3D->pt3D.z < 1e-4)
continue;
totalPntSize++;
int histPos = (int)(pt3D->pt3D.z - zRange.min);
zHist[histPos] ++;
}
}
std::vector<int> zSumHist;
zSumHist.resize(zHistSize);
bool isSame = true;
//ÒÔÀåÃ×Ϊµ¥Î»½øÐÐÀÛ¼Ó
for (int i = 0; i < zHistSize; i++)
{
int sumValue = 0;
for (int j = i - 5; j <= i + 5; j++)
{
if ((j >= 0) && (j < zHistSize))
sumValue += zHist[j];
}
zSumHist[i] = sumValue;
if (i > 0)
{
if (sumValue != zSumHist[i - 1])
isSame = false;
}
}
if(true == isSame)
{
//²»½øÐÐÀÛ¼Ó£¨Èç¹ûÀÛ¼Ó£¬ÀÛ¼ÓÖµÏàµÈ£©
for (int i = 0; i < zHistSize; i++)
zSumHist[i] = zHist[i];
}
//ѰÕÒ¼«Öµ
int _state = 0;
int pre_i = -1;
int sEdgePtIdx = -1;
int eEdgePtIdx = -1;
int pre_data = -1;
std::vector< SSG_intPair> pkTop;
std::vector< SSG_intPair> pkBtm;
std::vector<int> pkBtmBackIndexing;
pkBtmBackIndexing.resize(zHistSize);
for (int i = 0; i < zHistSize; i++)
pkBtmBackIndexing[i] = -1;
for (int i = 0; i < zHistSize; i++)
{
int curr_data = zSumHist[i];
if (pre_data < 0)
{
sEdgePtIdx = i;
eEdgePtIdx = i;
pre_data = curr_data;
pre_i = i;
continue;
}
eEdgePtIdx = i;
double z_diff = curr_data - pre_data;
switch (_state)
{
case 0: //³õ̬
if (z_diff < 0) //Ͻµ
{
_state = 2;
}
else if (z_diff > 0) //ÉÏÉý
{
_state = 1;
}
break;
case 1: //ÉÏÉý
if (z_diff < 0) //Ͻµ
{
pkTop.push_back({pre_i, pre_data});
_state = 2;
}
else if(i == (zHistSize-1))
pkTop.push_back({ i, curr_data });
break;
case 2: //Ͻµ
if (z_diff > 0) // ÉÏÉý
{
int pkBtmIdx = (int)pkBtm.size();
pkBtmBackIndexing[pre_i] = pkBtmIdx;
pkBtm.push_back({ pre_i, pre_data });
_state = 1;
}
else if (i == (zHistSize - 1))
{
int pkBtmIdx = (int)pkBtm.size();
pkBtmBackIndexing[i] = pkBtmIdx;
pkBtm.push_back({ i, curr_data });
}
break;
default:
_state = 0;
break;
}
pre_data = curr_data;
pre_i = i;
}
//ѰÕÒµÚÒ»¸ö³¬¹ý×ܵãÊý1/3µÄ¼«Öµµã
if (pkTop.size() < 1)
return planePara;
int pntSizeTh = totalPntSize / 10;
SSG_intPair* vldPeak = NULL;
for (int i = 0, i_max = (int)pkTop.size(); i < i_max; i++)
{
if (pkTop[i].data_1 > pntSizeTh)
{
vldPeak = &pkTop[i];
break;
}
}
if (NULL == vldPeak)
return planePara;
//ѰÕÒ¿ªÊ¼ºÍ½áÊøÎ»ÖÃ
//ÏòǰÏòºóѰÕÒ
int preBtmIdx = -1;
for (int j = vldPeak->data_0 - 1; j >= 0; j--)
{
if (pkBtmBackIndexing[j] >= 0)
{
int idx = pkBtmBackIndexing[j];
if (pkBtm[idx].data_1 < (vldPeak->data_1 / 2))
{
preBtmIdx = j;
break;
}
}
}
int postBtmIdx = -1;
for (int j = vldPeak->data_0 + 1; j <zHistSize; j++)
{
if (pkBtmBackIndexing[j] >= 0)
{
int idx = pkBtmBackIndexing[j];
if (pkBtm[idx].data_1 < (vldPeak->data_1 / 2))
{
postBtmIdx = j;
break;
}
}
}
SVzNLRangeD topZRange;
if (preBtmIdx < 0)
topZRange.min = zRange.min;
else
topZRange.min = (float)preBtmIdx + zRange.min;
if (postBtmIdx < 0)
topZRange.max = zRange.max;
else
topZRange.max = (float)postBtmIdx + zRange.min;
//È¡Êý¾Ý
std::vector<cv::Point3f> Points3ds;
for (int line = 0; line < lineNum; line++)
{
for (int i = 0; i < laser3DPoints[line].nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &laser3DPoints[line].p3DPosition[i];
if (pt3D->pt3D.z < 1e-4)
continue;
if ((pt3D->pt3D.z >= topZRange.min) && (pt3D->pt3D.z <= topZRange.max))
{
cv::Point3f a_vldPt;
a_vldPt.x = (float)pt3D->pt3D.x;
a_vldPt.y = (float)pt3D->pt3D.y;
a_vldPt.z = (float)pt3D->pt3D.z;
Points3ds.push_back(a_vldPt);
}
}
}
//Æ½ÃæÄâºÏ
std::vector<double> planceFunc;
vzCaculateLaserPlane(Points3ds, planceFunc);
#if 1 //Á½¸öÏòÁ¿µÄÐýתÐýת£¬Ê¹ÓÃËÄÔªÊý·¨£¬
Vector3 a = Vector3(planceFunc[0], planceFunc[1], planceFunc[2]);
Vector3 b = Vector3(0, 0, -1.0);
Quaternion quanPara = rotationBetweenVectors(a, b);
RotationMatrix rMatrix;
quaternionToMatrix(quanPara, rMatrix.data);
//¼ÆËã·´ÏòÐýת¾ØÕó
Quaternion invQuanPara = rotationBetweenVectors(b, a);
RotationMatrix invMatrix;
quaternionToMatrix(invQuanPara, invMatrix.data);
#else //¸ù¾ÝÆ½ÃæµÄ·¨ÏòÁ¿¼ÆËãÅ·À­½Ç£¬½ø¶ø¼ÆËãÐýת¾ØÕó
//²ÎÊý¼ÆËã
SSG_EulerAngles eulerPra = planeNormalToEuler(planceFunc[0], planceFunc[1], planceFunc[2]);
//·´Éä½øÐÐУÕý
eulerPra.roll = eulerPra.roll;
eulerPra.pitch = eulerPra.pitch;
eulerPra.yaw = eulerPra.yaw;
RotationMatrix rMatrix = eulerToRotationMatrix(eulerPra.yaw, eulerPra.pitch, eulerPra.roll);
#endif
planePara.planeCalib[0] = rMatrix.data[0][0];
planePara.planeCalib[1] = rMatrix.data[0][1];
planePara.planeCalib[2] = rMatrix.data[0][2];
planePara.planeCalib[3] = rMatrix.data[1][0];
planePara.planeCalib[4] = rMatrix.data[1][1];
planePara.planeCalib[5] = rMatrix.data[1][2];
planePara.planeCalib[6] = rMatrix.data[2][0];
planePara.planeCalib[7] = rMatrix.data[2][1];
planePara.planeCalib[8] = rMatrix.data[2][2];
planePara.invRMatrix[0] = invMatrix.data[0][0];
planePara.invRMatrix[1] = invMatrix.data[0][1];
planePara.invRMatrix[2] = invMatrix.data[0][2];
planePara.invRMatrix[3] = invMatrix.data[1][0];
planePara.invRMatrix[4] = invMatrix.data[1][1];
planePara.invRMatrix[5] = invMatrix.data[1][2];
planePara.invRMatrix[6] = invMatrix.data[2][0];
planePara.invRMatrix[7] = invMatrix.data[2][1];
planePara.invRMatrix[8] = invMatrix.data[2][2];
#if 0 //test: Á½¸ö¾ØÕóµÄ³Ë»ý±ØÐëÊǵ¥Î»Õó
double testMatrix[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
testMatrix[i][j] = 0;
for (int m = 0; m < 3; m++)
testMatrix[i][j] += invMatrix.data[i][m] * rMatrix.data[m][j];
}
}
#endif
//Êý¾Ý½øÐÐת»»
SVzNLRangeD calibZRange = { 0, -1 };
topZRange = { 0, -1 };
for (int i = 0, i_max = (int)Points3ds.size(); i < i_max; i++)
{
//z
if (topZRange.max < topZRange.min)
{
topZRange.min = Points3ds[i].z;
topZRange.max = Points3ds[i].z;
}
else
{
if (topZRange.min > Points3ds[i].z)
topZRange.min = Points3ds[i].z;
if (topZRange.max < Points3ds[i].z)
topZRange.max = Points3ds[i].z;
}
cv::Point3f a_calibPt;
a_calibPt.x = (float)(Points3ds[i].x * planePara.planeCalib[0] + Points3ds[i].y * planePara.planeCalib[1] + Points3ds[i].z * planePara.planeCalib[2]);
a_calibPt.y = (float)(Points3ds[i].x * planePara.planeCalib[3] + Points3ds[i].y * planePara.planeCalib[4] + Points3ds[i].z * planePara.planeCalib[5]);
a_calibPt.z = (float)(Points3ds[i].x * planePara.planeCalib[6] + Points3ds[i].y * planePara.planeCalib[7] + Points3ds[i].z * planePara.planeCalib[8]);
//z
if (calibZRange.max < calibZRange.min)
{
calibZRange.min = a_calibPt.z;
calibZRange.max = a_calibPt.z;
}
else
{
if (calibZRange.min > a_calibPt.z)
calibZRange.min = a_calibPt.z;
if (calibZRange.max < a_calibPt.z)
calibZRange.max = a_calibPt.z;
}
}
planePara.planeHeight = calibZRange.min;
return planePara;
}
//¼ÆËãÒ»¸öÆ½Ãæµ÷ƽ²ÎÊý¡£
//Êý¾ÝÊäÈëÖпÉÒÔÓÐÒ»¸öµØÆ½ÃæºÍ²Î¿¼µ÷Æ½Æ½Ãæ£¬ÒÔ×î¸ßµÄÆ½Ãæ½øÐе÷ƽ
//Ðýת¾ØÕóΪµ÷ƽ²ÎÊý£¬¼´½«Æ½Ãæ·¨Ïòµ÷ÕûΪ´¹Ö±ÏòÁ¿µÄ²ÎÊý
SSG_planeCalibPara sg_getPlaneCalibPara2(
std::vector< std::vector<SVzNL3DPosition>>& scanLines)
{
//ÉèÖóõʼ½á¹û
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;
int lineNum = (int)scanLines.size();
//ͳ¼Æz·¶Î§
SVzNLRangeD zRange = { 0, -1 }; //< Z·¶Î§
for (int line = 0; line < lineNum; line++)
{
int nPositionCnt = (int)scanLines[line].size();
for (int i = 0; i < nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->pt3D.z < 1e-4)
continue;
//z
if (zRange.max < zRange.min)
{
zRange.min = pt3D->pt3D.z;
zRange.max = pt3D->pt3D.z;
}
else
{
if (zRange.min > pt3D->pt3D.z)
zRange.min = pt3D->pt3D.z;
if (zRange.max < pt3D->pt3D.z)
zRange.max = pt3D->pt3D.z;
}
}
}
//ÔÚZ·½Ïò½øÐÐͳ¼Æ£¬È¡µÚÒ»¸ö¼«Öµ
//ÒÔmmΪµ¥Î»£¬¼ò»¯Á¿»¯
int zHistSize = (int)(zRange.max - zRange.min) + 1;
if (zHistSize == 0)
return planePara;
std::vector<int> zHist;
zHist.resize(zHistSize);
int totalPntSize = 0;
for (int line = 0; line < lineNum; line++)
{
int nPositionCnt = (int)scanLines[line].size();
for (int i = 0; i < nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->pt3D.z < 1e-4)
continue;
totalPntSize++;
int histPos = (int)(pt3D->pt3D.z - zRange.min);
zHist[histPos] ++;
}
}
std::vector<int> zSumHist;
zSumHist.resize(zHistSize);
bool isSame = true;
//ÒÔÀåÃ×Ϊµ¥Î»½øÐÐÀÛ¼Ó
for (int i = 0; i < zHistSize; i++)
{
int sumValue = 0;
for (int j = i - 5; j <= i + 5; j++)
{
if ((j >= 0) && (j < zHistSize))
sumValue += zHist[j];
}
zSumHist[i] = sumValue;
if (i > 0)
{
if (sumValue != zSumHist[i - 1])
isSame = false;
}
}
if (true == isSame)
{
//²»½øÐÐÀÛ¼Ó£¨Èç¹ûÀÛ¼Ó£¬ÀÛ¼ÓÖµÏàµÈ£©
for (int i = 0; i < zHistSize; i++)
zSumHist[i] = zHist[i];
}
//ѰÕÒ¼«Öµ
int _state = 0;
int pre_i = -1;
int sEdgePtIdx = -1;
int eEdgePtIdx = -1;
int pre_data = -1;
std::vector< SSG_intPair> pkTop;
std::vector< SSG_intPair> pkBtm;
std::vector<int> pkBtmBackIndexing;
pkBtmBackIndexing.resize(zHistSize);
for (int i = 0; i < zHistSize; i++)
pkBtmBackIndexing[i] = -1;
for (int i = 0; i < zHistSize; i++)
{
int curr_data = zSumHist[i];
if (pre_data < 0)
{
sEdgePtIdx = i;
eEdgePtIdx = i;
pre_data = curr_data;
pre_i = i;
continue;
}
eEdgePtIdx = i;
double z_diff = curr_data - pre_data;
switch (_state)
{
case 0: //³õ̬
if (z_diff < 0) //Ͻµ
{
_state = 2;
}
else if (z_diff > 0) //ÉÏÉý
{
_state = 1;
}
break;
case 1: //ÉÏÉý
if (z_diff < 0) //Ͻµ
{
pkTop.push_back({ pre_i, pre_data });
_state = 2;
}
else if (i == (zHistSize - 1))
pkTop.push_back({ i, curr_data });
break;
case 2: //Ͻµ
if (z_diff > 0) // ÉÏÉý
{
int pkBtmIdx = (int)pkBtm.size();
pkBtmBackIndexing[pre_i] = pkBtmIdx;
pkBtm.push_back({ pre_i, pre_data });
_state = 1;
}
else if (i == (zHistSize - 1))
{
int pkBtmIdx = (int)pkBtm.size();
pkBtmBackIndexing[i] = pkBtmIdx;
pkBtm.push_back({ i, curr_data });
}
break;
default:
_state = 0;
break;
}
pre_data = curr_data;
pre_i = i;
}
//ѰÕÒµÚÒ»¸ö³¬¹ý×ܵãÊý1/3µÄ¼«Öµµã
if (pkTop.size() < 1)
return planePara;
int pntSizeTh = totalPntSize / 10;
SSG_intPair* vldPeak = NULL;
for (int i = 0, i_max = (int)pkTop.size(); i < i_max; i++)
{
if (pkTop[i].data_1 > pntSizeTh)
{
vldPeak = &pkTop[i];
break;
}
}
if (NULL == vldPeak)
return planePara;
//ѰÕÒ¿ªÊ¼ºÍ½áÊøÎ»ÖÃ
//ÏòǰÏòºóѰÕÒ
int preBtmIdx = -1;
for (int j = vldPeak->data_0 - 1; j >= 0; j--)
{
if (pkBtmBackIndexing[j] >= 0)
{
int idx = pkBtmBackIndexing[j];
if (pkBtm[idx].data_1 < (vldPeak->data_1 / 2))
{
preBtmIdx = j;
break;
}
}
}
int postBtmIdx = -1;
for (int j = vldPeak->data_0 + 1; j < zHistSize; j++)
{
if (pkBtmBackIndexing[j] >= 0)
{
int idx = pkBtmBackIndexing[j];
if (pkBtm[idx].data_1 < (vldPeak->data_1 / 2))
{
postBtmIdx = j;
break;
}
}
}
SVzNLRangeD topZRange;
if (preBtmIdx < 0)
topZRange.min = zRange.min;
else
topZRange.min = (float)preBtmIdx + zRange.min;
if (postBtmIdx < 0)
topZRange.max = zRange.max;
else
topZRange.max = (float)postBtmIdx + zRange.min;
//È¡Êý¾Ý
std::vector<cv::Point3f> Points3ds;
for (int line = 0; line < lineNum; line++)
{
int nPositionCnt = (int)scanLines[line].size();
for (int i = 0; i < nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->pt3D.z < 1e-4)
continue;
if ((pt3D->pt3D.z >= topZRange.min) && (pt3D->pt3D.z <= topZRange.max))
{
cv::Point3f a_vldPt;
a_vldPt.x = (float)pt3D->pt3D.x;
a_vldPt.y = (float)pt3D->pt3D.y;
a_vldPt.z = (float)pt3D->pt3D.z;
Points3ds.push_back(a_vldPt);
}
}
}
//Æ½ÃæÄâºÏ
std::vector<double> planceFunc;
vzCaculateLaserPlane(Points3ds, planceFunc);
#if 1 //Á½¸öÏòÁ¿µÄÐýתÐýת£¬Ê¹ÓÃËÄÔªÊý·¨£¬
Vector3 a = Vector3(planceFunc[0], planceFunc[1], planceFunc[2]);
Vector3 b = Vector3(0, 0, -1.0);
Quaternion quanPara = rotationBetweenVectors(a, b);
RotationMatrix rMatrix;
quaternionToMatrix(quanPara, rMatrix.data);
//¼ÆËã·´ÏòÐýת¾ØÕó
Quaternion invQuanPara = rotationBetweenVectors(b, a);
RotationMatrix invMatrix;
quaternionToMatrix(invQuanPara, invMatrix.data);
#else //¸ù¾ÝÆ½ÃæµÄ·¨ÏòÁ¿¼ÆËãÅ·À­½Ç£¬½ø¶ø¼ÆËãÐýת¾ØÕó
//²ÎÊý¼ÆËã
SSG_EulerAngles eulerPra = planeNormalToEuler(planceFunc[0], planceFunc[1], planceFunc[2]);
//·´Éä½øÐÐУÕý
eulerPra.roll = eulerPra.roll;
eulerPra.pitch = eulerPra.pitch;
eulerPra.yaw = eulerPra.yaw;
RotationMatrix rMatrix = eulerToRotationMatrix(eulerPra.yaw, eulerPra.pitch, eulerPra.roll);
#endif
planePara.planeCalib[0] = rMatrix.data[0][0];
planePara.planeCalib[1] = rMatrix.data[0][1];
planePara.planeCalib[2] = rMatrix.data[0][2];
planePara.planeCalib[3] = rMatrix.data[1][0];
planePara.planeCalib[4] = rMatrix.data[1][1];
planePara.planeCalib[5] = rMatrix.data[1][2];
planePara.planeCalib[6] = rMatrix.data[2][0];
planePara.planeCalib[7] = rMatrix.data[2][1];
planePara.planeCalib[8] = rMatrix.data[2][2];
planePara.invRMatrix[0] = invMatrix.data[0][0];
planePara.invRMatrix[1] = invMatrix.data[0][1];
planePara.invRMatrix[2] = invMatrix.data[0][2];
planePara.invRMatrix[3] = invMatrix.data[1][0];
planePara.invRMatrix[4] = invMatrix.data[1][1];
planePara.invRMatrix[5] = invMatrix.data[1][2];
planePara.invRMatrix[6] = invMatrix.data[2][0];
planePara.invRMatrix[7] = invMatrix.data[2][1];
planePara.invRMatrix[8] = invMatrix.data[2][2];
#if 0 //test: Á½¸ö¾ØÕóµÄ³Ë»ý±ØÐëÊǵ¥Î»Õó
double testMatrix[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
testMatrix[i][j] = 0;
for (int m = 0; m < 3; m++)
testMatrix[i][j] += invMatrix.data[i][m] * rMatrix.data[m][j];
}
}
#endif
//Êý¾Ý½øÐÐת»»
SVzNLRangeD calibZRange = { 0, -1 };
topZRange = { 0, -1 };
double sumMeanZ = 0;
int sumSize = 0;
for (int i = 0, i_max = (int)Points3ds.size(); i < i_max; i++)
{
//z
if (topZRange.max < topZRange.min)
{
topZRange.min = Points3ds[i].z;
topZRange.max = Points3ds[i].z;
}
else
{
if (topZRange.min > Points3ds[i].z)
topZRange.min = Points3ds[i].z;
if (topZRange.max < Points3ds[i].z)
topZRange.max = Points3ds[i].z;
}
cv::Point3f a_calibPt;
a_calibPt.x = (float)(Points3ds[i].x * planePara.planeCalib[0] + Points3ds[i].y * planePara.planeCalib[1] + Points3ds[i].z * planePara.planeCalib[2]);
a_calibPt.y = (float)(Points3ds[i].x * planePara.planeCalib[3] + Points3ds[i].y * planePara.planeCalib[4] + Points3ds[i].z * planePara.planeCalib[5]);
a_calibPt.z = (float)(Points3ds[i].x * planePara.planeCalib[6] + Points3ds[i].y * planePara.planeCalib[7] + Points3ds[i].z * planePara.planeCalib[8]);
//z
if (calibZRange.max < calibZRange.min)
{
calibZRange.min = a_calibPt.z;
calibZRange.max = a_calibPt.z;
sumMeanZ += a_calibPt.z;
sumSize++;
}
else
{
if (calibZRange.min > a_calibPt.z)
calibZRange.min = a_calibPt.z;
if (calibZRange.max < a_calibPt.z)
calibZRange.max = a_calibPt.z;
sumMeanZ += a_calibPt.z;
sumSize++;
}
}
if (sumSize > 0)
sumMeanZ = sumMeanZ / (double)sumSize;
planePara.planeHeight = sumMeanZ; // calibZRange.min;
return planePara;
}
SSG_planeCalibPara sg_getPlaneCalibPara2_ROI(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
SVzNL3DRangeD roi)
{
//ÉèÖóõʼ½á¹û
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;
int lineNum = scanLines.size();
//È¡Êý¾Ý
std::vector<cv::Point3f> Points3ds;
for (int line = 0; line < lineNum; line++)
{
int nPositionCnt = (int)scanLines[line].size();
for (int i = 0; i < nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &scanLines[line][i];
if (pt3D->pt3D.z < 1e-4)
continue;
bool isValid = false;
if ((pt3D->pt3D.x >= roi.xRange.min) && (pt3D->pt3D.x <= roi.xRange.max) &&
(pt3D->pt3D.y >= roi.yRange.min) && (pt3D->pt3D.y <= roi.yRange.max) &&
(pt3D->pt3D.z >= roi.zRange.min) && (pt3D->pt3D.y <= roi.zRange.max))
{
cv::Point3f a_vldPt;
a_vldPt.x = (float)pt3D->pt3D.x;
a_vldPt.y = (float)pt3D->pt3D.y;
a_vldPt.z = (float)pt3D->pt3D.z;
Points3ds.push_back(a_vldPt);
}
}
}
//Æ½ÃæÄâºÏ
std::vector<double> planceFunc;
vzCaculateLaserPlane(Points3ds, planceFunc);
#if 1 //Á½¸öÏòÁ¿µÄÐýתÐýת£¬Ê¹ÓÃËÄÔªÊý·¨£¬
Vector3 a = Vector3(planceFunc[0], planceFunc[1], planceFunc[2]);
Vector3 b = Vector3(0, 0, -1.0);
Quaternion quanPara = rotationBetweenVectors(a, b);
RotationMatrix rMatrix;
quaternionToMatrix(quanPara, rMatrix.data);
//¼ÆËã·´ÏòÐýת¾ØÕó
Quaternion invQuanPara = rotationBetweenVectors(b, a);
RotationMatrix invMatrix;
quaternionToMatrix(invQuanPara, invMatrix.data);
#else //¸ù¾ÝÆ½ÃæµÄ·¨ÏòÁ¿¼ÆËãÅ·À­½Ç£¬½ø¶ø¼ÆËãÐýת¾ØÕó
//²ÎÊý¼ÆËã
SSG_EulerAngles eulerPra = planeNormalToEuler(planceFunc[0], planceFunc[1], planceFunc[2]);
//·´Éä½øÐÐУÕý
eulerPra.roll = eulerPra.roll;
eulerPra.pitch = eulerPra.pitch;
eulerPra.yaw = eulerPra.yaw;
RotationMatrix rMatrix = eulerToRotationMatrix(eulerPra.yaw, eulerPra.pitch, eulerPra.roll);
#endif
planePara.planeCalib[0] = rMatrix.data[0][0];
planePara.planeCalib[1] = rMatrix.data[0][1];
planePara.planeCalib[2] = rMatrix.data[0][2];
planePara.planeCalib[3] = rMatrix.data[1][0];
planePara.planeCalib[4] = rMatrix.data[1][1];
planePara.planeCalib[5] = rMatrix.data[1][2];
planePara.planeCalib[6] = rMatrix.data[2][0];
planePara.planeCalib[7] = rMatrix.data[2][1];
planePara.planeCalib[8] = rMatrix.data[2][2];
planePara.invRMatrix[0] = invMatrix.data[0][0];
planePara.invRMatrix[1] = invMatrix.data[0][1];
planePara.invRMatrix[2] = invMatrix.data[0][2];
planePara.invRMatrix[3] = invMatrix.data[1][0];
planePara.invRMatrix[4] = invMatrix.data[1][1];
planePara.invRMatrix[5] = invMatrix.data[1][2];
planePara.invRMatrix[6] = invMatrix.data[2][0];
planePara.invRMatrix[7] = invMatrix.data[2][1];
planePara.invRMatrix[8] = invMatrix.data[2][2];
#if 0 //test: Á½¸ö¾ØÕóµÄ³Ë»ý±ØÐëÊǵ¥Î»Õó
double testMatrix[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
testMatrix[i][j] = 0;
for (int m = 0; m < 3; m++)
testMatrix[i][j] += invMatrix.data[i][m] * rMatrix.data[m][j];
}
}
#endif
//Êý¾Ý½øÐÐת»»
SVzNLRangeD calibZRange = { 0, -1 };
for (int i = 0, i_max = (int)Points3ds.size(); i < i_max; i++)
{
cv::Point3f a_calibPt;
a_calibPt.x = (float)(Points3ds[i].x * planePara.planeCalib[0] + Points3ds[i].y * planePara.planeCalib[1] + Points3ds[i].z * planePara.planeCalib[2]);
a_calibPt.y = (float)(Points3ds[i].x * planePara.planeCalib[3] + Points3ds[i].y * planePara.planeCalib[4] + Points3ds[i].z * planePara.planeCalib[5]);
a_calibPt.z = (float)(Points3ds[i].x * planePara.planeCalib[6] + Points3ds[i].y * planePara.planeCalib[7] + Points3ds[i].z * planePara.planeCalib[8]);
//z
if (calibZRange.max < calibZRange.min)
{
calibZRange.min = a_calibPt.z;
calibZRange.max = a_calibPt.z;
}
else
{
if (calibZRange.min > a_calibPt.z)
calibZRange.min = a_calibPt.z;
if (calibZRange.max < a_calibPt.z)
calibZRange.max = a_calibPt.z;
}
}
planePara.planeHeight = calibZRange.min;
return planePara;
}
//¼ÆËãÒ»¸öÆ½Ãæµ÷ƽ²ÎÊý¡£
//ÒÔÊý¾ÝÊäÈëÖÐROIÒÔÄÚµÄµã½øÐÐÆ½ÃæÄâºÏ£¬¼ÆËãµ÷ƽ²ÎÊý
//Ðýת¾ØÕóΪµ÷ƽ²ÎÊý£¬¼´½«Æ½Ãæ·¨Ïòµ÷ÕûΪ´¹Ö±ÏòÁ¿µÄ²ÎÊý
SSG_planeCalibPara sg_getPlaneCalibPara_ROIs(
SVzNL3DLaserLine* laser3DPoints,
int lineNum,
std::vector<SVzNL3DRangeD>& ROIs)
{
//ÉèÖóõʼ½á¹û
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;
//È¡Êý¾Ý
std::vector<cv::Point3f> Points3ds;
for (int line = 0; line < lineNum; line++)
{
for (int i = 0; i < laser3DPoints[line].nPositionCnt; i++)
{
SVzNL3DPosition* pt3D = &laser3DPoints[line].p3DPosition[i];
if (pt3D->pt3D.z < 1e-4)
continue;
bool isValid = false;
for (int m = 0, m_max = (int)ROIs.size(); m < m_max; m++)
{
if ((pt3D->pt3D.x >= ROIs[m].xRange.min) && (pt3D->pt3D.x <= ROIs[m].xRange.max) &&
(pt3D->pt3D.y >= ROIs[m].yRange.min) && (pt3D->pt3D.y <= ROIs[m].yRange.max) &&
(pt3D->pt3D.z >= ROIs[m].zRange.min) && (pt3D->pt3D.y <= ROIs[m].zRange.max))
{
isValid = true;
break;
}
}
if (false == isValid)
continue;
cv::Point3f a_vldPt;
a_vldPt.x = (float)pt3D->pt3D.x;
a_vldPt.y = (float)pt3D->pt3D.y;
a_vldPt.z = (float)pt3D->pt3D.z;
Points3ds.push_back(a_vldPt);
}
}
//Æ½ÃæÄâºÏ
std::vector<double> planceFunc;
vzCaculateLaserPlane(Points3ds, planceFunc);
#if 1 //Á½¸öÏòÁ¿µÄÐýתÐýת£¬Ê¹ÓÃËÄÔªÊý·¨£¬
Vector3 a = Vector3(planceFunc[0], planceFunc[1], planceFunc[2]);
Vector3 b = Vector3(0, 0, -1.0);
Quaternion quanPara = rotationBetweenVectors(a, b);
RotationMatrix rMatrix;
quaternionToMatrix(quanPara, rMatrix.data);
//¼ÆËã·´ÏòÐýת¾ØÕó
Quaternion invQuanPara = rotationBetweenVectors(b, a);
RotationMatrix invMatrix;
quaternionToMatrix(invQuanPara, invMatrix.data);
#else //¸ù¾ÝÆ½ÃæµÄ·¨ÏòÁ¿¼ÆËãÅ·À­½Ç£¬½ø¶ø¼ÆËãÐýת¾ØÕó
//²ÎÊý¼ÆËã
SSG_EulerAngles eulerPra = planeNormalToEuler(planceFunc[0], planceFunc[1], planceFunc[2]);
//·´Éä½øÐÐУÕý
eulerPra.roll = eulerPra.roll;
eulerPra.pitch = eulerPra.pitch;
eulerPra.yaw = eulerPra.yaw;
RotationMatrix rMatrix = eulerToRotationMatrix(eulerPra.yaw, eulerPra.pitch, eulerPra.roll);
#endif
planePara.planeCalib[0] = rMatrix.data[0][0];
planePara.planeCalib[1] = rMatrix.data[0][1];
planePara.planeCalib[2] = rMatrix.data[0][2];
planePara.planeCalib[3] = rMatrix.data[1][0];
planePara.planeCalib[4] = rMatrix.data[1][1];
planePara.planeCalib[5] = rMatrix.data[1][2];
planePara.planeCalib[6] = rMatrix.data[2][0];
planePara.planeCalib[7] = rMatrix.data[2][1];
planePara.planeCalib[8] = rMatrix.data[2][2];
planePara.invRMatrix[0] = invMatrix.data[0][0];
planePara.invRMatrix[1] = invMatrix.data[0][1];
planePara.invRMatrix[2] = invMatrix.data[0][2];
planePara.invRMatrix[3] = invMatrix.data[1][0];
planePara.invRMatrix[4] = invMatrix.data[1][1];
planePara.invRMatrix[5] = invMatrix.data[1][2];
planePara.invRMatrix[6] = invMatrix.data[2][0];
planePara.invRMatrix[7] = invMatrix.data[2][1];
planePara.invRMatrix[8] = invMatrix.data[2][2];
#if 0 //test: Á½¸ö¾ØÕóµÄ³Ë»ý±ØÐëÊǵ¥Î»Õó
double testMatrix[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
testMatrix[i][j] = 0;
for (int m = 0; m < 3; m++)
testMatrix[i][j] += invMatrix.data[i][m] * rMatrix.data[m][j];
}
}
#endif
//Êý¾Ý½øÐÐת»»
SVzNLRangeD calibZRange = { 0, -1 };
for (int i = 0, i_max = (int)Points3ds.size(); i < i_max; i++)
{
cv::Point3f a_calibPt;
a_calibPt.x = (float)(Points3ds[i].x * planePara.planeCalib[0] + Points3ds[i].y * planePara.planeCalib[1] + Points3ds[i].z * planePara.planeCalib[2]);
a_calibPt.y = (float)(Points3ds[i].x * planePara.planeCalib[3] + Points3ds[i].y * planePara.planeCalib[4] + Points3ds[i].z * planePara.planeCalib[5]);
a_calibPt.z = (float)(Points3ds[i].x * planePara.planeCalib[6] + Points3ds[i].y * planePara.planeCalib[7] + Points3ds[i].z * planePara.planeCalib[8]);
//z
if (calibZRange.max < calibZRange.min)
{
calibZRange.min = a_calibPt.z;
calibZRange.max = a_calibPt.z;
}
else
{
if (calibZRange.min > a_calibPt.z)
calibZRange.min = a_calibPt.z;
if (calibZRange.max < a_calibPt.z)
calibZRange.max = a_calibPt.z;
}
}
planePara.planeHeight = calibZRange.min;
return planePara;
}
// ´ÓÐýת¾ØÕó¼ÆËãÅ·À­½Ç£¨Z-Y-X˳Ðò£©
SSG_EulerAngles rotationMatrixToEulerZYX(const double R[3][3]) {
SSG_EulerAngles angles;
// ¼ÆË㸩Ñö½Ç£¨pitch£©¦È
angles.pitch = asin(-R[2][0]); // asin·µ»Ø»¡¶È
// ¼ì²éÍòÏò½ÚËø£¨cos¦È½Ó½ü0£©
const double epsilon = 1e-6;
if (abs(cos(angles.pitch)) > epsilon) {
// ÎÞÍòÏò½ÚËø£¬Õý³£¼ÆËãyawºÍroll
angles.yaw = atan2(R[1][0], R[0][0]);
angles.roll = atan2(R[2][1], R[2][2]);
}
else {
// ÍòÏò½ÚËø£¬Ô¼¶¨roll=0£¬¼ÆËãyaw
angles.roll = 0.0;
angles.yaw = atan2(-R[0][1], R[1][1]);
}
// ½«»¡¶Èת»»Îª½Ç¶È
const double rad2deg = 180.0 / M_PI;
angles.yaw *= rad2deg;
angles.pitch *= rad2deg;
angles.roll *= rad2deg;
return angles;
}
// ´ÓÅ·À­½Ç¼ÆËãÐýת¾ØÕó£¨Z-Y-X˳Ðò£©
void eulerToRotationMatrixZYX(const SSG_EulerAngles& angles, double R[3][3]) {
// ½«½Ç¶Èת»»Îª»¡¶È
const double deg2rad = M_PI / 180.0;
const double yaw = angles.yaw * deg2rad;
const double pitch = angles.pitch * deg2rad;
const double roll = angles.roll * deg2rad;
// Ô¤¼ÆËãÈý½Çº¯ÊýÖµ
const double cy = cos(yaw), sy = sin(yaw);
const double cp = cos(pitch), sp = sin(pitch);
const double cr = cos(roll), sr = sin(roll);
#if 0
// ÈÆZÖáÐýת¾ØÕó
double Rz[3][3] = {
{cy, -sy, 0},
{sy, cy, 0},
{0, 0, 1}
};
// ÈÆYÖáÐýת¾ØÕó
double Ry[3][3] = {
{cp, 0, sp},
{0, 1, 0},
{-sp, 0, cp}
};
// ÈÆXÖáÐýת¾ØÕó
double Rx[3][3] = {
{1, 0, 0},
{0, cr, -sr},
{0, sr, cr}
};
// ¾ØÕóÏà³Ë˳Ðò£ºR = Rz * Ry * Rx
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
// ÏȼÆËã Rz * Ry
double temp[3][3] = { 0 };
for (int k = 0; k < 3; ++k) {
temp[i][j] += Rz[i][k] * Ry[k][j];
}
// ÔÙÓë Rx Ïà³Ë
R[i][j] = 0;
for (int k = 0; k < 3; ++k) {
R[i][j] += temp[i][k] * Rx[k][j];
}
}
}
#endif
// ÓÅ»¯ºóµÄÖ±½Ó¼ÆË㹫ʽ£¨±ÜÃâÖÐ¼ä¾ØÕó£©
R[0][0] = cy * cp;
R[0][1] = cy * sp * sr - sy * cr;
R[0][2] = cy * sp * cr + sy * sr;
R[1][0] = sy * cp;
R[1][1] = sy * sp * sr + cy * cr;
R[1][2] = sy * sp * cr - cy * sr;
R[2][0] = -sp;
R[2][1] = cp * sr;
R[2][2] = cp * cr;
}
//¸ù¾ÝÏà»ú×Ë̬¶ÔÏà»ú²É¼¯µÄ3DÊý¾Ý½øÐÐÐýת(ûÓÐÆ½ÒÆ)£¬½«Êý¾Ýµ÷ÕûΪ¸©ÊÓ״̬
///camPoseRΪ3x3¾ØÕó
void lineDataRT(SVzNL3DLaserLine* a_line, const double* camPoseR, double groundH)
{
for (int i = 0; i < a_line->nPositionCnt; i++)
{
SVzNL3DPoint a_pt = a_line->p3DPosition[i].pt3D;
if (a_pt.z < 1e-4)
continue;
double x = a_pt.x * camPoseR[0] + a_pt.y * camPoseR[1] + a_pt.z * camPoseR[2];
double y = a_pt.x * camPoseR[3] + a_pt.y * camPoseR[4] + a_pt.z * camPoseR[5];
double z = a_pt.x * camPoseR[6] + a_pt.y * camPoseR[7] + a_pt.z * camPoseR[8];
if ((groundH > 0) && (z > groundH)) //È¥³ýµØÃæ
z = 0;
a_pt.x = x;
a_pt.y = y;
a_pt.z = z;
a_line->p3DPosition[i].pt3D = a_pt;
}
return;
}
void lineDataRT_vector(std::vector< SVzNL3DPosition>& a_line, const double* camPoseR, double groundH)
{
for (int i = 0; i < a_line.size(); i++)
{
SVzNL3DPoint a_pt = a_line[i].pt3D;
if (a_pt.z < 1e-4)
continue;
double x = a_pt.x * camPoseR[0] + a_pt.y * camPoseR[1] + a_pt.z * camPoseR[2];
double y = a_pt.x * camPoseR[3] + a_pt.y * camPoseR[4] + a_pt.z * camPoseR[5];
double z = a_pt.x * camPoseR[6] + a_pt.y * camPoseR[7] + a_pt.z * camPoseR[8];
if ((groundH > 0) && (z > groundH)) //È¥³ýµØÃæ
z = 0;
a_pt.x = x;
a_pt.y = y;
a_pt.z = z;
a_line[i].pt3D = a_pt;
}
return;
}
void lineDataRT_RGBD(SVzNLXYZRGBDLaserLine* a_line, const double* camPoseR, double groundH)
{
for (int i = 0; i < a_line->nPointCnt; i++)
{
SVzNLPointXYZRGBA a_pt = a_line->p3DPoint[i];
if (a_pt.z < 1e-4)
continue;
double x = a_pt.x * camPoseR[0] + a_pt.y * camPoseR[1] + a_pt.z * camPoseR[2];
double y = a_pt.x * camPoseR[3] + a_pt.y * camPoseR[4] + a_pt.z * camPoseR[5];
double z = a_pt.x * camPoseR[6] + a_pt.y * camPoseR[7] + a_pt.z * camPoseR[8];
if ((groundH > 0) && (z > groundH)) //È¥³ýµØÃæ
z = 0;
a_pt.x = (float)x;
a_pt.y = (float)y;
a_pt.z = (float)z;
a_line->p3DPoint[i] = a_pt;
}
return;
}
//¶ÔÕ¤¸ñ»¯Êý¾Ý½øÐÐXYÆ½ÃæÉϵÄͶӰÁ¿»¯£¬²¢¶ÔÁ¿»¯²úÉúµÄ¿Õ°×µã½øÐвåÖµ
void pointClout2DProjection(
std::vector< std::vector<SVzNL3DPosition>>& gridScanData,
SVzNLRangeD x_range,
SVzNLRangeD y_range,
double scale,
int edgeSkip,
double inerPolateDistTh, //²åÖµãÐÖµ¡£´óÓÚ´ËãÐÖµµÄ²»½øÐÐÁ¿»¯²åÖµ
cv::Mat& projectionData,//ͶӰÁ¿»¯Êý¾Ý£¬³õʼ»¯ÎªÒ»¸ö¼«´óÖµ1e+6
cv::Mat& backIndexing //±ê¼Ç×ø±êË÷Òý£¬ÓÃÓÚ»ØÕÒ3D×ø±ê
)
{
int lineNum = (int)gridScanData.size();
if (lineNum == 0)
return;
int nPointCnt = (int)gridScanData[0].size();
for (int line = 0; line < lineNum; line++)
{
int pre_x = -1, pre_y = -1;
SVzNL3DPosition* prePt = NULL;
for (int i = 0; i < nPointCnt; i++)
{
SVzNL3DPosition* pt3D = &gridScanData[line][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)/scale + edgeSkip;
int py = (int)(y - y_range.min)/scale + edgeSkip;
cv::Vec2i v2i_exist = backIndexing.at<cv::Vec2i>(py, px);
#if 0
if ((v2i_exist[0] > 0) || (v2i_exist[1] > 0)) //¶à¸öµãÖØ¸´Í¶Ó°µ½Í¬Ò»¸öµãÉÏ£¬Ö»±£ÁôÒ»¸öÓÐЧµã
{
pt3D->pt3D.z = 0; //invalidate
}
else
#endif
{
cv::Vec2i v2i = { line, i };
backIndexing.at<cv::Vec2i>(py, px) = v2i;
projectionData.at<float>(py, px) = 1e+6;
//´¹Ö±²åÖµ
if (prePt)
{
//¼ÆËã¾àÀ룬³¬¹ýÒ»¶¨¾àÀëÔò²»²åÖµ
double dist = sqrt(pow(pt3D->pt3D.x - prePt->pt3D.x, 2) +
pow(pt3D->pt3D.y - prePt->pt3D.y, 2) +
pow(pt3D->pt3D.z - prePt->pt3D.z, 2));
if (dist < inerPolateDistTh)
{
std::vector<SVzNL2DPoint> interPts;
drawLine(
pre_x,
pre_y,
px,
py,
interPts);
for (int m = 0, m_max = (int)interPts.size(); m < m_max; m++)
projectionData.at<float>(interPts[m].y, interPts[m].x) = 1e+6;
}
}
prePt = pt3D;
pre_x = px;
pre_y = py;
}
}
}
//ˮƽ²åÖµ
int pixWin = (int)(inerPolateDistTh / scale);
for (int y = 0; y < projectionData.rows; y++)
{
int pre_x = -1;
for (int x = 0; x < projectionData.cols; x++)
{
double value = projectionData.at<float>(y, x);
if (value > 1e-4)
{
if (pre_x >= 0)
{
//²åÖµ
int x_diff = x - pre_x;
if ((x_diff > 1) && (x_diff < pixWin))
{
for (int m = pre_x + 1; m < x; m++)
projectionData.at<float>(y, m) = 1e+6;
}
}
pre_x = x;
}
}
}
}