실전 응용
해골과 반 합성
import cv2
import numpy as np
# 영상의 15%를 알파 블렌딩의 범위로 지정
alpha_width_rate = 15
# 합성할 두 영상 읽기
img_face = cv2.imread('./img/man_face.jpg')
img_skull = cv2.imread('./img/skull.jpg')
# 입력 영상과 같은 크기의 결과 영상 준비
img_comp = np.zeros_like(img_face)
# 연산에 필요한 좌표 계산
height, width = img_face.shape[:2]
middle = width//2
alpha_width = width * alpha_width_rate // 100
start = middle - alpha_width//2
step = 100/alpha_width
# 입력 영상의 절반씩 복사해서 결과 영상에 합성
img_comp[:, :middle, : ] = img_face[:, :middle, :].copy()
img_comp[:, middle:, : ] = img_skull[:, middle:, :].copy()
cv2.imshow('half', img_comp)
# 알파 값을 바꾸면서 알파 블렌딩 적용
for i in range(alpha_width+1 ):
alpha = (100 - step * i) / 100 # 증감 간격에 따른 알파 값(1~0)
beta = 1 - alpha # 베타값(0~1)
# 알파 블렌딩 적용
img_comp[:, start+i] = img_face[:, start + i] * alpha + img_skull[:, start+i] * beta
print(i, alpha, beta)
cv2.imshow('half skull', img_comp)
cv2.waitKey()
cv2.destroyAllWindows()
0 1.0 0.0
1 0.9895833333333333 0.01041666666666674
2 0.9791666666666667 0.02083333333333326
3 0.96875 0.03125
4 0.9583333333333333 0.04166666666666674
5 0.9479166666666667 0.05208333333333326
6 0.9375 0.0625
7 0.9270833333333333 0.07291666666666674
8 0.9166666666666667 0.08333333333333326
9 0.90625 0.09375
10 0.8958333333333333 0.10416666666666674
11 0.8854166666666667 0.11458333333333326
12 0.875 0.125
13 0.8645833333333333 0.13541666666666674
14 0.8541666666666667 0.14583333333333326
15 0.84375 0.15625
16 0.8333333333333333 0.16666666666666674
17 0.8229166666666665 0.17708333333333348
18 0.8125 0.1875
19 0.8020833333333333 0.19791666666666674
20 0.7916666666666665 0.20833333333333348
21 0.78125 0.21875
22 0.7708333333333333 0.22916666666666674
23 0.7604166666666665 0.23958333333333348
24 0.75 0.25
25 0.7395833333333333 0.26041666666666674
26 0.7291666666666665 0.2708333333333335
27 0.71875 0.28125
28 0.7083333333333333 0.29166666666666674
29 0.6979166666666665 0.3020833333333335
30 0.6875 0.3125
31 0.6770833333333333 0.32291666666666674
32 0.6666666666666665 0.3333333333333335
33 0.65625 0.34375
34 0.6458333333333333 0.35416666666666674
35 0.6354166666666666 0.36458333333333337
36 0.625 0.375
37 0.6145833333333333 0.38541666666666674
38 0.6041666666666666 0.39583333333333337
39 0.59375 0.40625
40 0.5833333333333333 0.41666666666666674
41 0.5729166666666666 0.42708333333333337
42 0.5625 0.4375
43 0.5520833333333333 0.44791666666666674
44 0.5416666666666666 0.45833333333333337
45 0.53125 0.46875
46 0.5208333333333333 0.47916666666666674
47 0.5104166666666666 0.48958333333333337
48 0.5 0.5
49 0.48958333333333326 0.5104166666666667
50 0.47916666666666663 0.5208333333333334
51 0.46874999999999994 0.53125
52 0.45833333333333326 0.5416666666666667
53 0.44791666666666663 0.5520833333333334
54 0.43749999999999994 0.5625
55 0.42708333333333326 0.5729166666666667
56 0.41666666666666663 0.5833333333333334
57 0.40624999999999994 0.59375
58 0.39583333333333326 0.6041666666666667
59 0.38541666666666663 0.6145833333333334
60 0.37499999999999994 0.625
61 0.36458333333333326 0.6354166666666667
62 0.3541666666666666 0.6458333333333335
63 0.34375 0.65625
64 0.33333333333333326 0.6666666666666667
65 0.3229166666666666 0.6770833333333335
66 0.3125 0.6875
67 0.30208333333333326 0.6979166666666667
68 0.2916666666666666 0.7083333333333335
69 0.28125 0.71875
70 0.27083333333333326 0.7291666666666667
71 0.2604166666666666 0.7395833333333335
72 0.25 0.75
73 0.2395833333333333 0.7604166666666667
74 0.22916666666666657 0.7708333333333335
75 0.21875 0.78125
76 0.2083333333333333 0.7916666666666667
77 0.19791666666666657 0.8020833333333335
78 0.1875 0.8125
79 0.1770833333333333 0.8229166666666667
80 0.16666666666666657 0.8333333333333335
81 0.15625 0.84375
82 0.1458333333333333 0.8541666666666667
83 0.13541666666666657 0.8645833333333335
84 0.125 0.875
85 0.11458333333333329 0.8854166666666667
86 0.10416666666666657 0.8958333333333335
87 0.09375 0.90625
88 0.08333333333333329 0.9166666666666667
89 0.07291666666666657 0.9270833333333335
90 0.0625 0.9375
91 0.05208333333333329 0.9479166666666667
92 0.041666666666666574 0.9583333333333335
93 0.03125 0.96875
94 0.020833333333333287 0.9791666666666667
95 0.010416666666666572 0.9895833333333335
96 0.0 1.0
모션 감지
import cv2
import numpy as np
# 감도 설정(카메라 품질에 따라 조정 필요)
thresh = 25 # 달라진 픽셀값 기준치 설정
max_diff = 5 # 달라진 픽셀 개 기준치 설정
# 카메라 캡션 장치 준비
a, b, c = None, None, None
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480) # 프레임 폭을 480으로 설정
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 320) # 프레임 높이를 320으로 설정
if cap.isOpened():
ret, a = cap.read() # a프레임 읽기
ret, b = cap.read() # b프레임 읽기
while ret:
ret, c = cap.read() # c프레임 읽기
draw = c.copy() # 출력 영상에 사용할 복제본
if not ret:
break
# 3개의 영상을 그레이 스케일로 변경
a_gray = cv2.cvtColor(a, cv2.COLOR_BGR2GRAY)
b_gray = cv2.cvtColor(b, cv2.COLOR_BGR2GRAY)
c_gray = cv2.cvtColor(c, cv2.COLOR_BGR2GRAY)
# a-b, b-a 절대값 차 구하기
diff1 = cv2.absdiff(a_gray, b_gray)
diff2 = cv2.absdiff(b_gray, c_gray)
# 스레시홀드로 기준치 이내의 차이는 무시
ret, diff1_t = cv2.threshold(diff1, thresh, 255, cv2.THRESH_BINARY)
ret, diff2_t = cv2.threshold(diff2, thresh, 255, cv2.THRESH_BINARY)
# 두 차이에 대해서 AND연산, 두 영상의 차이가 모두 발견된 경우
diff = cv2.bitwise_and(diff1_t, diff2_t)
# 열림 연산으로 노이즈 제거
k = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))
diff = cv2.morphologyEx(diff, cv2.MORPH_OPEN, k)
# 차이가 발생한 픽셀이 개수 판단 후 사각형 그리기
diff_cnt = cv2.countNonZero(diff)
if diff_cnt > max_diff:
nzero = np.nonzero(diff) # 0이 아닌 픽셀의 좌표 얻기
cv2. rectangle(draw, (min(nzero[1]), min(nzero[0])),
(max(nzero[1]), max(nzero[0])), (0,255,0),2)
cv2.putText(draw, "Motion Detected", (10, 30),
cv2.FONT_HERSHEY_DUPLEX, 0.5, (0,0,255))
# 컬러 스케일 영상과 스레시 홀드 영상을 통합해서 출력
stacked = np.hstack((draw, cv2.cvtColor(diff, cv2.COLOR_GRAY2BGR)))
cv2.imshow('motion sensor', stacked)
# 다음 비교를 위해 영상 순서 정리
a = b
b = c
if cv2.waitKey(1) & 0xFF ==27:
break