图像处理常用算法GPU实现一:图像二值化

来源:互联网 发布:淘宝的优惠券怎么用啊 编辑:程序博客网 时间:2024/05/26 22:09

本系列文章将使用GPU实现图像处理中常用的算法,此处只给出代码,关于算法原理描述有很多资料,大家可以自行查找。不足之处请大家不吝赐教,共同提高。

[cpp] view plain copy
  1. /******************************** 
  2. *  Author: rabbit729 
  3. *  E-mail: wlq_729@163.com 
  4. *  Date:   2012-09-20 
  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"erzhihua.fx", NULL, NULL, D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, NULL, &g_pEffect, &errBuffer)))  
  116.     {  
  117.         if (errBuffer)  
  118.         {  
  119.             MessageBox(0, (LPCTSTR)errBuffer->GetBufferPointer(), 0, 0);  
  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-09-20 
  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. Texture2D TexScreen;  
  33.   
  34. sampler2D TexMapScreen {  
  35.     Texture = <TexScreen>;  
  36. };  
  37.   
  38. float4 ps_mainPassScreen(float2 texCoord: TEXCOORD0) : COLOR   
  39. {  
  40.    float4 col = tex2D(TexMapScreen,  texCoord);  
  41.    float Intensity;  
  42.   
  43.    // 灰度化  
  44.    // I = 0.299*R + 0.587*G + 0.184*B  
  45.    Intensity = 0.299*col.r + 0.587*col.g + 0.184*col.r;  
  46.      
  47.    // 阈值为0.5,关于怎么选取阈值有好多方法,大家可以自行查阅  
  48.    if(Intensity > 0.5)  
  49.       Intensity = 0.5f;  
  50.    else  
  51.       Intensity = 0.1f;  
  52.   
  53.    return float4(Intensity.xxx,col.a);  
  54. }  
  55.   
  56. technique Screen  
  57. {  
  58.    pass P0  
  59.    {  
  60.       VertexShader = compile vs_3_0 vs_mainPassScreen();  
  61.       PixelShader  = compile ps_3_0 ps_mainPassScreen();  
  62.    }  
  63. }  


 结果:

原始图片:

二值化后结果: