구현 - CCTV 알고리즘


1. 구현 환경


- H/W : Raspberry Pi 2와 Pi camera

- Library : opencv 2 using C



2. 소스 코드


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
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
 
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
 
#include <opencv2/core/core_c.h>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/highgui/highgui_c.h>
 
#define CAM_WIDTH 640
#define CAM_HEIGHT 480
 
 
int main(int argc, char** argv)
{
    int value1, value2, value3;
    int flag = 0;
    int cnt = 0;
 
    time_t curr_t, passed_t;
    double diff_t;
 
    CvCapture* capture;        //variable for camera
    IplImage *curr, *prev;        //variable for image
 
 
    //choose a camera for capturing
    capture = cvCaptureFromCAM(0);
    if(capture == 0){
        perror("Opencv : open Webcam\n");
     return -1;
    }
 
 
    //setting properties of capture image
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, CAM_WIDTH);
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, CAM_HEIGHT);
 
    curr = cvQueryFrame(capture);
    prev = cvCreateImage(cvGetSize(curr),8,3);
    cvCopy(curr, prev);
 
 
    while(1){
    curr = cvQueryFrame(capture);
 
        for (int x = 0; x < curr->height; x++){    //calculating difference between two images
            for (int y = 0; y < curr->width; y++){
                value1 = abs((curr->imageData[x*curr->widthStep + 3 * y + 0]) - (prev->imageData[x*prev->widthStep + 3 * y + 0]));
                value2 = abs((curr->imageData[x*curr->widthStep + 3 * y + 1]) - (prev->imageData[x*prev->widthStep + 3 * y + 1]));
                value3 = abs((curr->imageData[x*curr->widthStep + 3 * y + 2]) - (prev->imageData[x*prev->widthStep + 3 * y + 2]));
 
                //r,g,b values of prev and curr image aren't different, cnt is increased
                if(value1>50 && value2>50 && value3>50){
                    cnt++;
                }
 
            }
        }
    //if the number of different pixels are less than 200, we think there is no difference between prev and curr image
        if (cnt<50){
            if(flag == 0){    //At first, check the time
                time(&curr_t);
                flag = 1;
            }
            else{        //still there is no difference, check the elapsed time
                time(&passed_t);
                diff_t = difftime(passed_t, curr_t);
 
                //checking elapsed time
                if(diff_t>=10){
                    printf("there is no difference\n");
                    printf(ctime(&curr_t));
                    diff_t=0;
                     //save .avi file
 
 
                }
             }//end of else
             cnt =0;
        }//end of first if
        else{
            flag=0;
            cnt=0;
            printf("there is difference! \n");
         }
     
 
        cvShowImage("current", curr);
        cvShowImage("previous", prev);
 
        cvCopy(curr,prev);
 
        if(cvWaitKey(10)== 'p')
            break;
        //cvWaitKey(100);
    }//end of while(1)
 
    cvReleaseCapture(&capture);
    cvReleaseImage(&curr);
    cvReleaseImage(&prev);
 
    return 0;
}

cs


- 위 코드의 주 기능

=> 이전 캡쳐 화면과 현재 화면의 픽셀 RGB 값 비교 ( RGB는 3채널로 구성되어 있으므로 widthStep 사용해야함)

=> 경과 시간 체크( 설정 시간(현재는 10초, 설계상 6시간) 동안 변화가 감지되지 않을 경우, "there is no difference\n" 출력)

=> 설정 시간을 초과해 알림을 띄우는 중에 변화를 감지하면 알림을 멈추는 지 test( "there is difference\n" 출력)



3. 유의할 점


- 라즈베리파이는 데비안 계열의 OS인 라즈비안을 쓴다. 따라서 진짜 진짜 기본적인 리눅스 명령어는 알아야 한다.


- pi camera는 USB가 아닌 CSI 타입으로 하드웨어를 별도로 장착한다고 생각해야 한다. 따라서 pi cam을 사용하려면 아래의 

  명령어를 먼저 실행시켜 줘야 한다.

     < modprobe bcm2835-v4l2 > 

  만약, 위 명령어를 실행하지 않고 위의 소스코드를 실행하면 카메라를 찾을 수 없어 "Open webcam"이 출력될 것이다.


- Opencv 라이브러리를 포함하는 소스코드를 컴파일 할 때 붙여줘야하는 명령어

<`pkg-config --cflags --libs opencv`>


- 화면 비교를 위해 이전 화면을 유지해야 하기 위해서 while문 어디에 위치시켜야 할 지 혼란스러웠는데 여러 소스를 보다가 cvCopy를 

  while문 하단에 놓은 걸 보고 해결했었던게 기억에 남는다. 이렇게 하면 쉬운걸..!!!!!!하고...허허





신고
  1. ehdchdltm 2017.03.29 19:48 신고

    안녕하세요.
    졸업작품 진행 도중 검색을 하다가 방문하게 되었습니다.
    목적과 내용이 저희 팀이 생각했던 부분과 매우 흡사하여 혹시 여쭤볼 것이 몇 가지 있는데 따로 연락처를 받을 수 있을까요?

    • HJ_Reden 2017.03.29 19:50 신고

      hjung4337@gmail.com이요ㅎㅎ 제가 도움이 될까 싶은데요ㅠㅠ

  2. ehdchdltm 2017.03.29 20:05 신고

    네 방금 보내주신 메일로 저희가 작성한 프로젝트 계획서 보내드렸는데 제가 궁금한 부분이라던지 모르는 부분이 많아서 조언을 구하고 싶습니다.

설계


1. 시스템 구성도


* 독거노인의 집의 크기를 방 한 칸 정도로 가정한다. 

1. Raspberry pi 2와 pi camera를 이용하여 CCTV 시스템을 구성한다.

2. 독거 노인의 생활이 주로 이루어지는 이불 앞, TV 앞 등에 구현한 CCTV를 설치한다.

3. 독거노인의 움직임을 모니터링한다.

4. 설정시간 이상 움직임이 감지되지 않을 경우, 관리자(ex) 사회복지사, 자식 등)의 안드로이드 앱으로 알림을 띄운다.

5. 관리자가 독거노인의 상황을 확인하고 문제 발생 시 영상을 확인하여 조치를 취하도록 한다.



2. CCTV 구현 알고리즘





- Difference : 이전화면(n-1)과 현재화면(n)의 픽셀을 비교하여 RGB 각각의 차이가 50이상 나는 픽셀의 개수

=> Difference가 적으면, 화면의 변화가 별로 없는 것이므로, 움직임이 감지되지 않는 것으로 본다.


- difftime(curr_t, passed_t) : 화면 변화가 감지되지 않은 때로부터의 경과 시간
=> curr_t : 화면에 변화가 없기 시작한 시간
=> passed_t : curr_t이 기록된 이후 계속해서 화면 변화가 발생하지 않는 시간










신고

독거노인 관리 시스템 


목적 

- 독거노인의 움직임을 모니터링하여 고독사를 방지하기 위함



* 기능

- 독거 노인의 움직임이 설정 시간동안(약 6시간 - 임의 변경 가능) 감지되지 않을 경우, 관리자의 안드로이드 어플에 알림을 띄워 상황을 알리는 것



* 개발 환경

- Android : 갤럭시 S4(Android ver. 5.0.1 API 23)

- H/W : Raspberry pi2, pi camera

   


- Lib : OpenCV 2





(학교 졸업 과제로 진행했었는데, 정리 겸 다시 해보고 있음)

신고

Audio File(wav.) Plot하기 


1. Audio File plot

->"audio file(wav)의 signal을 python을 이용하여 plot해보자"


  •  필요한 라이브러리

- Numpy : read한 file을 numpy int array로 변경

- Matplotlib : Plot

- Wave : wave file open

- Sys 

- Pydub : audio file의 channel이 mono가 아닌 stereo일 경우, mono로 변경하기 위함




  • 알아두기

      1. Pydub가 ffmpeg 혹은 libav에 Dependencies를 가지므로, 둘 중 하나를 설치하여 환경변수 설정을 꼭 해줘야 함!

      2. Audio Data type

 

              - 보통, 16 bit PCM을 주로 사용하는 듯하다. 

              - 8-bit PCM일 경우, unsigned int형이란 걸 주의하라고 나와있음!




  • 코드

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
import matplotlib.pyplot as plt
import numpy as np
import wave
import sys
from pydub import AudioSegment
 
sound=AudioSegment.from_wav("Car1.wav")
sound=sound.set_channels(1)
sound.export("out_Car1.wav"format="wav")
 
spf = wave.open('out_Car1.wav','r')
 
#Extract Raw Audio from Wav File
signal = spf.readframes(-1)
signal = np.fromstring(signal, dtype=np.int16)
 
 
#If Stereo
if spf.getnchannels() == 2:
    print 'Just mono files'
    sys.exit(0)
 
plt.figure(1)
plt.title('Signal Wave...')
plt.plot(signal)
plt.show()
 
cs




  • 결과



 



2. x-axis Time space로 변경하기

-> " Audio file을 plot 했을 때 x축을 time space(in second)로 변경해보자 "


  •  알아두기

-  x축을 Second로 표시하기 위해서는 Frame rate을 얻어서 signal의 size를 나눠야한다.

=> numpy의 linspace function을 사용!

* linspace() : 동일한 간격으로 떨어진 수를 만들어 내는 함수

-> numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)




  • 코드

1
Time = np.linspace(0,len(signal)/framerate, num=len(signal))
cs




  • 결과




  • 전체 코드


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 matplotlib.pyplot as plt
import numpy as np
import wave
import sys
from pydub import AudioSegment
 
sound=AudioSegment.from_wav("Car1.wav")
sound=sound.set_channels(1)
sound.export("out_Car1.wav"format="wav")
 
spf = wave.open('out_Car1.wav','r')
 
#Extract Raw Audio from Wav File
signal = spf.readframes(-1)
signal = np.fromstring(signal, dtype=np.int16)
framerate = spf.getframerate()
 
#If Stereo
if spf.getnchannels() == 2:
    print 'Just mono files'
    sys.exit(0)
    
Time = np.linspace(0,len(signal)/framerate, num=len(signal))
 
plt.figure(1)
plt.title('Signal Wave...')
plt.plot(Time,signal)
plt.show()
 
cs




신고

'Study_CS > Python' 카테고리의 다른 글

Wav File Plot  (0) 2016.10.29
이스케이프 문자  (0) 2016.10.26

+ Recent posts

티스토리 툴바