1. 程式人生 > >影象處理:Robert邊緣檢測運算元

影象處理:Robert邊緣檢測運算元

事情比較多比較雜,早點把學校的事弄完吧,好久沒寫部落格了,最近計算機前沿這門課,老師要佈置課題,大部分是Verilog HDL程式設計,腦殼疼,硬體太煩,在這裡插入圖片描述
不過還好,可以選擇其他方向的
在這裡插入圖片描述

哈哈,api學習還是有必要的,不必造輪子,不過,要有造輪子的能力,具體分的課題是邊緣檢測演算法的Robert運算元
在這裡插入圖片描述
書上只是給個函式,可以理解為虛擬碼,具體實現,還是要自己去動手的,書上只是給個思路而已:
在這裡插入圖片描述

核心就是對畫素的處理,獲取點陣圖畫素位,處理畫素位,設定畫素位,就這麼幾部,當初想,多麼簡單啊,其實還是不能大意,遇到一些問題,然後慢慢克服,最終解決難題,只有這樣,才能不斷成長,絕對不能眼高手低
主要遇到的問題,就是獲得點陣圖的畫素位

一開始,我以為BITMAP結構的bmBits就是存放畫素位的,結果執行有問題
在這裡插入圖片描述
還以為是我自己沒有新載入一個位圖,在新位圖裡存放新畫素位,結果還是不行,除錯時發現BITMAP的bmBits始終為0
在這裡插入圖片描述
所以問題出在這,我們並沒有真正獲取到點陣圖的畫素位,要獲取點陣圖的畫素位,可以用GetBitmapBits函式,函式怎麼用去查msdn或者百度
相應的設定畫素位用SetBitmapBits,下面就是Robert運算元具體實現的核心程式碼了
在這裡插入圖片描述

最後實現效果:
在這裡插入圖片描述
在這裡插入圖片描述
好了,大功告成,一定要注意,獲取設定點陣圖畫素位,用BITMAP的bmBits成員是不行的,用GetBitmapBits和SetBitmapBits即可


最後附上完整win32 API程式碼:

//VC++影象處理程式
//影象的邊緣檢測-Robert運算元
# include<windows.h>
# include<cmath>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//視窗過程函式
void RobertOperator(HDC hdc, HDC hMemDc, HBITMAP hBitmap, int Width, int Height);
int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	PSTR szCmdLine,
	int iCmdShow) 
{
	TCHAR szAppName[] = TEXT("Robert運算元");

	//設計視窗類
	WNDCLASS wndclass;//視窗類
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//視窗背景畫刷(白色)
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hInstance = NULL;
	wndclass.lpfnWndProc = WndProc;
	wndclass.lpszClassName = szAppName;//類名
	wndclass.lpszMenuName = NULL;
	wndclass.style = CS_HREDRAW | CS_VREDRAW;

	//註冊視窗類
	if (!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("Program requires windows NT!"), szAppName, MB_ICONERROR);
		return 0;
	}

	//建立視窗
	HWND hwnd = CreateWindow(szAppName,
		TEXT("Robert運算元"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
	    540,
		630,
		NULL,
		NULL,
		hInstance,
		NULL);

	ShowWindow(hwnd, SW_SHOW);
	UpdateWindow(hwnd);

	MSG msg;//訊息迴圈
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	

	return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	static HDC hMemDc;
	static int xWidth, yHeight;
	static BITMAP bm;
	static HBITMAP hBitmap;

	switch (uMsg)
	{
	case WM_CREATE:
	{
		//原點陣圖
		 hBitmap= (HBITMAP)LoadImage(NULL, TEXT("Picture2.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
		if (hBitmap == NULL)
		{
			MessageBox(NULL, TEXT("讀取圖片失敗"), TEXT("Error"), MB_ICONERROR);
			return 0;
		}

		//將原點陣圖選進記憶體DC
		HDC hdc = GetDC(hwnd);
		hMemDc = CreateCompatibleDC(hdc);//記憶體DC
		SelectObject(hMemDc, hBitmap);
		ReleaseDC(hwnd, hdc);

		//計算點陣圖的寬和高
		GetObject(hBitmap, sizeof(bm), &bm);
		xWidth = bm.bmWidth;
		yHeight = bm.bmHeight;
		return 0;
	}
	case WM_PAINT:
	{
		HDC hdc;
		PAINTSTRUCT ps;
		hdc = BeginPaint(hwnd, &ps);
		BitBlt(hdc, 0, 0, xWidth, yHeight, hMemDc, 0, 0, SRCCOPY);
		//BitBlt(hdc, 0, 300, xTempWidth, yTempHeight, hTempMemDc, 0, 0, SRCCOPY);
		RobertOperator(hdc, hMemDc,hBitmap,xWidth, yHeight);
		//BitBlt(hdc, 590, 0, xWidth, yHeight, hMemDc, 0, 0, SRCCOPY);
		EndPaint(hwnd, &ps);
		return 0;
	}
	case WM_CLOSE:
		DeleteDC(hMemDc);
		PostQuitMessage(0);
		//DestroyWindow(hwnd);
		return 0;
	}


	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void RobertOperator(HDC hdc, HDC hMemDc,HBITMAP hBitmap,int Width, int Height)
{
	

	int Robert_Pixel[4];//Robert運算元
	
	
	BYTE *pTempPixel = new BYTE[16*Width*Height];
	//得到點陣圖的畫素位
	GetBitmapBits(hBitmap,16*Width*Height,(LPVOID)pTempPixel);
	
	BYTE *pPixel = new BYTE[16*Width*Height];
	for(int j=0;j<4*Height-1;j++)
		for (int i = 0; i < 4*Width - 1; i++)
		{
			//生成Robert運算元
			Robert_Pixel[0] = pTempPixel[j*4*Width+i];
			Robert_Pixel[1] = pTempPixel[j*4*Width+ i + 1];
			Robert_Pixel[2] = pTempPixel[(j + 1)*4*Width+ i];
			Robert_Pixel[3] = pTempPixel[(j + 1)*4*Width+i + 1];

			//生成當前畫素
			pPixel[j*4*Width+i] = (int)sqrt((Robert_Pixel[0] - Robert_Pixel[3])*
				(Robert_Pixel[0] - Robert_Pixel[3]) + (Robert_Pixel[1] - Robert_Pixel[2])*
				(Robert_Pixel[1] - Robert_Pixel[2]));
			//pPixel[j*Width + i] = pTempPixel[j*Width + i] + 100;

		}
	//設定新畫素位
	SetBitmapBits(hBitmap,16* Width*Height,pPixel);
	BitBlt(hdc,0, 300, Width, Height, hMemDc, 0, 0, SRCCOPY);

}

注意相應的點陣圖檔案要放在工程目錄下,以及點陣圖的檔名