点云转为图像的相关处理

为什么会有这么一个操作呢?

是因为有些时候在三维上可能很难处理,但是在二维上却是很简单的事情,比如提取线性特征啊什么的,这些opencv都有很成熟的算法,直接调用就可以了(我这个憨坨坨刚开始准备直接在三维上面找直线)。这些代码呢是在很久之前写的,因为要放弃那个程序了(版本太低了,写的太差了),但是里面的代码我觉得还是可以记录一下。

首先是点云转为高程差影像(里面的ccPointCloud是cloudcompare带的),gridsize就是你的像素大小

typedef QVector LinePtsList

IplImage* Point2Img(ccPointCloud *theCloud, double gridSize,double dh,    const char *str)
{
    //将点云投影到XOY平面
    CCVector3 _min,_max;
    theCloud->getBoundingBox(_min,_max);    
    long npt = theCloud->size();
    float  len_X = _max.x - _min.x;
    float  len_Y = _max.y - _min.y;
    int _col=((int)(len_X/gridSize)+1);
    int _row=((int)(len_Y/gridSize)+1);
    _col = ( _col * 8 + 31 ) / 32 * 4;//一定要有此步骤,不然图像是变形的

    LinePtsList *childs = new LinePtsList[_row*_col];//存储格网的所有点
    LinePtsList *child_b;
    int xi,yi;

  for (long i =0 ; i < npt ;i++)
    {
        const CCVector3 *pt= theCloud->getPoint(i); 
        xi = (int)((pt->x - _min[0])/gridSize);
        yi = (int)((pt->y - _min[1])/gridSize);    

        child_b = childs+xi +yi * _col;//记录每个格网的所有点
        CCVector3 pt_add =  *pt;
        child_b->push_back(pt_add);
    }

    char *lpData=new char[_row*_col];
    for(int i=0;i<_col;i++)
        for(int j=0;j<_row;j++)
        {
            child_b = childs+i +j * _col;
            if(child_b->size()>0)
            {
                CCVector3 range1,range2;
                getBBofCCVector3list(child_b,&range1,&range2);    
                if(range2.z-range1.z                     lpData[i+(_row-j-1)*_col]=0;
                else
                    lpData[i+(_row-j-1)*_col]=(range2.z)/_max.z*255;
            }
            else
                lpData[i+(_row-j-1)*_col]=0;
        }

        //转成影像
        CvSize _size;
        _size.width=_col;
        _size.height=_row;
        IplImage* img = cvCreateImage( _size, IPL_DEPTH_8U, 1 ); 
        img->imageData = lpData; //Arr为二维数组名

        //文件保存
        cvSaveImage( str, img );//显示图像
        delete[]lpData;
        delete[]childs;
        return img;
}

高程差影像的结果就是这样子的哈,你看,是不是好明显的。

点云转为图像的相关处理_第1张图片

然后呢,是对影像进行处理了,可以通过hough变换提取直线,举个栗子哈,是用的opencv里面的

std::vectorCV_HOUGH_LINE(ccPointCloud *theCloud, double gridSize,double dh)
{
    //一个是待处理的图像
    const char *str_process="D:\\Point2Img.jpg"; 
    Point2Img(theCloud, gridSize,dh,str_process);
    //一个是输出的结果图像
    const char *str_out="D:\\Point2Img_out.jpg"; 
    Point2Img(theCloud, gridSize,0,str_out);

    cv::Mat image_process = cv::imread(str_process);
    cv::Mat image_out = cv::imread(str_out);
    cv::Mat contours;
    cv::cvtColor(image_process, contours, cv::COLOR_BGR2GRAY);
    cv::bitwise_not(contours, contours);

    cv::Canny(image_process, contours, 100, 200);

    cv::namedWindow("Canny");
    cv::imshow("Canny",contours);

    LineFinder finder;
    // Set probabilistic Hough parameters
    finder.setLineLengthAndGap(100/gridSize, 50/gridSize);//(100, 50)
    finder.setMinVote(100/gridSize);
    // Detect lines and draw them
    std::vector lines = finder.findLines(contours);
    finder.drawDetectedLines(image_process, cv::Scalar(0, 0, 255));

    //UVLines (image_process);

    cv::namedWindow("Detected Lines with HoughP of image process");
    cv::imshow("Detected Lines with HoughP of image process",image_process);

    std::vector lines_merge=finder.GetLineEquation(image_out, cv::Scalar(0, 255, 0));
    cv::namedWindow("Detected Lines with HoughP of image out");
    cv::imshow("Detected Lines with HoughP of image out",image_out);

    imwrite("D:\\HoughLIneImg.jpg",image_out);//image_out
    return lines_merge;//lines_merge 
}

运行结果:

点云转为图像的相关处理_第2张图片

这个就比较简单了哈

应该后面应该不会再去做电力线相关的研究了,所以一些非核心的代码可以放出来,但是一些比较重要的代码还是要有知识产权意识的,欢迎大家多交流哈,反正我已经从一个坑跳进了另一个坑了

有人问get什么什么box函数,贴在下面

void getBBofCCVector3list(QVector *pts, CCVector3 *left_down, CCVector3 *right_up)
{
    if (pts->size()< 0) return;
    left_down->x = right_up->x = pts->front().x;
    left_down->y = right_up->y = pts->front().y;
    left_down->z = right_up->z = pts->front().z;
    CCVector3 *pt_now = NULL;
    for (int i = 0; i< pts->size(); i++)
    {
        pt_now = &pts->data()[(i)];
        if (pt_now->x < left_down->x) left_down->x = pt_now->x;
        if (pt_now->y < left_down->y) left_down->y = pt_now->y;
        if (pt_now->z < left_down->z) left_down->z = pt_now->z;
        if (pt_now->x > right_up->x) right_up->x = pt_now->x;
        if (pt_now->y > right_up->y) right_up->y = pt_now->y;
        if (pt_now->z > right_up->z) right_up->z = pt_now->z;
    }
}

你可能感兴趣的:(点云处理,opencv,CloudCompare)