图像处理常用算法GPU实现四:基于中值滤波的二值图像平滑

[cpp]  view plain  copy
  1. /******************************** 
  2. *  Author: rabbit729 
  3. *  E-mail: wlq_729@163.com 
  4. *  Date:   2012-10-08 
  5. *  Description: 图像的平滑 
  6. ********************************/  
  7. #include <d3dx9.h>  
  8.   
  9. //-----------------------------------------------------------------------------  
  10. // Desc: 全局变量  
  11. //-----------------------------------------------------------------------------  
  12. LPDIRECT3D9             g_pD3D                 = NULL;  //Direct3D对象  
  13. LPDIRECT3DDEVICE9       g_pd3dDevice           = NULL;  //Direct3D设备对象  
  14.   
  15. LPDIRECT3DTEXTURE9      g_pTextureScreen        = NULL; //待处理图片  
  16.   
  17. ID3DXEffect*            g_pEffect               = NULL;  //效果指针  
  18. //常量句柄  
  19. D3DXHANDLE              hTechScreen             = NULL;  //Effect句柄  
  20. D3DXHANDLE              hTexScreen              = NULL;  //纹理句柄  
  21. D3DXHANDLE              hViewPortWidthInv       = NULL;  //视口宽倒数句柄  
  22. D3DXHANDLE              hViewPortHeightInv      = NULL;  //视口高倒数句柄  
  23.   
  24. LPDIRECT3DVERTEXBUFFER9 g_pScreenSpaceQuad      = NULL;  //背板VB  
  25.   
  26. const int WIDTH  = 465;  
  27. const int HEIGHT = 669;  
  28.   
  29. #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)  
  30.   
  31. struct Vertex  
  32. {  
  33.     Vertex(){}  
  34.     Vertex(float x, float y, float z, float w)  
  35.     {  
  36.         _x = x;   _y = y;   _z = z; _w = w;  
  37.     }  
  38.   
  39.     float _x, _y, _z, _w;  
  40.   
  41.     static const DWORD FVF;  
  42. };  
  43. const DWORD Vertex::FVF = D3DFVF_XYZW;  
  44.   
  45.   
  46. //-----------------------------------------------------------------------------  
  47. // Desc: 设置世界矩阵  
  48. //-----------------------------------------------------------------------------  
  49. VOID SetWorldMatrix()  
  50. {  
  51.     //创建并设置世界矩阵  
  52.     D3DXMATRIXA16 matWorld, matRotateX, matRotateY;  
  53.     D3DXMATRIXA16 matScale;  
  54.     D3DXMatrixIdentity(&matScale);  
  55.     matScale._11 = matScale._22 = matScale._33 = 0.5f;  
  56.   
  57.     D3DXMatrixIdentity(&matWorld);  
  58.     D3DXMatrixIdentity(&matRotateX);  
  59.     D3DXMatrixIdentity(&matRotateY);  
  60.     D3DXMatrixRotationX( &matRotateX, D3DX_PI / 3.0 );  
  61.     D3DXMatrixRotationY( &matRotateY, -D3DX_PI / 8.0 );  
  62.     D3DXMatrixMultiply(&matWorld, &matRotateX, &matRotateY);  
  63.   
  64.     D3DXMatrixMultiply(&matWorld, &matScale, &matWorld);  
  65.     g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );  
  66. }  
  67.   
  68.   
  69. //-----------------------------------------------------------------------------  
  70. // Desc: 设置观察矩阵和投影矩阵  
  71. //-----------------------------------------------------------------------------  
  72. VOID SetViewAndProjMatrix()  
  73. {  
  74.     //创建并设置观察矩阵  
  75.     D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-250.0f );  
  76.     D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );  
  77.     D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );  
  78.     D3DXMATRIXA16 matView;  
  79.     D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );  
  80.     g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );  
  81.   
  82.     //创建并设置投影矩阵  
  83.     D3DXMATRIXA16 matProj;  
  84.     D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f );  
  85.     g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );  
  86. }  
  87.   
  88.   
  89. //-----------------------------------------------------------------------------  
  90. // Desc: 初始化Direct3D  
  91. //-----------------------------------------------------------------------------  
  92. HRESULT InitD3D( HWND hWnd )  
  93. {  
  94.     //创建Direct3D对象, 该对象用于创建Direct3D设备对象  
  95.     if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )  
  96.         return E_FAIL;  
  97.   
  98.     //设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象  
  99.     D3DPRESENT_PARAMETERS d3dpp;   
  100.     ZeroMemory( &d3dpp, sizeof(d3dpp) );  
  101.     d3dpp.Windowed = TRUE;  
  102.     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;  
  103.     d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;  
  104.   
  105.     //创建Direct3D设备对象  
  106.     if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,  
  107.         D3DCREATE_SOFTWARE_VERTEXPROCESSING,  
  108.         &d3dpp, &g_pd3dDevice ) ) )  
  109.     {  
  110.         return E_FAIL;  
  111.     }  
  112.   
  113.     //创建Effect  
  114.     ID3DXBuffer* errBuffer = NULL;  
  115.     if (FAILED(D3DXCreateEffectFromFile(g_pd3dDevice, L"zhognzhilvbo.fx", NULL, NULL, D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, NULL, &g_pEffect, &errBuffer)))  
  116.     {  
  117.         if (errBuffer)  
  118.         {  
  119.             char* pErr = (char*)errBuffer->GetBufferPointer();  
  120.             errBuffer->Release();  
  121.         }  
  122.         return E_FAIL;  
  123.     }  
  124.   
  125.     //获取常量句柄  
  126.     hTechScreen         = g_pEffect->GetTechniqueByName("Screen");  
  127.     hTexScreen          = g_pEffect->GetParameterByName(0, "TexScreen");  
  128.     hViewPortWidthInv   = g_pEffect->GetParameterByName(0, "viewport_inv_width");  
  129.     hViewPortHeightInv  = g_pEffect->GetParameterByName(0, "viewport_inv_height");  
  130.   
  131.     //设置环境光  
  132.     g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );  
  133.   
  134.     //设置观察矩阵和投影矩阵  
  135.     SetViewAndProjMatrix();  
  136.   
  137.     return S_OK;  
  138. }  
  139.   
  140. //-----------------------------------------------------------------------------  
  141. // Desc: 创建场景图形  
  142. //-----------------------------------------------------------------------------  
  143. HRESULT InitGeometry()  
  144. {  
  145.     // 创建屏幕板  
  146.     g_pd3dDevice->CreateVertexBuffer(  
  147.         6 * sizeof(Vertex),  
  148.         D3DUSAGE_WRITEONLY,  
  149.         Vertex::FVF,   
  150.         D3DPOOL_MANAGED,  
  151.         &g_pScreenSpaceQuad,  
  152.         0);  
  153.   
  154.     Vertex* vertices;  
  155.     g_pScreenSpaceQuad->Lock(0, 0, (void**)&vertices, 0);  
  156.   
  157.     vertices[0] = Vertex(-1.0f, 1.0f, 0.5f, 1.0f);  
  158.     vertices[1] = Vertex(1.0f,  1.0f, 0.5f, 1.0f);  
  159.     vertices[2] = Vertex( 1.0f, -1.0f, 0.5f, 1.0f);  
  160.     vertices[3] = Vertex(-1.0f, 1.0f, 0.5f, 1.0f);  
  161.     vertices[4] = Vertex( 1.0f, -1.0f, 0.5f, 1.0f);  
  162.     vertices[5] = Vertex( -1.0f, -1.0f, 0.5f, 1.0f);  
  163.   
  164.     g_pScreenSpaceQuad->Unlock();  
  165.   
  166.     //加载纹理  
  167.     HRESULT hr = D3DXCreateTextureFromFile(g_pd3dDevice, L"meinv.jpg", &g_pTextureScreen);  
  168.     if (FAILED(hr))  
  169.     {  
  170.         return E_FAIL;  
  171.     }   
  172.   
  173.     return S_OK;  
  174. }  
  175.   
  176.   
  177. //-----------------------------------------------------------------------------  
  178. // Desc: 释放创建的对象  
  179. //-----------------------------------------------------------------------------  
  180. VOID Cleanup()  
  181. {  
  182.     if (g_pScreenSpaceQuad != NULL)  
  183.     {  
  184.         g_pScreenSpaceQuad->Release();  
  185.     }  
  186.   
  187.     if (g_pTextureScreen != NULL)  
  188.     {  
  189.         g_pTextureScreen->Release();  
  190.     }  
  191.   
  192.     if (g_pEffect != NULL)  
  193.     {  
  194.         g_pEffect->Release();  
  195.     }  
  196.   
  197.     //释放Direct3D设备对象  
  198.     if( g_pd3dDevice != NULL )  
  199.         g_pd3dDevice->Release();  
  200.   
  201.     //释放Direct3D对象  
  202.     if( g_pD3D != NULL )  
  203.         g_pD3D->Release();  
  204. }  
  205.   
  206. VOID RenderScreen()  
  207. {  
  208.     //将RenderTarget作为纹理  
  209.     g_pEffect->SetTexture(hTexScreen, g_pTextureScreen);  
  210.   
  211.     float fWidthInv = 1.0f / WIDTH;  
  212.     float fHeightInv = 1.0f / HEIGHT;  
  213.     g_pEffect->SetFloat(hViewPortWidthInv, fWidthInv);  
  214.     g_pEffect->SetFloat(hViewPortHeightInv, fHeightInv);  
  215.   
  216.     g_pd3dDevice->SetStreamSource(0, g_pScreenSpaceQuad, 0, sizeof(Vertex));  
  217.     g_pd3dDevice->SetFVF(Vertex::FVF);  
  218.   
  219.     // 设置要使用的Technique  
  220.     g_pEffect->SetTechnique(hTechScreen);  
  221.   
  222.     UINT numPasses = 0;  
  223.     g_pEffect->Begin(&numPasses, 0);  
  224.   
  225.     for (int i = 0; i < numPasses; i++)  
  226.     {  
  227.         g_pEffect->BeginPass(i);  
  228.   
  229.         g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);  
  230.   
  231.         g_pEffect->EndPass();  
  232.     }  
  233.     g_pEffect->End();  
  234. }  
  235.   
  236. //-----------------------------------------------------------------------------  
  237. // Desc: 渲染场景  
  238. //-----------------------------------------------------------------------------  
  239. VOID Render()  
  240. {      
  241.     // 获取backbuffer  
  242.     LPDIRECT3DSURFACE9 pBackbuffer;  
  243.     g_pd3dDevice->GetRenderTarget(0, &pBackbuffer);  
  244.   
  245.     //开始渲染场景  
  246.     if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )  
  247.     {  
  248.         //设回backbuffer  
  249.         g_pd3dDevice->SetRenderTarget(0, pBackbuffer);  
  250.         RenderScreen();  
  251.   
  252.         //场景渲染结束  
  253.         g_pd3dDevice->EndScene();  
  254.     }  
  255.   
  256.     //在屏幕上显示场景  
  257.     g_pd3dDevice->Present( NULL, NULL, NULL, NULL );  
  258. }  
  259.   
  260.   
  261. //-----------------------------------------------------------------------------  
  262. // Desc: 窗口过程, 处理消息  
  263. //-----------------------------------------------------------------------------  
  264. LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )  
  265. {  
  266.     switch( msg )  
  267.     {  
  268.     case WM_DESTROY:  
  269.         Cleanup();  
  270.         PostQuitMessage( 0 );  
  271.         return 0;  
  272.     }  
  273.   
  274.     return DefWindowProc( hWnd, msg, wParam, lParam );  
  275. }  
  276.   
  277.   
  278. //-----------------------------------------------------------------------------  
  279. // Desc: 入口函数  
  280. //-----------------------------------------------------------------------------  
  281. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCELPSTRINT )  
  282. {  
  283.     //注册窗口类  
  284.     WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,   
  285.         GetModuleHandle(NULL), NULL, NULL, NULL, NULL,  
  286.         L"ClassName", NULL };  
  287.     RegisterClassEx( &wc );  
  288.   
  289.     //创建窗口  
  290.     HWND hWnd = CreateWindow( L"ClassName", L"图像平滑",   
  291.         WS_OVERLAPPEDWINDOW, 200, 100, WIDTH, HEIGHT,  
  292.         GetDesktopWindow(), NULL, wc.hInstance, NULL );  
  293.   
  294.     //初始化Direct3D  
  295.     if( SUCCEEDED( InitD3D( hWnd ) ) )  
  296.     {   
  297.         //创建场景图形  
  298.         if( SUCCEEDED( InitGeometry() ) )  
  299.         {  
  300.             //显示窗口  
  301.             ShowWindow( hWnd, SW_SHOWDEFAULT );  
  302.             UpdateWindow( hWnd );  
  303.   
  304.             //进入消息循环  
  305.             MSG msg;   
  306.             ZeroMemory( &msg, sizeof(msg) );  
  307.             while( msg.message!=WM_QUIT )  
  308.             {  
  309.                 if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )  
  310.                 {  
  311.                     TranslateMessage( &msg );  
  312.                     DispatchMessage( &msg );  
  313.                 }  
  314.                 else  
  315.                 {  
  316.                     Render();  //渲染场景  
  317.                 }  
  318.             }  
  319.         }  
  320.     }  
  321.   
  322.     UnregisterClass( L"ClassName", wc.hInstance );  
  323.     return 0;  
  324. }  


Effect代码:

[cpp]  view plain  copy
  1. /******************************** 
  2. *  Author: rabbit729 
  3. *  E-mail: wlq_729@163.com 
  4. *  Date:   2011-10-08 
  5. ********************************/  
  6.   
  7. //------------------------------  
  8. //  顶点着色器  
  9. //------------------------------  
  10.   
  11. float viewport_inv_width;  
  12. float viewport_inv_height;  
  13. struct VS_OUTPUTSCREEN {  
  14.    float4 Pos: POSITION;  
  15.    float2 texCoord: TEXCOORD0;  
  16. };  
  17.   
  18. VS_OUTPUTSCREEN vs_mainPassScreen(float4 Pos: POSITION){  
  19.    VS_OUTPUTSCREEN Out;  
  20.   
  21.    Out.Pos = float4(Pos.xy, 0, 1);  
  22.   
  23.    Out.texCoord.x = 0.5 * (1 + Pos.x - viewport_inv_width);  
  24.    Out.texCoord.y = 0.5 * (1 - Pos.y - viewport_inv_height);  
  25.   
  26.    return Out;  
  27. }  
  28.   
  29. //------------------------------  
  30. //  像素着色器  
  31. //------------------------------  
  32.   
  33. Texture2D TexScreen;  
  34.   
  35. sampler2D TexMapScreen {  
  36.     Texture = <TexScreen>;  
  37. };  
  38.   
  39. const float4 samples[9] = {  
  40.   -1.0, -1.0, 0.0, 1.0,  
  41.   0.0, -1.0, 0.0, 1.0,  
  42.   1.0, 1.0, 0.0, 1.0,  
  43.   -1.0, 0.0, 0.0, 1.0,  
  44.   0.0, 0.0, 0.0, 1.0,  
  45.   1.0, 0.0, 0.0, 1.0,  
  46.   -1.0, 1.0, 0.0, 1.0,  
  47.   0.0, 1.0, 0.0, 1.0,  
  48.   1.0, 1.0, 0.0, 1.0  
  49. };  
  50.   
  51. float4 ps_mainPassScreen(float2 texCoord: TEXCOORD0) : COLOR   
  52. {  
  53.    //return float4(Intensity.xxx,col.a);  
  54.    float4 col = float4(0, 0, 0, 0);  
  55.      
  56.    float fArr[9];  
  57.    for(int i = 0; i < 9; i++)  
  58.    {  
  59.      fArr[i] = tex2D(TexMapScreen, texCoord + float2(samples[i].x*viewport_inv_width, samples[i].y*viewport_inv_height));  
  60.    }  
  61.      
  62.    //冒泡排序  
  63.    for(int j = 0; j < 8; j++)  
  64.    {  
  65.         for(int k = 0; k < 9 - j - 1; k++)  
  66.         {  
  67.           if(fArr[k] > fArr[k + 1])  
  68.           {  
  69.             float fTemp;  
  70.             fTemp = fArr[k];  
  71.             fArr[k] = fArr[k + 1];  
  72.             fArr[k + 1] = fTemp;  
  73.           }  
  74.         }  
  75.    }  
  76.      
  77.    return fArr[4];  
  78. }  
  79.   
  80. //------------------------------  
  81. //  效果框架  
  82. //------------------------------  
  83.   
  84. technique Screen  
  85. {  
  86.    pass P0  
  87.    {  
  88.       VertexShader = compile vs_3_0 vs_mainPassScreen();  
  89.       PixelShader  = compile ps_3_0 ps_mainPassScreen();  
  90.    }  
  91. }  


结果:

原图:

平滑后结果:

0
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: pcl::MedianFilter是点云库PCL中的一个中值滤波类,用于对点云进行去噪处理。中值滤波是一种非线性滤波方法,它的核心思想是将像素值替换为该像素周围像素的中值,从而去除图像中的噪声。 在点云中,中值滤波的原理与图像中的类似,即对每个点的邻域内的点进行排序,并将中间值作为该点的新值。在PCL的MedianFilter中,可以通过设置邻域的大小和是否考虑点的法向量等参数来控制滤波的效果。 以下是一个简单的使用例子: ```cpp #include <iostream> #include <pcl/point_types.h> #include <pcl/filters/median_filter.h> int main() { // 生成一个简单的点云 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); cloud->width = 5; cloud->height = 1; cloud->points.resize(cloud->width * cloud->height); for (size_t i = 0; i < cloud->points.size(); ++i) { cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f); cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f); } // 创建滤波器 pcl::MedianFilter<pcl::PointXYZ> median_filter; median_filter.setInputCloud(cloud); median_filter.setWindowSize(3); // 执行滤波 pcl::PointCloud<pcl::PointXYZ>::Ptr filtered_cloud(new pcl::PointCloud<pcl::PointXYZ>); median_filter.filter(*filtered_cloud); // 输出结果 std::cout << "Cloud before filtering: " << std::endl; for (const auto& point : *cloud) std::cout << " " << point.x << " " << point.y << " " << point.z << std::endl; std::cout << "Cloud after filtering: " << std::endl; for (const auto& point : *filtered_cloud) std::cout << " " << point.x << " " << point.y << " " << point.z << std::endl; return 0; } ``` 在上述例子中,我们创建了一个5个点的点云,并使用MedianFilter对其进行中值滤波,邻域大小为3。最后输出原始点云和滤波后的点云的结果。 ### 回答2: pcl::MedianFilter中值滤波是一种常用的滤波方法,用于去除图像或点云中的噪声。 中值滤波的原理是基于中值统计的思想,即在一个窗口范围内,将窗口内的所有像素点或点云数据进行排序,取中间值作为滤波后的像素点或点云数据。 对于二维图像,中值滤波可用于去除图像中的椒盐噪声或其他类型的噪声。在窗口范围内对像素点进行排序后,将中间的像素值作为滤波后的像素值,可以有效地减少噪声对图像的影响。 对于三维点云数据,中值滤波同样适用于去除点云数据中的离群点噪声。在窗口范围内对点云数据进行排序后,取中间的点云数据作为滤波后的数据,可以将离群点的影响降到最小。 pcl::MedianFilter中值滤波的使用非常简单,只需指定窗口的大小和椒盐噪声或离群点噪声的阈值即可。窗口大小决定了滤波的范围,阈值确定了噪声的最大值或最小值。 需要注意的是,中值滤波可能会导致图像或点云数据的平滑效果,因此在应用中需要根据实际需求来选择合适的窗口大小和阈值。 总而言之,pcl::MedianFilter中值滤波是一种常用的滤波方法,适用于去除图像或点云中的噪声,具有简单易用、可调节参数等特点。使用该滤波方法可以有效提高图像或点云数据的质量。 ### 回答3: pcl::MedianFilter中值滤波是一种常用的数字图像处理方法,其目的是通过将像素点周围的像素值进行排序并选择中间值,来消除图像中的噪声或异常点。 在pcl库中,使用MedianFilter类可以实现中值滤波中值滤波主要包括以下几个步骤: 1. 遍历图像中的每一个像素点。 2. 对当前像素点周围的邻域进行窗口操作,将窗口内的像素值排序。 3. 选择排序后中间位置的像素值作为当前像素点的新值。 4. 重复步骤2和步骤3,直到遍历完整个图像。 中值滤波的原理是基于噪声的统计特征,认为噪声通常会使得像素值发生较大偏差,而图像本身的特征通常是平滑变化的。通过将邻域内的像素值重新排序,并选择其中的中间值来取代原始像素值,可以有效抑制噪声的影响,同时保留图像的细节和边缘特征。 需要注意的是,中值滤波对于图像中的稀疏噪声和脉冲噪声有较好的抑制效果,但对于高斯噪声和平均噪声的处理效果相对较差。此外,中值滤波在处理较大噪声时可能会产生平滑效果过强的问题,因此在实际应用中需要根据具体情况选择合适的窗口大小。 总之,pcl::MedianFilter中值滤波是一种简单但常用图像处理方法,可以有效地去除图像中的噪声,提高图像质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值