반응형

freeglut을 설치하고 간단한 OpenGL 예제를 만들어 보자.


http://freeglut.sourceforge.net/ 에서 MSVC용 Prepackaged Release 를 다운 받아 원하는 폴더에 설치 한다.


빈 Console 프로젝트를 만든다.


freeglut 라이브러리의 dll 파일이 있는 폴더를 Environment에 지정 한다.


Include 디렉토리를 지정 한다.


sprintf() 사용을 위해 SDL checks를 No로 바꾼다. Yes로 된 경우 비표준 함수인 sprintf_s()를 써야 한다.


SDL checks: Adds recommended Security Development Lifecycle (SDL) checks. These checks include extra security-relevant warnings as errors, and additional secure code-generation features.


Library 디렉토리를 지정 한다.


외부 라이브러리 사용시 위 사진과 같이 라이브러리 파일들을 추가해야 하지만 freeglut_std.h에 필요한 라이브러리가 모두 추가 되어 있으므로 하지 않아도 된다.



<freeglut_std.h>

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
40
41
#   include <windows.h>
 
/* Windows static library */
#   ifdef FREEGLUT_STATIC
 
#error Static linking is not supported with this build. Please remove the FREEGLUT_STATIC preprocessor directive, or download the source code from http://freeglut.sf.net/ and build against that.
 
/* Windows shared library (DLL) */
#   else
 
#       define FGAPIENTRY __stdcall
#       if defined(FREEGLUT_EXPORTS)
#           define FGAPI __declspec(dllexport)
#       else
#           define FGAPI __declspec(dllimport)
 
            /* Link with Win32 shared freeglut lib */
#           if FREEGLUT_LIB_PRAGMAS
#             pragma comment (lib, "freeglut.lib")
#           endif
 
#       endif
 
#   endif
 
/* Drag in other Windows libraries as required by FreeGLUT */
#   if FREEGLUT_LIB_PRAGMAS
#       pragma comment (lib, "glu32.lib")    /* link OpenGL Utility lib     */
#       pragma comment (lib, "opengl32.lib"/* link Microsoft OpenGL lib   */
#       pragma comment (lib, "gdi32.lib")    /* link Windows GDI lib        */
#       pragma comment (lib, "winmm.lib")    /* link Windows MultiMedia lib */
#       pragma comment (lib, "user32.lib")   /* link Windows user lib       */
#   endif
 
#else
 
/* Non-Windows definition of FGAPI and FGAPIENTRY  */
#        define FGAPI
#        define FGAPIENTRY
 
#endif


windows.h 도 포함 되어 있다.


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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <gl/glut.h>
#include <cstdio>
 
GLfloat locationX = 0.0f, locationY = 0.0f;
const GLfloat step = 0.02f;
const GLfloat size = 0.2f;
int winId;
 
void Menu(int value);
void Keyboard(unsigned char key, int x, int y);
void Special(int key, int x, int y);
void Mouse(int button, int state, int x, int y);
void Display();
 
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    
    winId = glutCreateWindow("OpenGL");
 
    glutKeyboardFunc(Keyboard);
    glutSpecialFunc(Special);
    glutMouseFunc(Mouse);
 
    // Sub menu
    GLint SubMenu = glutCreateMenu(Menu);
    glutAddMenuEntry("Red"4);
    glutAddMenuEntry("Green"5);
    glutAddMenuEntry("Blue"6);
 
    // Menu
    glutCreateMenu(Menu);
    glutAddMenuEntry("White"1);
    glutAddMenuEntry("Black"2);
    glutAddMenuEntry("Gray"3);
 
    // Add sub menu
    glutAddSubMenu("Triangle Color", SubMenu);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
 
    glutDisplayFunc(Display);
 
    glutMainLoop();
 
    return 0;
}
 
void Menu(int value)
{
    switch (value) {
    case 1:
        glClearColor(1.0f1.0f1.0f1.0f);    // 배경 흰색
 
        break;
    case 2:
        glClearColor(0.0f0.0f0.0f1.0f);    // 배경 검정색
 
        break;
    case 3:
        glClearColor(0.5f0.5f0.5f1.0f);    // 배경 회색
 
        break;
    case 4:
        glColor3f(1.0f0.0f0.0f);            // 삼감형 빨간색
 
        break;
    case 5:
        glColor3f(0.0f1.0f0.0f);            // 삼감형 녹색
 
        break;
    case 6:
        glColor3f(0.0f0.0f1.0f);            // 삼감형 파란색
 
        break;
    default:
 
        break;
    }
 
    glutPostRedisplay();
}
 
void Keyboard(unsigned char key, int x, int y)
{
    switch (key) {
    case 'r':
    case 'R':
        glClearColor(1.0f0.0f0.0f1.0f);    // 배경 빨간색
 
        break;
    case 'g':
    case 'G':
        glClearColor(0.0f1.0f0.0f1.0f);    // 배경 녹색
 
        break;
    case 'b':
    case 'B':
        glClearColor(0.0f0.0f1.0f1.0f);    // 배경 파란색
 
        break;
    case 27:
        glutDestroyWindow(winId);                // ESC키 프로그램 종료
        exit(0);
 
        break;
    default:
 
        break;
    }
 
    glutPostRedisplay();
}
 
void Special(int key, int x, int y)
{
    switch (key) {
    case GLUT_KEY_LEFT:        // step 만큼 x감소
        locationX -= step;
 
        break;
    case GLUT_KEY_RIGHT:    // step 만큼 x증가
        locationX += step;
 
        break;
    case GLUT_KEY_UP:        // step 만큼 y증가
        locationY += step;
 
        break;
    case GLUT_KEY_DOWN:        // step 만큼 y감소
        locationY -= step;
 
        break;
    }
    char title[128= {0,};
    sprintf(title, "Triangle location (%.2f, y=%.2f)", locationX, locationY);
    glutSetWindowTitle(title); // 제목표시줄에 삼각형 좌표 표시
 
    glutPostRedisplay();
}
 
void Mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        glColor3f(0.0f1.0f1.0f);    // 삼각형 하늘색
        char title[128= { 0, };
        sprintf(title, "Click (x: %d, y: %d)", x, y);
        glutSetWindowTitle(title); // 제목표시줄에 클릭 좌표 표시
 
        glutPostRedisplay();
    }
    else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP){
        glColor3f(1.0f1.0f0.0f);    // 삼각형 노란색
 
        glutPostRedisplay();
    }
}
 
 
void Display()
{
    glClear(GL_COLOR_BUFFER_BIT);
        
    glBegin(GL_TRIANGLES);
    glVertex2f(locationX, locationY + size);
    glVertex2f(locationX - size, locationY - size);
    glVertex2f(locationX + size, locationY - size);
    glEnd();
 
    glFinish();
}


코드를 입력하고 실행 한다.


오른쪽 버튼을 클릭하면 메뉴가 나온다.


삼각형이 빨간색으로 바뀌었다.


r,g,b, 방향키, ESC키 등을 눌러 본다.


SubSystem을Console에서 Widows로 바꾼다.



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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <gl/glut.h>
 
void Menu(int value)
{
    switch (value) {
    case 1:
        glClearColor(1.0f1.0f1.0f1.0f);
 
        break;
    case 2:
        glClearColor(0.0f0.0f0.0f1.0f);
 
        break;
    case 3:
        glClearColor(0.5f0.5f0.5f1.0f);
 
        break;
    case 4:
        glColor3f(1.0f0.0f0.0f);
 
        break;
    case 5:
        glColor3f(0.0f1.0f0.0f);
 
        break;
    case 6:
        glColor3f(0.0f0.0f1.0f);
 
        break;
    default:
 
        break;
    }
 
    glutPostRedisplay();
}
 
void display() {
    glClear(GL_COLOR_BUFFER_BIT);
 
    glBegin(GL_TRIANGLES);
    glVertex2f(0.0f0.5f);
    glVertex2f(-0.5f-0.5f);
    glVertex2f(0.5f-0.5f);
    glEnd();
 
    glFinish();
}
 
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
    glutCreateWindow("OpenGL");
 
    // Sub menu
    GLint SubMenu = glutCreateMenu(Menu);
    glutAddMenuEntry("Red"4);
    glutAddMenuEntry("Green"5);
    glutAddMenuEntry("Blue"6);
 
    // Menu
    glutCreateMenu(Menu);
    glutAddMenuEntry("White"1);
    glutAddMenuEntry("Black"2);
    glutAddMenuEntry("Gray"3);
 
    // Add sub menu
    glutAddSubMenu("Triangle Color", SubMenu);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
 
    glutDisplayFunc(display);
 
    glutMainLoop();
 
    return 0;
}


위 코드와 같이 Windows 프로그램에 맞게 바꾸고 빌드하면 에러없이 빌드는 되지만 아무것도 실행 되지는 않는다.


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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <Windows.h>
#include <gl/gl.h>
 
# pragma comment (lib, "opengl32.lib")
# pragma comment(lib, "glu32.lib")
 
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass = TEXT("OpenGL");
HDC hdc;
HGLRC hrc;
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Display();
 
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst = hInstance;
 
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hInstance = hInstance;
    WndClass.lpfnWndProc = WndProc;
    WndClass.lpszClassName = lpszClass;
    WndClass.lpszMenuName = NULL;
    WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    RegisterClass(&WndClass);
 
    hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);
 
    while (GetMessage(&Message, NULL00)) {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
 
    return (int)Message.wParam;
}
 
void Display()
{
    glClear(GL_COLOR_BUFFER_BIT);
 
    glBegin(GL_TRIANGLES);
    glVertex2f(0.0f0.5f);
    glVertex2f(-0.5f-0.5f);
    glVertex2f(0.5f-0.5f);
    glEnd();
 
    glFinish();
}
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    switch (iMessage) {
    case WM_CREATE:
        hWndMain = hWnd;
        PIXELFORMATDESCRIPTOR pfd;
        int nPixelFormat;
 
        hdc = GetDC(hWnd);
        memset(&pfd, 0sizeof(pfd));
 
        pfd.nSize = sizeof(pfd);
        pfd.nVersion = 1;
        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
        pfd.iPixelType = PFD_TYPE_RGBA;
        pfd.cColorBits = 32;
 
        nPixelFormat = ChoosePixelFormat(hdc, &pfd);
        SetPixelFormat(hdc, nPixelFormat, &pfd);
 
        hrc = wglCreateContext(hdc);
        wglMakeCurrent(hdc, hrc);
 
        return 0;
 
    case WM_PAINT:
        Display();
 
        SetTextColor(hdc, RGB(2552550));
        SetBkMode(hdc, TRANSPARENT);
        TextOutA(hdc, 1010"Windows OpenGL"14);
        
        ValidateRect(hWnd, NULL);
 
        return 0;
 
    case WM_SIZE:
        glViewport(00, LOWORD(lParam), HIWORD(lParam));
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
 
        glOrtho(-11-111-1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
 
        return 0;
    case WM_DESTROY:
        wglMakeCurrent(hdc, NULL);
        wglDeleteContext(hrc);
        ReleaseDC(hWnd, hdc);
        PostQuitMessage(0);
 
        return 0;
    }
 
    return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}


glut을 사용하지 않고 Windows에서 지원하는 OpenGL 관련 wgl함수를 이용해 작성한 코드이다.



※ Reference

http://soen.kr/lecture/library/opengl/opengl-5.htm


반응형
Posted by J-sean
:
반응형

GDI+ Bitmap class inherits from the Image class. The Image class provides methods for loading and saving vector images (metafiles) and raster images (bitmaps). You can build Windows applications with GDI+ and OpenCV.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <windows.h>
#include <gdiplus.h>
#include <opencv2/opencv.hpp>
 
#pragma comment(lib, "gdiplus")
 
using namespace cv;
using namespace Gdiplus;
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
LPCSTR lpszClass = "MatToBitmap";
 
Mat src;    // source image
Mat org;    // original image
Mat dst;    // processed image
 

Prepare necessities.

 

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
40
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst = hInstance;
 
    ULONG_PTR gpToken;
    GdiplusStartupInput gpsi;
    if (GdiplusStartup(&gpToken, &gpsi, NULL!= Ok) {
        MessageBox(NULL, TEXT("GDI+ start-up error."), TEXT("GDI+ Error"), MB_OK);
 
        return 0;
    }
 
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); //(HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClass.hInstance = hInstance;
    WndClass.lpfnWndProc = (WNDPROC)WndProc;
    WndClass.lpszClassName = lpszClass;
    WndClass.lpszMenuName = NULL;
    WndClass.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&WndClass);
 
    hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,
        670340NULL, (HMENU)NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);
 
    while (GetMessage(&Message, 000)) {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
 
    GdiplusShutdown(gpToken);
 
    return (int)Message.wParam;
}
 
 

Start GDI+ and change the background color to the radio button color and Window size.

 

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, 0sizeof(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;
    }
}
 
 

Retrieve an image file name.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool ImageLoad()
{
    TCHAR filename[MAX_PATH] = "";
 
    if (getFile(filename)) {
        src = imread(filename);
        if (src.empty()) {
            MessageBox(NULL, TEXT("Image load failed"), TEXT("No image loaded"), MB_OK);
 
            return false;
        }
 
        return true;
    }
    else {
        return false;
    }
}
 
 

Read the image from the file.

 

1
2
3
4
5
6
7
8
void ImageResize()
{
    // maximum image display size: 320 X 240 with original ratio
    double ratio = min((double)320 / (double)src.size().width, (double)240 / (double)src.size().height);
    resize(src, src, cv::Size(), ratio, ratio);
    org = src.clone();
    cvtColor(org, org, COLOR_BGR2BGRA);
}
 
 

Resize an image.

 

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
40
41
42
43
44
45
46
47
void ImageProcess(int direction)
{
    cvtColor(src, dst, COLOR_BGR2GRAY);
 
    float vertical[] = {
        -202,
        -202,
        -202
    };
 
    float horizontal[] = {
        -2-2-2,
        000,
        222
    };
 
    float diagonal[] = {
        -2-20,
        -202,
        022
    };
    
    Mat emboss;
    switch (direction)
    {
    case 0:
        emboss = Mat(33, CV_32FC1, vertical);
 
        break;
 
    case 1:
        emboss = Mat(33, CV_32FC1, horizontal);
 
        break;
 
    case 2:
        emboss = Mat(33, CV_32FC1, diagonal);
 
        break;
 
    default:
        emboss = Mat(33, CV_32FC1, vertical);
    }
    filter2D(dst, dst, -1, emboss, cv::Point(-1-1), 128);
    
    cvtColor(dst, dst, COLOR_GRAY2BGRA);
}
 
 

Process an image with embossing filter.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void OnPaint(HDC hdc)
{
    if (!dst.empty()) {
        Graphics G(hdc);
 
        Bitmap bitmapDst(dst.size().width, dst.size().height, dst.step, PixelFormat32bppARGB, dst.data);
        Bitmap bitmapOrg(org.size().width, org.size().height, org.step, PixelFormat32bppARGB, org.data);
        // stride(src.step): Integer that specifies the byte offset between the beginning of one scan line and
        // the next. This is usually(but not necessarily) the number of bytes in the pixel format(for example,
        // 2 for 16 bits per pixel) multiplied by the width of the bitmap. The value passed to this parameter
        // must be a multiple of four.
 
        G.DrawImage(&bitmapDst, 00, bitmapDst.GetWidth(), bitmapDst.GetHeight());
        G.DrawImage(&bitmapOrg, bitmapOrg.GetWidth() + 100, bitmapOrg.GetWidth(), bitmapOrg.GetHeight());
    }
    else {
        TextOut(hdc, 270110, TEXT("No image to display"), 19);
    }
}
 
 

Draw original and processed images.

 

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
enum { ID_R1 = 101, ID_R2, ID_R3 };
HWND r1, r2, r3;
int x = 10;
int y = 270;
int w = 90;
int h = 20;
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;    
 
    switch (iMessage) {
    case WM_CREATE:
        if (ImageLoad()) {
            ImageResize();
            ImageProcess(0);
        }
        
        CreateWindow(TEXT("button"), TEXT("Filter type"), WS_CHILD | WS_VISIBLE |
            BS_GROUPBOX, 525029050, hWnd, (HMENU)0, g_hInst, NULL);
 
        r1 = CreateWindow(TEXT("button"), TEXT("Vertical"), WS_CHILD | WS_VISIBLE |
            BS_AUTORADIOBUTTON | WS_GROUP, x, y, w, h, hWnd, (HMENU)ID_R1, g_hInst, NULL);
 
        r2 = CreateWindow(TEXT("button"), TEXT("Horizontal"), WS_CHILD | WS_VISIBLE |
            BS_AUTORADIOBUTTON, x + 90, y, w, h, hWnd, (HMENU)ID_R2, g_hInst, NULL);
 
        r3 = CreateWindow(TEXT("button"), TEXT("Diagonal"), WS_CHILD | WS_VISIBLE |
            BS_AUTORADIOBUTTON, x + 180, y, w, h, hWnd, (HMENU)ID_R3, g_hInst, NULL);
 
        CheckRadioButton(hWnd, ID_R1, ID_R3, ID_R1);
 
        return 0;
 
    case WM_COMMAND:
        if (!dst.empty()) {
            switch (LOWORD(wParam)) {
            case ID_R1:
                ImageProcess(0);
                break;
 
            case ID_R2:
                ImageProcess(1);
                break;
 
            case ID_R3:
                ImageProcess(2);
                break;
            }
 
            InvalidateRect(hWnd, NULL, TRUE);
        }
 
        return 0;
 
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        OnPaint(hdc);
        EndPaint(hWnd, &ps);
 
        return 0;
 
    case WM_DESTROY:
        PostQuitMessage(0);
 
        return 0;
    }
 
    return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
 
 

Define the necessary variables and handle window messages.

 

 

Run the application and select an image file.

 

Processed and original image with a vertical filter.

 

Processed and original image with a horizontal filter.

 

Processed and original image with a diagonal filter.

 

 

반응형
Posted by J-sean
:
반응형

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, 0sizeof(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(00255), -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(00);
                dstQuad[1= Point2f(width - 10);
                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.


반응형
Posted by J-sean
:
반응형

Windows에서 Visual Studio를 이용해 Linux에 원격으로 접속해서 C++ 프로그램 개발이 가능하다.

Linux에는 미리 gcc나 g++가 설치 되어 있어야 한다.

- Fedora: sudo dnf install g++

- Ubuntu: sudo apt-get install g++


New Project 창을 열고 Visual C++ - Cross Platform - Linux - 원하는 프로젝트를 선택해서 이름과 디렉토리를 지정해 준다.


간단한 소스가 입력된 프로젝트가 생성 된다. 아직 Linux에 연결되지는 않았다.


ifconfig 명령으로 접속할 Linux system의 주소를 확인한다.




Tools - Options창에서 Cross Platform - Add를 클릭한다.


Host name, Port, User name, Authentication type, Password를 입력한다.


헤더 파일, 인텔리센스등의 업데이트가 진행 된다.


업데이트가 완료되면 연결된 Linux system의 정보가 등록 된다.


Build 하면 Source를 Linux system으로 복사하고 Remote Build가 진행 된다.


Linux system에서 확인해 보면 실행파일이 생성 되어 있고 문제 없이 실행 된다.


Property Pages에서 Output Directory, Remote Build Machine등 여러가지 설정을 바꿀 수 있다.


반응형
Posted by J-sean
:
반응형

Python에서 windows API를 사용 할 수 있게 해 주는 모듈이다.

간단한 Desktop GUI 예제:

 

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
import win32api
import win32gui
import win32con
import win32ui
 
#hinstance = win32api.GetModuleHandle(None)
 
hWnd = win32gui.GetDesktopWindow()
# Retrieves a handle to the desktop window. The desktop window covers the entire screen.
# The desktop window is the area on top of which other windows are painted.
hdc = win32gui.GetDC(hWnd)
#win32gui.GetDC(None)
# A handle to the window whose DC is to be retrieved. If this value is NULL, GetDC
# retrieves the DC for the entire screen.
 
hMemDC = win32gui.CreateCompatibleDC(hdc)
 
hImage = win32gui.LoadImage(None, "cat.bmp", win32con.IMAGE_BITMAP, 00, win32con.LR_LOADFROMFILE | win32con.LR_CREATEDIBSECTION);
# Loads an icon, cursor, animated cursor, or bitmap
 
hOldBitmap = win32gui.SelectObject(hMemDC, hImage)
win32gui.BitBlt(hdc, 505050 + 40050 + 272, hMemDC, 00, win32con.SRCCOPY) # Image(400, 272) at (50, 50)
# The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels
# from the specified source device context into a destination device context.
 
win32gui.SelectObject(hMemDC, hOldBitmap)
win32gui.DeleteObject(hImage)
win32gui.DeleteDC(hMemDC)
win32gui.ReleaseDC(hWnd, hdc)
cs

 

결과

 

 

실행 방식에 따라 제대로 표시가 안되는 경우가 있다.

 

1) 스크립트파일 - 우클릭 - 연결 프로그램 - Python - 표시가 안되는 경우가 있다.

2) Console - 스크립트 파일 실행 - 잘 표시 된다.

 

반응형
Posted by J-sean
:
반응형

Python에서 windows API를 사용 할 수 있게 해 주는 모듈이다.


간단한 Desktop GUI 예제:

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
40
41
42
43
44
45
46
47
48
49
50
import win32api
import win32gui
import win32con
import win32ui
 
hWnd = win32gui.GetDesktopWindow()
# Retrieves a handle to the desktop window. The desktop window covers the entire screen.
# The desktop window is the area on top of which other windows are painted.
hdc = win32gui.GetDC(hWnd)
#win32gui.GetDC(None)
# A handle to the window whose DC is to be retrieved. If this value is NULL, GetDC
# retrieves the DC for the entire screen.
 
red = win32api.RGB(25500)
win32gui.SetPixel(hdc, 00, red)  # (0, 0)에 빨간 점 그리기
 
MyPen = win32gui.CreatePen(win32con.PS_SOLID, 5, win32api.RGB(0,0,255));
OldPen = win32gui.SelectObject(hdc, MyPen);
 
win32gui.Rectangle(hdc, 5050100100# (50, 50, 100, 100)에 파란 선으로 사각형 그리기
 
win32gui.SelectObject(hdc, OldPen);
win32gui.DeleteObject(MyPen);
 
# 폰트 만들기
font_spec = {'name':'Arial''height':42'weight':30}
font = win32ui.CreateFont(font_spec)
#lf = win32gui.LOGFONT()
#lf.lfFaceName = "Times New Roman"
#lf.lfHeight = 100
#lf.lfWeight = win32con.FW_NORMAL
#hf = win32gui.CreateFontIndirect(lf)
 
oldfont = win32gui.SelectObject(hdc, font.GetSafeHandle())
 
win32gui.SetTextColor(hdc, win32api.RGB(255,0,0))
win32gui.SetBkColor(hdc, win32api.RGB(255,255,0))
#win32gui.SetBkMode(hdc, win32con.TRANSPARENT)
# Desktop window DC로는 SetBKMode()가 잘 작동하지 않는다
 
text = 'Software Engineer'
rect = win32gui.GetClientRect(hWnd)
win32gui.DrawText(hdc, text, len(text), rect, win32con.DT_CENTER | win32con.DT_VCENTER
                  | win32con.DT_SINGLELINE | win32con.DT_WORDBREAK)
# 화면 가운데 문자열 출력
 
win32gui.SelectObject(hdc,oldfont)
win32gui.DeleteObject(font.GetSafeHandle())
 
win32gui.ReleaseDC(hWnd, hdc)
cs


반응형

'Python' 카테고리의 다른 글

Pillow 이미지 서치(Image Search) 1  (0) 2018.11.30
pywin32 Windows Extensions for Python 2  (0) 2018.11.27
Pillow 화면 변화 감지(Pixel Checksum) 2  (0) 2018.11.21
Pillow 화면 변화 감지(Pixel Checksum) 1  (0) 2018.11.20
PyMySQL  (2) 2018.11.19
Posted by J-sean
: