读书人

图像处理惯用算法GPU实现四:基于中值

发布时间: 2012-10-16 09:57:37 作者: rapoo

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

/*********************************  Author: rabbit729*  E-mail: wlq_729@163.com*  Date:   2012-10-08*  Description: 图像的平滑********************************/#include <d3dx9.h>//-----------------------------------------// Desc: 全局变量//-----------------------------------------LPDIRECT3D9             g_pD3D                 = NULL;  //Direct3D对象LPDIRECT3DDEVICE9       g_pd3dDevice           = NULL;  //Direct3D设备对象LPDIRECT3DTEXTURE9      g_pTextureScreen        = NULL; //待处理图片ID3DXEffect*            g_pEffect               = NULL;  //效果指针//常量句柄D3DXHANDLE              hTechScreen             = NULL;  //Effect句柄D3DXHANDLE              hTexScreen              = NULL;  //纹理句柄D3DXHANDLE              hViewPortWidthInv       = NULL;  //视口宽倒数句柄D3DXHANDLE              hViewPortHeightInv      = NULL;  //视口高倒数句柄LPDIRECT3DVERTEXBUFFER9 g_pScreenSpaceQuad      = NULL;  //背板VBconst int WIDTH  = 465;const int HEIGHT = 669;#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)struct Vertex{Vertex(){}Vertex(float x, float y, float z, float w){_x = x;   _y = y;   _z = z; _w = w;}float _x, _y, _z, _w;static const DWORD FVF;};const DWORD Vertex::FVF = D3DFVF_XYZW;//-----------------------------------------// Desc: 设置世界矩阵//-----------------------------------------VOID SetWorldMatrix(){//创建并设置世界矩阵D3DXMATRIXA16 matWorld, matRotateX, matRotateY;D3DXMATRIXA16 matScale;D3DXMatrixIdentity(&matScale);matScale._11 = matScale._22 = matScale._33 = 0.5f;D3DXMatrixIdentity(&matWorld);D3DXMatrixIdentity(&matRotateX);D3DXMatrixIdentity(&matRotateY);D3DXMatrixRotationX( &matRotateX, D3DX_PI / 3.0 );D3DXMatrixRotationY( &matRotateY, -D3DX_PI / 8.0 );D3DXMatrixMultiply(&matWorld, &matRotateX, &matRotateY);D3DXMatrixMultiply(&matWorld, &matScale, &matWorld);g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );}//-----------------------------------------// Desc: 设置观察矩阵和投影矩阵//-----------------------------------------VOID SetViewAndProjMatrix(){//创建并设置观察矩阵D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-250.0f );D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );D3DXMATRIXA16 matView;D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );//创建并设置投影矩阵D3DXMATRIXA16 matProj;D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f );g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );}//-----------------------------------------// Desc: 初始化Direct3D//-----------------------------------------HRESULT InitD3D( HWND hWnd ){//创—irect3D对象, 该对象用于创—irect3D设备对象if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )return E_FAIL;//设置D3DPRESENT_PARAMETERS结构, 准备创—irect3D设备对象D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) );d3dpp.Windowed = TRUE;d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;//创—irect3D设备对象if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp, &g_pd3dDevice ) ) ){return E_FAIL;}//创建EffectID3DXBuffer* errBuffer = NULL;if (FAILED(D3DXCreateEffectFromFile(g_pd3dDevice, L"zhognzhilvbo.fx", NULL, NULL, D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, NULL, &g_pEffect, &errBuffer))){if (errBuffer){char* pErr = (char*)errBuffer->GetBufferPointer();errBuffer->Release();}return E_FAIL;}//获取常量句柄hTechScreen         = g_pEffect->GetTechniqueByName("Screen");hTexScreen          = g_pEffect->GetParameterByName(0, "TexScreen");hViewPortWidthInv   = g_pEffect->GetParameterByName(0, "viewport_inv_width");hViewPortHeightInv  = g_pEffect->GetParameterByName(0, "viewport_inv_height");//设置环境光g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );//设置观察矩阵和投影矩阵SetViewAndProjMatrix();return S_OK;}//-----------------------------------------// Desc: 创建场景图形//-----------------------------------------HRESULT InitGeometry(){// 创建屏幕板g_pd3dDevice->CreateVertexBuffer(6 * sizeof(Vertex),D3DUSAGE_WRITEONLY,Vertex::FVF, D3DPOOL_MANAGED,&g_pScreenSpaceQuad,0);Vertex* vertices;g_pScreenSpaceQuad->Lock(0, 0, (void**)&vertices, 0);vertices[0] = Vertex(-1.0f, 1.0f, 0.5f, 1.0f);vertices[1] = Vertex(1.0f,  1.0f, 0.5f, 1.0f);vertices[2] = Vertex( 1.0f, -1.0f, 0.5f, 1.0f);vertices[3] = Vertex(-1.0f, 1.0f, 0.5f, 1.0f);vertices[4] = Vertex( 1.0f, -1.0f, 0.5f, 1.0f);vertices[5] = Vertex( -1.0f, -1.0f, 0.5f, 1.0f);g_pScreenSpaceQuad->Unlock();//加载纹理HRESULT hr = D3DXCreateTextureFromFile(g_pd3dDevice, L"meinv.jpg", &g_pTextureScreen);if (FAILED(hr)){return E_FAIL;} return S_OK;}//-----------------------------------------// Desc: 释放创建的对象//-----------------------------------------VOID Cleanup(){if (g_pScreenSpaceQuad != NULL){g_pScreenSpaceQuad->Release();}if (g_pTextureScreen != NULL){g_pTextureScreen->Release();}if (g_pEffect != NULL){g_pEffect->Release();}//释放Direct3D设备对象if( g_pd3dDevice != NULL )g_pd3dDevice->Release();//释放Direct3D对象if( g_pD3D != NULL )g_pD3D->Release();}VOID RenderScreen(){//将RenderTarget作为纹理g_pEffect->SetTexture(hTexScreen, g_pTextureScreen);float fWidthInv = 1.0f / WIDTH;float fHeightInv = 1.0f / HEIGHT;g_pEffect->SetFloat(hViewPortWidthInv, fWidthInv);g_pEffect->SetFloat(hViewPortHeightInv, fHeightInv);g_pd3dDevice->SetStreamSource(0, g_pScreenSpaceQuad, 0, sizeof(Vertex));g_pd3dDevice->SetFVF(Vertex::FVF);// 设置要使用的Techniqueg_pEffect->SetTechnique(hTechScreen);UINT numPasses = 0;g_pEffect->Begin(&numPasses, 0);for (int i = 0; i < numPasses; i++){g_pEffect->BeginPass(i);g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);g_pEffect->EndPass();}g_pEffect->End();}//-----------------------------------------// Desc: 渲染场景//-----------------------------------------VOID Render(){    // 获取backbufferLPDIRECT3DSURFACE9 pBackbuffer;g_pd3dDevice->GetRenderTarget(0, &pBackbuffer);//开始渲染场景if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ){//设回backbufferg_pd3dDevice->SetRenderTarget(0, pBackbuffer);RenderScreen();//场景渲染结束g_pd3dDevice->EndScene();}//在屏幕上显示场景g_pd3dDevice->Present( NULL, NULL, NULL, NULL );}//-----------------------------------------// Desc: 窗口过程, 处理消息//-----------------------------------------LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){switch( msg ){case WM_DESTROY:Cleanup();PostQuitMessage( 0 );return 0;}return DefWindowProc( hWnd, msg, wParam, lParam );}//-----------------------------------------// Desc: 入口函数//-----------------------------------------INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ){//注册窗口类WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL,L"ClassName", NULL };RegisterClassEx( &wc );//创建窗口HWND hWnd = CreateWindow( L"ClassName", L"图像平滑", WS_OVERLAPPEDWINDOW, 200, 100, WIDTH, HEIGHT,GetDesktopWindow(), NULL, wc.hInstance, NULL );//初始化Direct3Dif( SUCCEEDED( InitD3D( hWnd ) ) ){ //创建场景图形if( SUCCEEDED( InitGeometry() ) ){//显示窗口ShowWindow( hWnd, SW_SHOWDEFAULT );UpdateWindow( hWnd );//进入消息循环MSG msg; ZeroMemory( &msg, sizeof(msg) );while( msg.message!=WM_QUIT ){if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){TranslateMessage( &msg );DispatchMessage( &msg );}else{Render();  //渲染场景}}}}UnregisterClass( L"ClassName", wc.hInstance );return 0;}


Effect代码:

/*********************************  Author: rabbit729*  E-mail: wlq_729@163.com*  Date:   2011-10-08********************************///------------------------------//  顶点着色器//------------------------------float viewport_inv_width;float viewport_inv_height;struct VS_OUTPUTSCREEN {   float4 Pos: POSITION;   float2 texCoord: TEXCOORD0;};VS_OUTPUTSCREEN vs_mainPassScreen(float4 Pos: POSITION){   VS_OUTPUTSCREEN Out;   Out.Pos = float4(Pos.xy, 0, 1);   Out.texCoord.x = 0.5 * (1 + Pos.x - viewport_inv_width);   Out.texCoord.y = 0.5 * (1 - Pos.y - viewport_inv_height);   return Out;}//------------------------------//  像素着色器//------------------------------Texture2D TexScreen;sampler2D TexMapScreen {    Texture = <TexScreen>;};const float4 samples[9] = {  -1.0, -1.0, 0.0, 1.0,  0.0, -1.0, 0.0, 1.0,  1.0, 1.0, 0.0, 1.0,  -1.0, 0.0, 0.0, 1.0,  0.0, 0.0, 0.0, 1.0,  1.0, 0.0, 0.0, 1.0,  -1.0, 1.0, 0.0, 1.0,  0.0, 1.0, 0.0, 1.0,  1.0, 1.0, 0.0, 1.0};float4 ps_mainPassScreen(float2 texCoord: TEXCOORD0) : COLOR {   //return float4(Intensity.xxx,col.a);   float4 col = float4(0, 0, 0, 0);      float fArr[9];   for(int i = 0; i < 9; i++)   { fArr[i] = tex2D(TexMapScreen, texCoord + float2(samples[i].x*viewport_inv_width, samples[i].y*viewport_inv_height));   }      //冒泡排序   for(int j = 0; j < 8; j++)   {for(int k = 0; k < 9 - j - 1; k++){  if(fArr[k] > fArr[k + 1])  {    float fTemp;fTemp = fArr[k];fArr[k] = fArr[k + 1];fArr[k + 1] = fTemp;  }}   }      return fArr[4];}//------------------------------//  效果框架//------------------------------technique Screen{   pass P0   {      VertexShader = compile vs_3_0 vs_mainPassScreen();      PixelShader  = compile ps_3_0 ps_mainPassScreen();   }}


结果:

原图:

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

平滑后结果:

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

读书人网 >图形图像

热点推荐