- /********************************
- * Author: rabbit729
- * E-mail: [email protected]
- * Date: 2012-09-23
- * 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; //背板VB
- const 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 )
- {
- //創建Direct3D對象, 該對象用於創建Direct3D設備對象
- if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
- return E_FAIL;
- //設置D3DPRESENT_PARAMETERS結構, 準備創建Direct3D設備對象
- D3DPRESENT_PARAMETERS d3dpp;
- ZeroMemory( &d3dpp, sizeof(d3dpp) );
- d3dpp.Windowed = TRUE;
- d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
- //創建Direct3D設備對象
- if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
- D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- &d3dpp, &g_pd3dDevice ) ) )
- {
- return E_FAIL;
- }
- //創建Effect
- ID3DXBuffer* errBuffer = NULL;
- if (FAILED(D3DXCreateEffectFromFile(g_pd3dDevice, L"edgedetect.fx", NULL, NULL, D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, NULL, &g_pEffect, &errBuffer)))
- {
- if (errBuffer)
- {
- MessageBox(0, (LPCTSTR)errBuffer->GetBufferPointer(), 0, 0);
- 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);
- // 設置要使用的Technique
- g_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()
- {
- // 獲取backbuffer
- LPDIRECT3DSURFACE9 pBackbuffer;
- g_pd3dDevice->GetRenderTarget(0, &pBackbuffer);
- //開始渲染場景
- if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
- {
- //設回backbuffer
- g_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 );
- //初始化Direct3D
- if( 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: [email protected]
- * Date: 2011-09-03
- ********************************/
- //------------------------------
- // 頂點着色器
- //------------------------------
- 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>;
- };
- //Laplacian算子盒1
- const float4 samples1[5] = {
- 0.0, 1.0, 0.0, -1.0,
- -1.0, 0.0, 0.0, -1.0,
- 0.0, 0.0, 0.0, 4.0,
- 1.0, 0.0, 0.0, -1.0,
- 0.0, 1.0, 0.0, -1.0
- };
- //Laplacian算子盒2
- const float4 samples2[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, 8.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
- };
- //Laplacian算子盒3
- const float4 samples3[9] = {
- -1.0, -1.0, 0.0, 1.0,
- 0.0, -1.0, 0.0, -2.0,
- 1.0, 1.0, 0.0, 1.0,
- -1.0, 0.0, 0.0, -2.0,
- 0.0, 0.0, 0.0, 4.0,
- 1.0, 0.0, 0.0, -2.0,
- -1.0, 1.0, 0.0, 1.0,
- 0.0, 1.0, 0.0, -2.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);
- for(int i = 0; i < 5; i++)
- {
- col += samples1[i].w * tex2D(TexMapScreen, texCoord + float2(samples1[i].x*viewport_inv_width,
- samples1[i].y*viewport_inv_height));
- }
- //爲了突出顯示,此處將結果乘2
- return 2.0 * col;
- }
- //------------------------------
- // 效果框架
- //------------------------------
- technique Screen
- {
- pass P0
- {
- VertexShader = compile vs_3_0 vs_mainPassScreen();
- PixelShader = compile ps_3_0 ps_mainPassScreen();
- }
- }
結果:
原圖:
處理結果1,採用Laplacin算子1
處理結果2,採用Laplacin算子2
處理結果3,採用Laplacin算子3
說明:
1.可以採用將圖像先進行灰度化後再進行邊緣檢測;
2.關於邊緣檢測還有其他的算子盒,大家可以根據需要選取不同的算子盒,通過上面的實驗可以看出,不同的算子盒適合不同的場景,結果也不同。
http://blog.csdn.net/rabbit729/article/details/8009218