Windows dialog based OpenCV Perspective Transform - 윈도우 다이얼로그 기반의 OpenCV Perspective Transform
OpenCV 2019. 10. 20. 14:10 |Build a windows dialog-based OpenCV perspective transform program.
Change Subsystem setting from Console to Windows if necessary.
Add a resource and create a dialog box.
Include and declare necessities.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <Windows.h> #include <opencv2/opencv.hpp> #include "resource.h" using namespace cv; bool getFile(PTCHAR filename); void onMouse(int event, int x, int y, int flags, void* userdata); INT_PTR MainDlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam); HWND hDlgMain; Mat sourceImage; Mat targetImage; // TTC card ratio int width = 850; int height = 550; Point2f srcQuad[4], dstQuad[4]; |
Define WinMain which calls getFile() and DialogBox().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { TCHAR filename[MAX_PATH] = ""; if (!getFile(filename)) { return -1; } sourceImage = imread(filename); if (sourceImage.empty()) { MessageBox(NULL, TEXT("Image load failed"), TEXT("No image loaded"), MB_OK); return -1; } namedWindow("sourceImage"); setMouseCallback("sourceImage", onMouse); imshow("sourceImage", sourceImage); DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), HWND_DESKTOP, MainDlgProc); return 0; } |
getFile() retrieves an image file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | bool getFile(PTCHAR filename) { OPENFILENAME ofn; memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = NULL; ofn.lpstrFilter = TEXT("all(*.*)\0*.*\0jpg(*.jpg)\0*.jpg\0png(*.png)\0*.png\0bmp(*.bmp)\0*.bmp\0"); ofn.lpstrFile = filename; ofn.nMaxFile = MAX_PATH; if (GetOpenFileName(&ofn) != 0) { //MessageBox(NULL, filename, TEXT("File opened."), MB_OK); return true; } else { MessageBox(NULL, TEXT("File open failed"), TEXT("No file selected"), MB_OK); return false; } } |
Define a mouse callback function that processes perspective transform.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | void onMouse(int event, int x, int y, int flags, void* userdata) { static int cnt = 0; if (event == EVENT_LBUTTONDOWN) { if (cnt < 4) { srcQuad[cnt++] = Point2f(x, y); circle(sourceImage, Point2f(x, y), 3, Scalar(0, 0, 255), -1); imshow("sourceImage", sourceImage); if (cnt == 4) { /* width = max( sqrt(pow(srcQuad[0].x - srcQuad[1].x, 2)) + sqrt(pow(srcQuad[0].y - srcQuad[1].y, 2)), sqrt(pow(srcQuad[2].x - srcQuad[3].x, 2)) + sqrt(pow(srcQuad[2].y - srcQuad[3].y, 2)) ); height = max( sqrt(pow(srcQuad[1].x - srcQuad[2].x, 2)) + sqrt(pow(srcQuad[1].y - srcQuad[2].y, 2)), sqrt(pow(srcQuad[3].x - srcQuad[0].x, 2)) + sqrt(pow(srcQuad[3].y - srcQuad[0].y, 2)) ); */ dstQuad[0] = Point2f(0, 0); dstQuad[1] = Point2f(width - 1, 0); dstQuad[2] = Point2f(width - 1, height - 1); dstQuad[3] = Point2f(0, height - 1); Mat perspectiveTransform = getPerspectiveTransform(srcQuad, dstQuad); warpPerspective(sourceImage, targetImage, perspectiveTransform, Size(width, height)); cnt = 0; imshow("targetImage", targetImage); } } } } |
Dialog box procedure sets and/or retrieves target image width and height value from the dialog.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | INT_PTR MainDlgProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) { switch (iMessage) { case WM_INITDIALOG: hDlgMain = hDlg; SetDlgItemInt(hDlg, IDC_WIDTH, width, FALSE); SetDlgItemInt(hDlg, IDC_HEIGHT, height, FALSE); return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: width = GetDlgItemInt(hDlg, IDC_WIDTH, NULL, FALSE); height = GetDlgItemInt(hDlg, IDC_HEIGHT, NULL, FALSE); return TRUE; case IDCLOSE: EndDialog(hDlg, IDOK); return TRUE; } } return FALSE; } |
Run the program and select an image file.
You can change the target image size or just leave it.
Source image window.
Choose four corners from the left-top to clockwise.
Perspective transform processed image.