影象處理:Robert邊緣檢測運算元
阿新 • • 發佈:2018-11-27
事情比較多比較雜,早點把學校的事弄完吧,好久沒寫部落格了,最近計算機前沿這門課,老師要佈置課題,大部分是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); }
注意相應的點陣圖檔案要放在工程目錄下,以及點陣圖的檔名