Search

2012年10月28日 星期日

最近好懶...

  自從這學期新住的地方有廚房後幾乎每餐都自己煮,因為懶得走出去買便當XD話說最近注意到wxWidgets在初始的邏輯上Windows跟Linux有不一樣的地方,同樣的code在wxFrame的Constructor初始其他library的實體或是虛擬設備再Linux正常,不過Windows下很明顯要等wxFrame自己初始完再初始DirectX或者OpenCV的設備或者實體的晶片才不會有問題,所以我猜當初Linux跟Windows版本是不同人寫的XD,還要等最近有空讀一下Source Code確認,另外對於辨識認證圖片的文字去除背景與雜訊後,要圈出文字範圍我發現先將它模糊幾次後做Canny再取輪廓準確率很高速度也快,不做模糊直接Canny再取輪廓會因為反差太大每個有色像素都被圈到,做幾次模糊可以讓文字從中像墨水般暈開然後取輪廓時就很容易標記整個範圍了。

2012年10月24日 星期三

ええええ?!

    繼上次改寫舊的繪圖引擎把矩陣運算等等的改用SIMD方式去寫之後,很好奇MSDN上寫的_mm_set_ps跟_mm_load_ps除了順序相反以外的差別,我以為_mm_set_ps直接從data段設定__m128之類型態的變數數值,不過看了一下編譯後的樣子會先設定xmm0~4低32位元然後用UNPCKLPS慢慢移動到xmm0最後才把xmm0的值移動到__m128之類型態的變數,而且沒開-O2跟有開在設定xmm0~4時順序會相反不過我看不出除了相同數值共用同個data段設定外這樣有優化什麼?而用_mm_load_ps就直接MOVAPS整個16 bytes的資料到xmm0再MOVAPS到__m128之類型態的變數,總之我覺得SSE2效果不錯也好用。


__declspec(align(16)) float data[4] = {1.13f,1.22f,1.31f,1.0f};    //Data Segment
__m128 m0 = _mm_set_ps(1.0f,1.22f,1.33f,1.0f);
__m128 m1 = _mm_load_ps(data);


==============================================================
Release /Od

__m128 m0 = _mm_set_ps(1.0f,1.22f,1.33f,1.0f);

MOVSS XMM0,DWORD PTR DS:[402178]         ; FLOAT 1.000000
MOVSS XMM1,DWORD PTR DS:[402174]         ; FLOAT 1.330000
MOVSS XMM2,DWORD PTR DS:[402170]         ; FLOAT 1.220000
MOVSS XMM3,DWORD PTR DS:[402178]         ; FLOAT 1.000000
UNPCKLPS XMM0,XMM2
UNPCKLPS XMM1,XMM3
UNPCKLPS XMM0,XMM1
MOVAPS DQWORD PTR SS:[LOCAL.6],XMM0
MOVAPS XMM0,DQWORD PTR SS:[LOCAL.6]
MOVAPS DQWORD PTR SS:[LOCAL.10],XMM0

__m128 m1 = _mm_load_ps(data);

MOVAPS XMM0,DQWORD PTR DS:[403030]
MOVAPS DQWORD PTR SS:[LOCAL.14],XMM0
MOVAPS XMM0,DQWORD PTR SS:[LOCAL.14]
MOVAPS DQWORD PTR SS:[LOCAL.18],XMM0

==============================================================

Release /O2

__m128 m0 = _mm_set_ps(1.0f,1.22f,1.33f,1.0f);

MOVSS XMM0,DWORD PTR DS:[402140]         ; FLOAT 1.000000
MOVSS XMM2,DWORD PTR DS:[40213C]         ; FLOAT 1.220000
MOVSS XMM3,DWORD PTR DS:[402138]         ; FLOAT 1.330000
MOVSS XMM1,XMM0
UNPCKLPS XMM0,XMM2
UNPCKLPS XMM3,XMM1
UNPCKLPS XMM0,XMM3
MOVAPS DQWORD PTR SS:[LOCAL.8],XMM0

__m128 m1 = _mm_load_ps(data);

MOVAPS XMM0,DQWORD PTR DS:[403030]
MOVAPS DQWORD PTR SS:[LOCAL.4],XMM0

2012年10月13日 星期六

wxWidgets With DirectX9 HLSL

    今天翻到以前用MFC+D3D9寫練習用的繪圖引擎,想改寫成wxWidgets版本,只要用wxWindow的GetHandle得到該平台的Handle就可以Create D3D Device了,還有一個是GetHWND意思一樣,要Create D3D10 Device也一樣,然後設定Vertex Shader or Pixel Shader就是D3D Device的事了。

render_data.h


#ifndef __RENDER_DATA__
#define __RENDER_DATA__

#define SAFE_RELEASE(x) if (x){x->Release();x = NULL;}

struct VertexTexture
{
float Position[3];
float Texcoord[2];
};

VertexTexture quad[4] =
{
{{-1.0f, -1.0f, 0.0f},{0.0f, 1.0f}},
{{ 1.0f, -1.0f, 0.0f},{1.0f, 1.0f}},
{{-1.0f,  1.0f, 0.0f},{0.0f, 0.0f}},
{{ 1.0f,  1.0f, 0.0f},{1.0f, 0.0f}}
};

#endif


shader.hlsl


sampler2D Sampler;

uniform float4x4 world_view_proj_matrix : register(c0);

struct VS_INPUT
{
float3 Position : POSITION;
float2 Texcoord : TEXCOORD;
};

struct VS_OUTPUT
{
float4 Position : POSITION;
float2 Texcoord : TEXCOORD0;
};

VS_OUTPUT VS(VS_INPUT In)
{
VS_OUTPUT Out;

Out.Position = mul(world_view_proj_matrix,float4(In.Position, 1.0f));
Out.Texcoord = In.Texcoord;

return Out;
}

float4 PS(VS_OUTPUT In) : COLOR
{
float4 color = tex2D(Sampler, In.Texcoord);

return color;
}



wxDirectX9.h


#ifndef __WX_DIRECT_X__
#define __WX_DIRECT_X__

#include <wx/wx.h>

#include <D3D9.h>
#include <D3DX9.h>

#include "render_data.h"

namespace{
HWND g_hwnd = NULL;

LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DPRESENT_PARAMETERS g_pD3DPresent;
LPDIRECT3DTEXTURE9 g_pTexture = NULL;

LPDIRECT3DVERTEXSHADER9 g_pVertexShaderDX9 = NULL;
LPDIRECT3DPIXELSHADER9  g_pPixelShaderDX9 = NULL;
}

class App:public wxApp
{
public:

bool OnInit();
int OnExit();
};

class Viewport:public wxPanel
{
public:

Viewport(wxWindow*,wxSize);
~Viewport();
void Reset(wxSizeEvent&);
void Updata(wxIdleEvent&);
void Render(wxEraseEvent&);
void InitDX9State();

private:

D3DXVECTOR3 eye;
D3DXVECTOR3 lookat;
D3DXVECTOR3 up;

D3DXMATRIX world_matrix;
D3DXMATRIX view_matrix;
D3DXMATRIX projection_matrix;

static const unsigned long fps = 60;
unsigned long begin,last;

float angle;

DECLARE_EVENT_TABLE()
};

class Frame:public wxFrame
{
public:

Frame(const wxString&,wxSize);
~Frame();

void OnExit(wxCommandEvent&);

bool InitD3D9Device();
void ReleaseD3D9Device();
LPDIRECT3DVERTEXSHADER9 LoadVertexShaderDX9(const wxString&,const wxString&,const wxString&);
LPDIRECT3DPIXELSHADER9 LoadPixelShaderDX9(const wxString&,const wxString&,const wxString&);

void CreateUI();

private:
Viewport *viewport;

DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(Viewport,wxPanel)
EVT_IDLE(Viewport::Updata)
EVT_ERASE_BACKGROUND(Viewport::Render)
EVT_SIZE(Viewport::Reset)
END_EVENT_TABLE()

BEGIN_EVENT_TABLE(Frame,wxFrame)
EVT_MENU(wxID_EXIT,Frame::OnExit)
END_EVENT_TABLE()

IMPLEMENT_APP(App)
DECLARE_APP(App)

#endif


wxDirectX9.cpp


#include "wxDirectX9.h"

bool App::OnInit()
{
Frame *frame = new Frame(wxT("wxDirectX9"),wxSize(512,512));

frame->Show(true);

return true;
}

int App::OnExit()
{
return wxApp::OnExit();
}

Frame::Frame(const wxString &title,wxSize size):wxFrame(NULL,wxID_ANY,title,wxDefaultPosition,size)
{
viewport = new Viewport(this,size);
g_hwnd = (HWND)viewport->GetHandle();

InitD3D9Device();

g_pVertexShaderDX9 = LoadVertexShaderDX9(wxT("shader.hlsl"),wxT("VS"),wxT("vs_3_0"));
g_pPixelShaderDX9 = LoadPixelShaderDX9(wxT("shader.hlsl"),wxT("PS"),wxT("ps_3_0"));

viewport->InitDX9State();

CreateUI();
}

Frame::~Frame()
{
ReleaseD3D9Device();
}

void Frame::CreateUI()
{
wxMenu *file = new wxMenu;
file->Append(wxID_EXIT,wxT("E&xit\tAlt-q"),wxT("Exit"));

wxMenuBar *bar = new wxMenuBar;
bar->Append(file,wxT("File"));
SetMenuBar(bar);
}

void Frame::OnExit(wxCommandEvent &event)
{
Close();
}

bool Frame::InitD3D9Device()
{
if(g_hwnd == NULL){
return false;
}

RECT rect;
GetWindowRect(g_hwnd,&rect);

float width = rect.right - rect.left;
float height = rect.bottom - rect.top;
if ( width == 0 || height == 0 ){
return false;
}

if( NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) ){
return false;
}

ZeroMemory(&g_pD3DPresent, sizeof(g_pD3DPresent));
g_pD3DPresent.Windowed = TRUE;
g_pD3DPresent.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_pD3DPresent.BackBufferFormat = D3DFMT_UNKNOWN;
g_pD3DPresent.BackBufferCount = 1;
g_pD3DPresent.EnableAutoDepthStencil = TRUE;
g_pD3DPresent.AutoDepthStencilFormat = D3DFMT_D24S8;
g_pD3DPresent.MultiSampleType = (D3DMULTISAMPLE_TYPE)0;
g_pD3DPresent.hDeviceWindow = g_hwnd;

bool device_initialized = false;

const int device_types = 4;

struct sDeviceType
{
D3DDEVTYPE type;
DWORD behavior;
};

sDeviceType device_type[device_types] =
{
{D3DDEVTYPE_HAL,D3DCREATE_HARDWARE_VERTEXPROCESSING},
{D3DDEVTYPE_HAL,D3DCREATE_MIXED_VERTEXPROCESSING},
{D3DDEVTYPE_HAL,D3DCREATE_SOFTWARE_VERTEXPROCESSING},
{D3DDEVTYPE_REF,D3DCREATE_SOFTWARE_VERTEXPROCESSING}
};

for (int type=0;type < device_types;++type)
{
if(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,device_type[type].type,g_hwnd,device_type[type].behavior,&g_pD3DPresent,&g_pD3DDevice) == D3D_OK)
{
device_initialized = true;
break;
}
}

return device_initialized;
}

void Frame::ReleaseD3D9Device()
{
SAFE_RELEASE(g_pD3DDevice);
SAFE_RELEASE(g_pD3D);
SAFE_RELEASE(g_pVertexShaderDX9);
SAFE_RELEASE(g_pPixelShaderDX9);
SAFE_RELEASE(g_pTexture);
}

LPDIRECT3DVERTEXSHADER9 Frame::LoadVertexShaderDX9(const wxString &filename,const wxString &entry,const wxString &profile)
{
LPD3DXBUFFER shader = NULL;
LPD3DXBUFFER error_msg = NULL;
DWORD flags = 0;

HRESULT result = D3DXCompileShaderFromFile(filename.wc_str(),NULL,NULL,entry.mb_str(),profile.mb_str(),flags,&shader,&error_msg,NULL);

if(result != S_OK){return NULL;}

LPDIRECT3DVERTEXSHADER9 vertex_shader = NULL;
result = g_pD3DDevice->CreateVertexShader((DWORD*)shader->GetBufferPointer(),&vertex_shader);

if(result != S_OK){return NULL;}

shader->Release();

return vertex_shader;
}

LPDIRECT3DPIXELSHADER9 Frame::LoadPixelShaderDX9(const wxString &filename,const wxString &entry,const wxString &profile)
{
LPD3DXBUFFER shader = NULL;
LPD3DXBUFFER error_msg = NULL;
DWORD flags = 0;

HRESULT result = D3DXCompileShaderFromFile(filename.wc_str(),NULL,NULL,entry.mb_str(),profile.mb_str(),flags,&shader,&error_msg,NULL);

if(result != S_OK){return NULL;}

LPDIRECT3DPIXELSHADER9 pixel_shader = NULL;
result = g_pD3DDevice->CreatePixelShader((DWORD*)shader->GetBufferPointer(),&pixel_shader);

if(result != S_OK){return NULL;}

shader->Release();

return pixel_shader;
}

Viewport::Viewport(wxWindow *parent,wxSize size):wxPanel(parent,wxID_ANY,wxDefaultPosition,size),eye(0.0f, 3.0f, 3.0f),lookat(0.0f, 0.0f, 0.0f),up(0.0f, -1.0f, 0.0f)
{
begin = last = 0;
angle = 0.0f;
}

Viewport::~Viewport()
{
}

void Viewport::InitDX9State()
{
int width,height;
GetSize(&width,&height);
float aspect = (float)height / (float)width;

D3DXMatrixPerspectiveFovRH(&projection_matrix,45.0f * (3.141592654f/180.0f),aspect,0.1f,10.0f);

D3DXMatrixLookAtRH(&view_matrix,&eye,&lookat,&up);

D3DXMatrixIdentity(&world_matrix);

D3DXMATRIX world_view_proj_matrix = world_matrix * view_matrix * projection_matrix;

g_pD3DDevice->SetVertexShaderConstantF(0,(float*)&world_view_proj_matrix,4);

g_pD3DDevice->SetSamplerState(0,  D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
g_pD3DDevice->SetSamplerState(0,  D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
g_pD3DDevice->SetSamplerState(0,  D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

g_pD3DDevice->SetSamplerState(0,  D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
g_pD3DDevice->SetSamplerState(0,  D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

g_pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
g_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

D3DXCreateTextureFromFileEx(g_pD3DDevice,L"lena.bmp",
D3DX_DEFAULT,D3DX_DEFAULT,D3DX_DEFAULT,0,D3DFMT_UNKNOWN,
D3DPOOL_MANAGED,D3DX_DEFAULT,
D3DX_DEFAULT,0,NULL, NULL,
&g_pTexture);
}

void Viewport::Updata(wxIdleEvent &event)
{
begin = wxGetLocalTimeMillis().ToLong();
if(begin - last > (1000 / fps)){
static float angle = 0.0f;
angle += 0.01f;
D3DXMatrixRotationZ(&world_matrix,angle);
D3DXMATRIX world_view_proj_matrix =  world_matrix * view_matrix * projection_matrix;
g_pD3DDevice->SetVertexShaderConstantF(0,(float*)&world_view_proj_matrix,4);
}
Refresh();
}

void Viewport::Reset(wxSizeEvent &event)
{
RECT rect;
GetWindowRect(g_hwnd, &rect);

g_pD3DPresent.BackBufferWidth = 0;
g_pD3DPresent.BackBufferHeight = 0;
g_pD3DPresent.BackBufferCount = 1;
g_pD3DDevice->Reset(&g_pD3DPresent);

int width,height;
GetSize(&width,&height);
float aspect = (float)height / (float)width;

D3DXMatrixPerspectiveFovRH(&projection_matrix,45.0f * (3.141592654f/180.0f),aspect,0.1f,10.0f);

D3DXMatrixLookAtRH(&view_matrix,&eye,&lookat,&up);

D3DXMATRIX world_view_proj_matrix = world_matrix * view_matrix * projection_matrix;

g_pD3DDevice->SetVertexShaderConstantF(0,(float*)&world_view_proj_matrix,4);
}

void Viewport::Render(wxEraseEvent &event)
{
g_pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_ARGB(0, 0, 0, 0),1.0f,0);

g_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

g_pD3DDevice->BeginScene();

g_pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1);

g_pD3DDevice->SetVertexShader(g_pVertexShaderDX9);
g_pD3DDevice->SetPixelShader(g_pPixelShaderDX9);

g_pD3DDevice->SetTexture(0, g_pTexture);

g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,quad,sizeof(VertexTexture));

g_pD3DDevice->EndScene();

g_pD3DDevice->Present(NULL,NULL,NULL,NULL);
}







2012年10月5日 星期五

新機器

    趁前天有空找同學一起去NOVA買新機的零件,這是我第一次在台中NOVA買電腦零件,大致上就是整個2樓問一圈看誰價格對味就買了,不過有的說沒貨要先付訂金調貨的我一概不考慮,因為主要還是怕被洗單還怎樣的...。

 用比較大的螢幕coding或是re感覺就真的不一樣,不過太近會有一點壓迫感ORZ



 GPU PRO 3的demo跑起來也沒有問題,本來想說要直接多貼幾千買GTX 660 Ti,不過後來想想明年還會再換顯示卡所以就先買GTX 660了XD



 前幾天也有同學想用Tesseract玩OCR解驗證圖片,所以我試著寫個小程式把驗證圖片背景去除,我的流程:
高斯濾波 -> 背景取平均值 -> 將接近前個步驟的值的一個範圍的像素設成白色 -> 去除雜訊如線條之類的 -> 將每個文字分割成一個個小圖片 -> 將小圖轉正 -> 個別丟到Tesseract就可以得到結果了。
不過第二跟第四個步驟要個別針對不同複雜度的圖片寫專用的演算法。