반응형

It describes how to detect faces with Haar-cascade classifier.

OpenCV에서 Haar-cascade classifier를 이용한 얼굴 검출.


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
#include <opencv2/opencv.hpp>
 
using namespace std;
using namespace cv;
 
int main()
{
    Mat src = imread("girl.jpg");
 
    if (src.empty()) {
        cerr << "Image load failed." << endl;
 
        return -1;
    }
 
    CascadeClassifier classifier("haarcascade_frontalface_default.xml");
    // Cascade classifier class for object detection.
 
    if (classifier.empty()) {
        cerr << "Classifier load failed." << endl;
 
        return -1;
    }
 
    vector<Rect> faces;
    classifier.detectMultiScale(src, faces);
    // Detects objects of different sizes in the input image.
    // The detected objects are returned as a list of rectangles.
 
    for (Rect rect : faces) {
        rectangle(src, rect, Scalar(00255), 2);
    }
 
    imshow("Face Detection", src);
 
    waitKey(0);
 
    return 0;
}



Run the program and see the result.


Detected two babies' faces.


It couldn't detect a face with shades and detected some wrong objects.


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

It shows how to detect and decode a QR Code.

OpenCV에서 QR코드를 감지하고 내용을 확인할 수 있다.


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
#include <Windows.h>
#include <opencv2/opencv.hpp>
 
using namespace std;
using namespace cv;
 
int main()
{
    VideoCapture cap(0);
 
    if (!cap.isOpened()) {
        cerr << "Camera open failed." << endl;
 
        return -1;
    }
 
    QRCodeDetector detector;
 
    Mat frame;
    vector<Point> points;
    String msg;
 
    while (true) {
        cap >> frame;
 
        if (frame.empty()) {
            cerr << "Empty frame." << endl;
 
            break;
        }
 
        msg = detector.detectAndDecode(frame, points); // Both detects and decodes QR code.
 
        if (!msg.empty()) {
            polylines(frame, points, true, Scalar(00255), 2);
            putText(frame, msg, Point(1030), FONT_HERSHEY_PLAIN, 2, Scalar(00255), 2);
 
            if (msg.substr(04== "http") {
                imshow("QR Code", frame);
 
                if (MessageBox(NULL, (msg + " is a website address.\nDo you want to visit?").c_str(), "QR Code", MB_YESNO) == IDYES) {
                    ShellExecute(NULL"open", msg.c_str(), NULLNULL, SW_SHOW);
                    // Performs an operation on a specified file.
                }
                else {
                    continue;
                }
            }
        }
        else {
            putText(frame, "No QR code detected", Point(1030), FONT_HERSHEY_PLAIN, 2, Scalar(00255), 2);
        }
 
        imshow("QR Code", frame);
 
        if (waitKey(10== 27)
            break;
    }
 
    return 0;
}



Run the program. It says 'No QR code detected' at first.


QR code with a message.


QR code with a website address.


If the first 4 letters of the message are 'http', it opens the website with the default web browser.



반응형
Posted by J-sean
:

Rotation 회전

OpenGL 2019. 12. 13. 14:43 |
반응형

It describes how to rotate objects.

OpenGL에서 오브젝트 회전 하기.


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
#include <gl/glut.h>
 
GLfloat angle = 0.0f;
 
void MyDisplay();
void MyTimer(int value);
 
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutCreateWindow("OpenGL Rotation");
 
    glutDisplayFunc(MyDisplay);
    glutTimerFunc(20, MyTimer, 1);
 
    glutMainLoop();
 
    return 0;
}
 
void MyDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 1st teapot, right, CCW
    glPushMatrix();
    glRotatef(45.0f1.0f0.0f0.0f);    // 45 degrees rotation around X-Axis to see the direction of the rotation.
    glTranslatef(0.5f0.0f0.0f);        // Changing the order of calling this Translate()..
    glRotatef(angle, 0.0f1.0f0.0f);    // and this Rotate() will affect how it spins. (rotation and revolution)
    glutWireTeapot(0.3);
    glPopMatrix();
    
    // 2nd teapot, left, CW
    glPushMatrix();
    // glPushMatrix pushes the current matrix stack down by one, duplicating the current matrix. That is, after a
    // glPushMatrix call, the matrix on top of the stack is identical to the one below it.
    glRotatef(45.0f1.0f0.0f0.0f);
    glTranslatef(-0.5f0.0f0.0f);
    glRotatef(-angle, 0.0f1.0f0.0f);
    glutWireTeapot(0.3);
    glPopMatrix();
    //glPopMatrix pops the current matrix stack, replacing the current matrix with the one below it on the stack.
 
    glutSwapBuffers();
}
 
void MyTimer(int value)
{
    angle += 1.0f;
    if (angle >= 360.0f) {
        angle = 0.0f;
    }
 
    glutPostRedisplay();
    glutTimerFunc(20, MyTimer, 1);
}



Run the program and see the directions of each rotation.


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

It describes how to keep the aspect ratio.

OpenGL에서 종횡비를 유지하기 위해서는 Viewport와 Projection의 비율을 같게 해야 한다.


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
#include <gl/glut.h>
 
const int InitWidth = 300;
const int InitHeight = 300;
 
void MyDisplay();
void MyReshape(int NewWidth, int NewHeight);
 
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
 
    glutInitDisplayMode(GLUT_RGB);
    glutInitWindowSize(InitWidth, InitHeight);
    glClearColor(0.0f0.0f0.0f0.0f);
    glutCreateWindow("OpenGL Aspect Ratio");
    
    glutReshapeFunc(MyReshape);
    // glutReshapeFunc sets the reshape callback for the current window.
    glutDisplayFunc(MyDisplay);
    
    glutMainLoop();
 
    return 0;
}
 
void MyDisplay() {
    glClear(GL_COLOR_BUFFER_BIT);
 
    glBegin(GL_TRIANGLES);
    glColor3f(0.0f0.0f1.0f);
    glVertex3f(0.0f0.5f0.0f);
    glColor3f(1.0f0.0f0.0f);
    glVertex3f(-0.5f-0.5f0.0f);
    glColor3f(0.0f1.0f0.0f);
    glVertex3f(0.5f-0.5f0.0f);
    glEnd();
 
    glFlush();
}
 
void MyReshape(int NewWidth, int NewHeight)
{
    glViewport(00, NewWidth, NewHeight);
    // glViewport specifies the affine transformation of x and y from normalized device coordinates to window coordinates.
 
    GLfloat WidthFactor = (GLfloat)NewWidth / (GLfloat)InitWidth;
    GLfloat HeightFactor = (GLfloat)NewHeight / (GLfloat)InitHeight;
    
    glMatrixMode(GL_PROJECTION);    // glMatrixMode sets the current matrix mode.
    glLoadIdentity();    // glLoadIdentity replaces the current matrix with the identity matrix.
    glOrtho(-1.0 * WidthFactor, 1.0 * WidthFactor, -1.0 * HeightFactor, 1.0 * HeightFactor, -1.01.0);
    // glOrtho describes a transformation that produces a parallel projection.
}



Run the program.


Resize the window.


Resize the window.


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

초등학교 시절이었나? 그때쯤 크리스마스 트리를 두어 번 만들어 보고 그 이후로는 한 번도 만들어 본적이 없는거 같다. 어차피 크리스마스가 내게 의미 있는 날도 아니고, 선물을 주고 받거나 뭔가 의미 있는걸 하는 사람은 영화에만 존재했으니 별 상관 없었던거 같다. 어쩌면 우리 가족의 그런 분위기가 날 그렇게 생각하게 만들었을지도 모른다는 생각도 든다.



그러다 몇년 전 부터 연말쯤 되면 크리스마스 트리가 생각나곤 했다. 거실에 두고 온 가족이 볼 만큼 큰거 말고 그냥 내방 구석에 한 자리 잡고 연말을 같이 보낼 작고 귀여운 트리.


올해는 무슨 생각이었는지 바로 검색을 시작 했다. 생각보다 많은 종류의 트리와 장식, 전구들.. 사실 이젠 더 이상 전구가 아닌거 같다. 대부분 LED를 이용한 저전력, 저발열의 제품들이 많이 나와 있었다. 분명 내 기억엔 시간이 지나면 뜨거워 지는 작은 전구들이었는데.. 어쨌든 맘에 드는걸 하나 발견 했고 주문 했다.


높이가 60cm 라고 했으니 그쯤 되는 상자에 담겨 온 듯 하다.


나뭇가지들은 모두 위로 말려있고 장식과 전구는 따로 포장, 지지대 3개는 분리된채 상자에 들어 있었다. 별거 없어 보이지만 있어야 할 건 다 있었다.



사방에서 보는걸 감안하고 장식을 달면 부족할거 같아 한쪽 방향에서만 볼 수 있게 트리를 배치하기로 하고 장식들을 한쪽으로 적당히 몰아 주었다. 졸려서 전구도 대충 빨리 감아주고 USB를 컴퓨터에 연결 했다. 가정용 220V 전원을 사용하는게 아닌 컴퓨터 USB 포트에서 작동 한다. 컴퓨터용 USB포트는 보통 500mA정도의 전류가 나오는데 충분한가 보다.


불을 껐다. 생각보다 굉장히 밝은 전구에 살짝 당황했다.


이런건 역시 동영상으로 확인해야 제대로 알 수 있다. 한밤중에 갑자기 만든 크리스마스 트리라 신경써서 장식을 배치하고 예쁘게 전구를 감지는 못했지만 꽤 괜찮은 모양이 나온다.


저렴한 가격에 간단한 장식부터 전구까지 모두 포함이면 나쁘지 않은 선택 이었던거 같다. 더 싸고 좋은게 있을지 모르겠지만, 사실 잘산거 같다고 생각하는 중이다.


정말 오랜만에 만들어본 크리스마스 트리. 나중에 유튜브 영상 찍을때 배경으로 사용할 생각부터 드는 난 이제 진정한 유튜버.


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

프로그래머도 아니면서 사람들의 관심이 거의 없는 프로그래밍이라는 주제로 블로그를 시작하고 꽤나 오랜 시간이 지나 구글 애드센스 승인까지 받았다. 음식, 패션 등의 주제로 시작했다면 더 빨리 받았을텐데.. 역시 주제를 잘 잡아야 한다.


확인 기준액이라는 $10를 넘어 PIN 번호를 요청하고 기다림..

4주를 기다렸지만 안온다.


다시 요청, 4주 기다림..

안온다.


주소를 바꾸면 될까 해서 회사 주소로 바꾸고 다시 요청, 4주 기다림..

안온다.



이젠 블로그에서 광고가 중단되었고 짜증이 밀려 왔다.

그냥 이메일로 보내주던가.. 대체 왜 느리고 오지도 않는 우편을 보내는 건지..


결국 PIN이 오지 않으면 어떻게 해야하는지 검색해보고 필요한 서류를 알아 두었다.

신분증 사본, 은행 입출금 내역서.. 아.. 귀찮네..


이것 때문에 연차까지 내서 은행을 가야 하나? 라는 생각이 들었고 언제 한 번 시간내서 갔다 와야지.. 하던 중 회사 우편물 사이에 뭔가 심상치 않은 엽서 같은걸 발견!!



드디어 받았다. 애드센스 PIN 번호.

아마 회사 주소로 바꾸고 나서야 제대로 도착한거 같은데.. 대체 왜 집주소로는 2번이나 오지 않았던건지 알 수가 없다.

나중에 유튜브 실버 버튼도 집으로는 안오는거 아닐까? 하는 너무 성급한 걱정이 들기 시작했다.



뭐 어쨌든.. 편지를 열어 PIN 번호를 확인하고 입력했다.



PIN 번호 확인이 안되었다는 메세지가 사라지고 다시 광고가 나오기 시작했다.

일주일 넘게 광고가 중단되었던 바람에 가뜩이나 클릭도 없는 블로그 수익은 바닥을 치고..



확인해 보니 대부분의 글들이 광고가 제대로 표시 되지 않는다.. 그냥 빈 공간으로 표시.. 후..



글 수정을 누르고 다시 저장을 하면 제대로 광고가 표시 되기도 하고.. 어떤 글은 또 안되기도 하고..

검색해 보니 이런 문제를 겪는 사람들이 꽤 있는 듯.. 블로그 스킨에 문제가 있는 건지, 아니면 다른 뭔가 문제가 있는건지 대체 알 수 가 없다.


하여간 맘에 안드는 구글 애드센스다.


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

It describes how to use the touch API in Android applications.


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
public class MainActivity extends AppCompatActivity {
 
    int[] id = new int[3];
    int[] x = new int[3];
    int[] y = new int[3];
    String result;
 
    TextView textView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textView = findViewById(R.id.textView);
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent event) {
 
        // 3개의 포인터(터치)까지 허용
        int pointer_count = event.getPointerCount();
        if (pointer_count > 3)
            pointer_count = 3;
 
        // ACTION_POINTER_DOWN 과 ACTION_POINTER_UP 이벤트는 액션 값에 추가적인 정보가 인코딩 되어 있다.
        // 액션 값과 MotionEvent.ACTION_POINTER_INDEX_MASK를 & 연산을 하게 되면 눌리거나 떼어진 포인터의 인덱스 값을 알 수 있다.
        // public static final int ACTION_POINTER_INDEX_MASK
        // Bits in the action code that represent a pointer index, used with ACTION_POINTER_DOWN and ACTION_POINTER_UP.
        switch (event.getAction() & MotionEvent.ACTION_MASK)
        {
            case MotionEvent.ACTION_DOWN:
                result = "Single Touch Down:";
                id[0= event.getPointerId(0);
                x[0= (int)event.getX(0);
                y[0= (int)event.getY(0);
                result += "\n(" + x[0+ ", " + y[0+ ")";
                break;
 
            case MotionEvent.ACTION_POINTER_DOWN:
                result = "Multi Touch Down:";
                for (int i = 0; i < pointer_count; i++)
                {
                    id[i] = event.getPointerId(i);
                    x[i] = (int)event.getX(i);
                    y[i] = (int)event.getY(i);
                    result += "\n(" + id[i] + ": " + x[i] + ", " + y[i] + ")";
                }
 
                // Move는 싱글, 멀티 모두 ACTION_MOVE 하나로 처리
            case MotionEvent.ACTION_MOVE:
                result = "Touch Move:";
                for (int i = 0; i < pointer_count; i++)
                {
                    id[i] = event.getPointerId(i);
                    x[i] = (int)event.getX(i);
                    y[i] = (int)event.getY(i);
                    result += "\n(" + id[i] + ": " + x[i] + ", " + y[i] + ")";
                }
                break;
 
            case MotionEvent.ACTION_UP:
                result = "Single Touch Up:";
                id[0= event.getPointerId(0);
                x[0= (int)event.getX(0);
                y[0= (int)event.getY(0);
                result += "\n(" + x[0+ ", " + y[0+ ")";
                break;
 
            case MotionEvent.ACTION_POINTER_UP:
                result = "Multi Touch Up:";
                for (int i = 0; i < pointer_count; i++)
                {
                    id[i] = event.getPointerId(i);
                    x[i] = (int) event.getX(i);
                    y[i] = (int) event.getY(i);
                    result += "\n(" + id[i] + ": " + x[i] + ", " + y[i] + ")";
                }
                break;
 
            default:
                break;
        }
 
        textView.setText(result);
 
        return super.onTouchEvent(event);
    }
}



Run the app and touch the panel.


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

It describes how to use the touch API in Android applications.


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
public class MainActivity extends AppCompatActivity {
 
    int x, y;
    TextView textView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        x = -1;
        y = -1;
        textView = findViewById(R.id.textView);
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent event) {
 
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                x = Math.round(event.getX());
                y = Math.round(event.getY());
                textView.setText("Down position: " + x + ", " + y);
                break;
 
            case MotionEvent.ACTION_MOVE:
                x = Math.round(event.getX());
                y = Math.round(event.getY());
                textView.setText("Move position: " + x + ", " + y);
                break;
 
            case MotionEvent.ACTION_UP:
                x = Math.round(event.getX());
                y = Math.round(event.getY());
                textView.setText("Up position: " + x + ", " + y);
                break;
 
            default:
                break;
        }
 
        return super.onTouchEvent(event);
    }



Run the app and touch the panel.


반응형
Posted by J-sean
: