C++ 如何为点云提供纹理?
我有一个使用OpenCV获得的视差图像。我能够使用OpenGL和CUDA显示一个640 x 360的点网格,并给每个点一个对应于视差值的Z值。结果是: 现在,我希望给点云中的每个点一个颜色值,对应于立体相机左图像中具有相同大小(640 x 380)的像素 这是我的CUDA内核和调用函数,其中我有两个图像、视差和包含颜色信息的左侧图像(灰度):C++ 如何为点云提供纹理?,c++,opencv,opengl,cuda,C++,Opencv,Opengl,Cuda,我有一个使用OpenCV获得的视差图像。我能够使用OpenGL和CUDA显示一个640 x 360的点网格,并给每个点一个对应于视差值的Z值。结果是: 现在,我希望给点云中的每个点一个颜色值,对应于立体相机左图像中具有相同大小(640 x 380)的像素 这是我的CUDA内核和调用函数,其中我有两个图像、视差和包含颜色信息的左侧图像(灰度): __global__ void simple_vbo_kernel(float4 *pos, unsigned int width, unsigned
__global__ void simple_vbo_kernel(float4 *pos, unsigned int width, unsigned int height, float time,
uchar* disp, int stepDisp)
{
const int x = threadIdx.x + blockIdx.x * blockDim.x;
const int y = threadIdx.y + blockIdx.y * blockDim.y;
if ((x < width) && (y < height))
{
float u = x / (float) width;
float v = y / (float) height;
u = u*2.0f - 1.0f;
v = v*2.0f - 1.0f;
const int depth = y * stepDisp + x;
float w = static_cast<float>(disp[depth]);
w/=10;
pos[y*width+x] = make_float4(u, w, v, 1.0f);
}
}
extern "C"
void launch_kernel(dim3 grid, dim3 block, float4 *pos, unsigned int mesh_width,unsigned int mesh_height,
float time, cv::Mat disp, cv::Mat left)
{
if(!disp.empty() && !left.empty()){
uchar* d_image;
int dsize = disp.rows * disp.step;
cudaMalloc((void**)&d_image, dsize);
cudaMemcpy(d_image, disp.ptr(), dsize, cudaMemcpyHostToDevice);
simple_vbo_kernel<<< grid, block>>>(pos, mesh_width, mesh_height, time, d_image, disp.step);
cudaDeviceSynchronize();
cudaFree(d_image);
}
}
\uuuuu全局\uuuuuu无效简单vbo\u内核(float4*pos、无符号整数宽度、无符号整数高度、浮点时间、,
uchar*disp,int-stepDisp)
{
const int x=threadIdx.x+blockIdx.x*blockDim.x;
const int y=threadIdx.y+blockIdx.y*blockDim.y;
如果((x<宽度)和(y<高度))
{
浮动u=x/(浮动)宽度;
浮动v=y/(浮动)高度;
u=u*2.0f-1.0f;
v=v*2.0f-1.0f;
常量int深度=y*stepDisp+x;
浮动w=静态施法(显示[深度]);
w/=10;
位置[y*宽度+x]=使浮点数为4(u、w、v、1.0f);
}
}
外部“C”
无效启动内核(dim3网格、dim3块、浮点4*pos、无符号整数网格宽度、无符号整数网格高度、,
浮动时间,cv::Mat disp,cv::Mat left)
{
如果(!disp.empty()&&!left.empty()){
uchar*d_图像;
int dsize=disp.rows*disp.step;
Cudamaloc((空白**)和d_图像,dsize);
cudaMemcpy(d_image,disp.ptr(),dsize,cudamemcpyhostodevice);
简单vbo内核>(位置、网格宽度、网格高度、时间、d_图像、显示步长);
cudaDeviceSynchronize();
cudaFree(d_图像);
}
}
我的问题是,在本例中,使用
cv::Mat left
为点云中的点提供纹理或颜色的最简单方法是什么?我在CUDA示例中看到了一些其他示例,但我没有找到如何执行此操作。对于稀疏点云(如您的点云),通常最好的做法是向顶点添加颜色属性,并为其指定所需的颜色。使图形着色器将该属性的值传递给发射的片段颜色。我找到了一个解决方案。在内核部分中,我为颜色提供了一个新的uchar4映射输入,两个输入指针的大小必须相同,才能在点和颜色之间建立正确的关系(float4*pos和uchar4*color)。由于d_图像是灰度图像(视差图像),而提供纹理的图像是彩色图像,因此在访问每个阵列时应考虑这一点。Opencv按BGR顺序排列,gstreamer按RGB排列:
__global__ void simple_vbo_kernel(float4 *pos, uchar4 *color, unsigned int width, unsigned int height, uchar* d_image, int stepDisp, uchar* d_color, int stepLeft)
{
const int x = threadIdx.x + blockIdx.x * blockDim.x;
const int y = threadIdx.y + blockIdx.y * blockDim.y;
if ((x < width) && (y < height)){
float u = x / (float) width;
float v = y / (float) height;
u = u*2.0f - 1.0f;
v = v*2.0f - 1.0f;
const int depthi = y * stepDisp + x;
float w = static_cast<float>(d_image[depthi]);
w/=25;
pos[y*width+x] = make_float4(u, w, v, 1.0f);
uchar b = static_cast<uchar>(d_color[y*width*3+x*3 + 0]);
uchar g = static_cast<uchar>(d_color[y*width*3+x*3 + 1]);
uchar r = static_cast<uchar>(d_color[y*width*3+x*3 + 2]);
color[y*width+x] = make_uchar4( r, g, b, 1.0f);
}
}
extern "C"
void launch_kernel(dim3 grid, dim3 block, unsigned int mesh_width, unsigned int mesh_height, float4 *pos, cv::Mat disp, uchar4 *color, cv::Mat left)
{
if(!disp.empty() && !left.empty()){
uchar* d_image;
int dsize = disp.rows * disp.step;
cudaMalloc((void**)&d_image, dsize);
cudaMemcpy(d_image, disp.ptr(), dsize, cudaMemcpyHostToDevice);
uchar* d_color;
int dcolorsize = left.rows * left.step;
cudaMalloc((void**)&d_color, dcolorsize);
cudaMemcpy(d_color, left.ptr(), dcolorsize, cudaMemcpyHostToDevice);
simple_vbo_kernel<<< grid, block>>>(pos, color, mesh_width, mesh_height, d_image, disp.step, d_color, left.step);
cudaDeviceSynchronize();
cudaFree(d_image);
cudaFree(d_color);
}
}
在OpenGl的初始化过程中,添加以下内容也很重要:
glEnable( GL_TEXTURE_2D );
并启用深度测试。我以前禁用过,我有奇怪的图像重叠:
glEnable(GL_DEPTH_TEST);
以及必须显示或更新图像的部分,在我的例子中,我在我的glutDisplayFunc(display)
函数中有它:
glBindBuffer(GL_ARRAY_BUFFER, pos_vbo);
glVertexPointer(4, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, color_vbo);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
glPointSize(3.0);
glDrawArrays(GL_POINTS, 0, mesh_width * mesh_height);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glutSwapBuffers();
glFlush();
glDeleteTextures(1, &color_vbo);
我的图像是灰度图像,因为我仍在尝试用gstreamer 0.10的颜色捕获我的rtsp流
我打开了一个新帖子,试图解决颜色问题:
…或者等待具有编辑权限的人插入内嵌图片。由于每个点对应一个像素,似乎不需要为其指定纹理,但您希望为其指定一种颜色(对应像素)?!?atm您渲染每个点为绿色我使用此函数渲染每个点为绿色:glColor3f(0.0,1.0,0.0);只需使用绿色而不是默认的白色。但我的目的是给三维图像的每个像素提供灰度图像或彩色图像的颜色信息,因为二维图像中的两个图像具有相同的像素大小。应该是这样的。我知道如何在内核中访问我的左Mat图像中的颜色信息(与我对视差Mat图像所做的非常类似),但我仍然不知道如何向像素添加额外的颜色属性。如果你能举个例子,我将不胜感激。根据你的建议,我正在寻找一些好的教程,我将尝试解决方案。非常感谢。
glBindBuffer(GL_ARRAY_BUFFER, pos_vbo);
glVertexPointer(4, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, color_vbo);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
glPointSize(3.0);
glDrawArrays(GL_POINTS, 0, mesh_width * mesh_height);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glutSwapBuffers();
glFlush();
glDeleteTextures(1, &color_vbo);