上一篇文章使用二维上最近的像素点对边界点进行赋值,本文使用的方法为寻找邻域内,与边界点三维距离最近的有效点进行赋值。
依然以边界点为中心,一圈圈发散寻找有效点,只要在内圈找到了有效点,就在该圈内寻找三维距离最近的点,(把leave设置为true)不
再去寻找外圈的最近点(一般内圈点的三维距离都比外圈小),以下为参考代码:
(vertexBuff存放的顶点数据和labelColor一一对应)
cv::Mat labelMat(cv::Size(640,480),CV_8UC1,cv::Scalar(0));
for(int i=0;i<480;i++)
{
for(int j=0;j<640;j++)
{
labelMat.at<uchar>(i,j)=labelColor[640*i+j];
}
}
//cv::imshow("aaa",labelMat);
for(int i=0;i<480;i++)
{
for(int j=0;j<640;j++)
{
int label_temp=labelMat.at<uchar>(i,j);
if(label_temp==0)
{
float cur_vert[3]={vertexBuff.at<Eigen::Vector4f>(i, j)(0),
vertexBuff.at<Eigen::Vector4f>(i, j)(1),
vertexBuff.at<Eigen::Vector4f>(i, j)(2)}; //当前边界点三维坐标
float min=10.0;//用于记录最小距离
int x=i,y=j; //用于记录三维距离最近点的二维坐标
for(int k=1;k<=r;k++)
{
int start,end;
bool leave=false;
//(i-k,j-k) -> (i-k,j+k)
if(i-k>0)
{
start=(j-k>=0)?j-k:0;
end=(j+k<=639)?j+k:639;
for(int temp=start;temp<=end;temp++)
{
int aa=labelMat.at<uchar>(i-k,temp);
if(aa>0)
{
//calculate the distance
float neigh_vert[3]={vertexBuff.at<Eigen::Vector4f>(i-k, temp)(0),
vertexBuff.at<Eigen::Vector4f>(i-k, temp)(1),
vertexBuff.at<Eigen::Vector4f>(i-k, temp)(2)};
float dis=(neigh_vert[0]-cur_vert[0])*(neigh_vert[0]-cur_vert[0])+
(neigh_vert[1]-cur_vert[1])*(neigh_vert[1]-cur_vert[1])+
(neigh_vert[2]-cur_vert[2])*(neigh_vert[2]-cur_vert[2]);
if(dis<min)
{
min=dis;
x=i-k;
y=temp; //记录下min和位置
leave=true; //检测到有效值,在获取当前循环最近点坐标后,即可进行赋值操作
}
}
}
}
//(i-k,j-k) -> (i+k,j-k)
if(j-k>0)
{
start=(i-k>=0)?i-k:0;
end=(i+k<=479)?i+k:479;
for(int temp=start;temp<=end;temp++)
{
int aa=labelMat.at<uchar>(temp,j-k);
if(aa>0)
{
float neigh_vert[3]={vertexBuff.at<Eigen::Vector4f>(temp,j-k)(0),
vertexBuff.at<Eigen::Vector4f>(temp,j-k)(1),
vertexBuff.at<Eigen::Vector4f>(temp,j-k)(2)};
float dis=(neigh_vert[0]-cur_vert[0])*(neigh_vert[0]-cur_vert[0])+
(neigh_vert[1]-cur_vert[1])*(neigh_vert[1]-cur_vert[1])+
(neigh_vert[2]-cur_vert[2])*(neigh_vert[2]-cur_vert[2]);
if(dis<min)
{
min=dis;
x=temp;
y=j-k; //记录下min和位置
leave=true;
}
}
}
}
//(i-k,j+k) -> (i+k,j+k)
if(j+k<640)
{
start=(i-k>=0)?i-k:0;
end=(i+k<=479)?i+k:479;
for(int temp=start;temp<=end;temp++)
{
int aa=labelMat.at<uchar>(temp,j+k);
if(aa>0)
{
float neigh_vert[3]={vertexBuff.at<Eigen::Vector4f>(temp,j+k)(0),
vertexBuff.at<Eigen::Vector4f>(temp,j+k)(1),
vertexBuff.at<Eigen::Vector4f>(temp,j+k)(2)};
float dis=(neigh_vert[0]-cur_vert[0])*(neigh_vert[0]-cur_vert[0])+
(neigh_vert[1]-cur_vert[1])*(neigh_vert[1]-cur_vert[1])+
(neigh_vert[2]-cur_vert[2])*(neigh_vert[2]-cur_vert[2]);
if(dis<min)
{
min=dis;
x=temp;
y=j+k; //记录下min和位置
leave=true;
}
}
}
}
//(i+k,j-k) -> (i+k,j+k)
if(i+k<480)
{
start=(j-k>=0)?j-k:0;
end=(j+k<=639)?j+k:639;
for(int temp=start;temp<=end;temp++)
{
int aa=labelMat.at<uchar>(i+k,temp);
if(aa>0)
{
float neigh_vert[3]={vertexBuff.at<Eigen::Vector4f>(i+k, temp)(0),
vertexBuff.at<Eigen::Vector4f>(i+k, temp)(1),
vertexBuff.at<Eigen::Vector4f>(i+k, temp)(2)};
float dis=(neigh_vert[0]-cur_vert[0])*(neigh_vert[0]-cur_vert[0])+
(neigh_vert[1]-cur_vert[1])*(neigh_vert[1]-cur_vert[1])+
(neigh_vert[2]-cur_vert[2])*(neigh_vert[2]-cur_vert[2]);
if(dis<min)
{
min=dis;
x=i+k;
y=temp; //记录下min和位置
leave=true;
}
}
}
}
if(leave)
{
labelColor[640*i+j]=labelMat.at<uchar>(x,y);
break;
}
}
}
}
}
cv::imshow("bbb",labelMat);
cv::waitKey(1);
下图是二维最近和三维最近的两张结果图,第一张是基于二维的,第二张是基于三维距离的
可以看出,基于三维距离的赋值方法,稍优于二维的效果,但是因为其他原因,分割的效果依然不是非常理想的状态。
此项目基于三维法向量的性质进行分割,系统计算出来的法向量图存在较大的噪声,导致分割出来的结果效果很差,后面应该会寻找方案,解决法向量图的滤波问题