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




我尝试用立方插值将原始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
相关产品推荐
相关产品推荐

