You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

3D医学超声体绘制中栅栏状伪影问题求助

3D医学超声体绘制栅栏状伪影问题求助

我基于Nvidia GPU Gems中的3D超声实时着色示例代码,实现了3D人体心脏超声数据集的体绘制。代码能正常运行,渲染结果可反映原始3D数据集的结构,但存在明显的栅栏状伪影(fence-like artifact),伪影程度随视角变化——第一张图伪影最显著,第四张图相对轻微:

心脏超声体绘制视角1
心脏超声体绘制视角2
心脏超声体绘制视角3
心脏超声体绘制视角4

我尝试用立方插值将原始3D数据集放大2倍(例如从100x100x100放大至200x200x200),但这种方法对消除栅栏状伪影没有帮助。

该实现采用OpenGL + Cg(C for graphics)完成,以下是部分核心代码。我对OpenGL和Cg技术栈不熟悉,恳请相关领域人士提供解决建议,感谢!


核心代码

主函数

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(640, 480);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    
    if (glutExtensionSupported("GL_EXT_texture3D")) {
        cerr << "GL_EXT_texture3D supported!" << endl;
        glTexImage3DEXT    = (PFNGLTEXIMAGE3DEXTPROC)wglGetProcAddress("glTexImage3DEXT");
        glTexSubImage3DEXT = (PFNGLTEXSUBIMAGE3DEXTPROC)wglGetProcAddress("glTexSubImage3DEXT");
    }
    else {
        cerr << "GL_EXT_texture3D unsupported!" << endl;
        exit(0);
    }
    
    Init();
    glutDisplayFunc(Display);
    glutReshapeFunc(Reshape);
    glutIdleFunc(Idle);
    glutKeyboardFunc (Keyboard);
    
    InitializeGPU();
    
    glutMainLoop();
    
    QuitGPU();

    return 0; 
}

初始化函数

void Init(void)
{    
   //ReadVolumes("../Data/US/", "Baby.lst");
   //ReadVolumes("../Data/US/GPU_Gem_Cardiac_lbbb_rotate/", "Cardiac.lst");
   ReadVolumes(Volume_path,list_name);
   InitColorMap();

   glClearColor (0.0, 0.0, 0.0, 0.0);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

   // Generate the 1D ColorMap
   glGenTextures(1, &GL_ColorMap);
   glBindTexture(GL_TEXTURE_1D, GL_ColorMap);
   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, ColorMapLength, 0, GL_RGBA, GL_UNSIGNED_BYTE, ColorMapArray);

   // Generate the ultrasound texture
   glGenTextures(1, &GL_USTexture);
   glBindTexture(GL_TEXTURE_3D, GL_USTexture);
   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexImage3DEXT(GL_TEXTURE_3D, 0, GL_RGBA, iWidth, iHeight, iDepth, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);

   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
   glEnable(GL_BLEND);
   
   // Enable clip planes
   glEnable(GL_CLIP_PLANE0);
   glEnable(GL_CLIP_PLANE1);

   glEnable(GL_CLIP_PLANE2);
   glEnable(GL_CLIP_PLANE3);

   glEnable(GL_CLIP_PLANE4);
   glEnable(GL_CLIP_PLANE5);

   SetDisplayList();
}

GPU初始化函数

void InitializeGPU(void)
{
    // Create Cg Context
    Context = cgCreateContext();
    CheckCgError();

    InitializeVertexProgram();
    cgGLEnableProfile(vProfile);
    CheckCgError();
    cgGLBindProgram(vProgram);
    CheckCgError();


    char Source_p = 1;
    // To load the Cg source code, comment out the following line.
    //Source_p = 0;
    InitializeFragmentProgram(Source_p);
    cgGLEnableProfile(fProfile);
    CheckCgError();
    cgGLBindProgram(fProgram);
    CheckCgError();
    cgGLEnableTextureParameter(ColorMap);
    CheckCgError();
    cgGLEnableTextureParameter(USTexture);
    CheckCgError();
}

Cg顶点着色器

void VertexProgram(in float4 Position   : POSITION,
                   out float4 hPosition : POSITION,
                   out float4 hTex0     : TEX0,
                   out float hClip0     : CLP0,
                   out float hClip1     : CLP1,
                   out float hClip2     : CLP2,
                   out float hClip3     : CLP3,
                   out float hClip4     : CLP4,
                   out float hClip5     : CLP5,
                   uniform float4 ZoomFactor,
                   uniform float4 Pyramid,
                   uniform float4 ClipPlane0,
                   uniform float4 ClipPlane1,
                   uniform float4 ClipPlane2,
                   uniform float4 ClipPlane3,
                   uniform float4 ClipPlane4,
                   uniform float4 ClipPlane5,
                   uniform float4x4 ModelView,
                   uniform float4x4 ModelViewProj)
{
  // Compute the clip-space position
  hPosition = mul(ModelViewProj, Position);

  // Remove the zoom factor from the position coordinates
  Position  = Position * ZoomFactor;

  // Compute the texture coordinates using the Cartesian grid
  hTex0     = mul(ModelView, Position);

  // Save original texture coordinates
  float4 hTex0_Orig = hTex0 - float4(0.5, 0.5, 0.0, 0.0);

  // Compute the scale for the texture coordinates in the
  // pyramidal grid
  hTex0.w   = Pyramid.x + hTex0.z*Pyramid.y;

  // Adjust for the texture coordinate offsets
  hTex0.x   = hTex0.x - 0.5 + 0.5*hTex0.w;

  // Clip pyramidal volume
  hClip0    =  dot(hTex0_Orig, ClipPlane0);
  hClip1    =  dot(hTex0_Orig, ClipPlane1);
  hClip2    =  dot(hTex0_Orig, ClipPlane2);
  hClip3    =  dot(hTex0_Orig, ClipPlane3);
  hClip4    =  dot(hTex0_Orig, ClipPlane4);
  hClip5    =  dot(hTex0_Orig, ClipPlane5);
}

Cg片段着色器

void FragmentProgram(in float4 inTex : TEXCOORD0,
                     out float4 sColor0 : COLOR0,
                     const uniform sampler3D USTexture,
                     const uniform sampler1D ColorMap)
{
  // Pre-multiply 'r' coordinate with the scale
  inTex.yz = inTex.yz * inTex.ww;

  // Projective 3D texture lookup
  float val = tex3Dproj(USTexture, inTex.yzxw);

  // Colormap look up
  sColor0 = tex1D(ColorMap, val);
  
}

内容的提问来源于stack exchange,提问作者Nate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:32:04