8. 인식 과정 - 음표(꼬리)
기둥은 객체 분석 과정에서 검출해낸 것이 있으니 따로 하지 않아도 됩니다.
애초에 직선 성분이 있는 객체만 음표로 가정하여 인식하는 것이기도 하구요.
# recognition_modules.py
import functions as fs
import cv2
def recognize_note(image, staff, stats, stems, direction):
(x, y, w, h, area) = stats
notes = []
pitches = []
note_condition = (
len(stems) and
w >= fs.weighted(10) and # 넓이 조건
h >= fs.weighted(35) and # 높이 조건
area >= fs.weighted(95) # 픽셀 갯수 조건
)
if note_condition:
for i in range(len(stems)):
stem = stems[i]
head_exist, head_fill, head_center = recognize_note_head(image, stem, direction)
if head_exist:
recognize_note_tail(image, i, stem, direction)
pass
이전 챕터에서 머리 인식 알고리즘 함수를 구현하였습니다.
반환 값은 각각 머리 존재 여부, 머리가 채워져 있는지를 담은 Boolean 값, 머리의 중심 y 좌표입니다.
머리가 존재하지 않으면 꼬리도 탐색할 필요가 없습니다.
머리가 존재하는 객체들에 한하여 꼬리를 탐색하는 함수를 호출하도록 하겠습니다.
index 값인 i를 파라미터로 넘겨주는 이유는
둘 이상의 음표가 빔으로 연결되어있는 경우 때문인데, 빔으로 연결된 음표는
두 번째 음표부터 꼬리를 찾기 위해선 왼쪽을 탐색해야 한다는 특징이 있습니다.
recognition_modules.py에 recognize_note_tail 함수를 정의하겠습니다.
음표 꼬리 부분을 탐색하는 함수입니다.
# recognition_modules.py
import functions as fs
import cv2
def recognize_note_tail(image, index, stem, direction):
(x, y, w, h) = stem
if direction: # 정 방향 음표
area_top = y # 음표 꼬리를 탐색할 위치 (상단)
area_bot = y + h - fs.weighted(15) # 음표 꼬리를 탐색할 위치 (하단)
else: # 역 방향 음표
area_top = y + fs.weighted(15) # 음표 꼬리를 탐색할 위치 (상단)
area_bot = y + h # 음표 꼬리를 탐색할 위치 (하단)
if index:
area_col = x - fs.weighted(4) # 음표 꼬리를 탐색할 위치 (열)
else:
area_col = x + w + fs.weighted(4) # 음표 꼬리를 탐색할 위치 (열)
pass
특징점으로는 특정 열을 따라가며 픽셀이 존재하는 부분이 몇 번 등장하는지 카운트하여
꼬리 개수를 세볼 예정입니다.
# recognition_modules.py
import functions as fs
import cv2
def recognize_note_tail(image, index, stem, direction):
(x, y, w, h) = stem
if direction: # 정 방향 음표
area_top = y # 음표 꼬리를 탐색할 위치 (상단)
area_bot = y + h - fs.weighted(10) # 음표 꼬리를 탐색할 위치 (하단)
area_left = x + w # 음표 꼬리를 탐색할 위치 (좌측)
area_right = x + w + fs.weighted(10) # 음표 꼬리를 탐색할 위치 (우측)
else: # 역 방향 음표
area_top = y + fs.weighted(10) # 음표 꼬리를 탐색할 위치 (상단)
area_bot = y + h # 음표 꼬리를 탐색할 위치 (하단)
area_left = x + w # 음표 꼬리를 탐색할 위치 (좌측)
area_right = x + w + fs.weighted(10) # 음표 꼬리를 탐색할 위치 (우측)
if index:
area_col = x - fs.weighted(3) # 음표 꼬리를 탐색할 위치 (열)
else:
area_col = x + w + fs.weighted(3) # 음표 꼬리를 탐색할 위치 (열)
cnt = 0
flag = False
for row in range(area_top, area_bot):
if not flag and image[row][area_col] == 255:
flag = True
cnt += 1
elif flag and image[row][area_col] == 0:
flag = False
fs.put_text(image, cnt, (x - fs.weighted(10), y + h + fs.weighted(20)))
pass
픽셀이 존재하면 flag를 True로 바꾸고 cnt를 1 증가 시킨 뒤
픽셀이 존재하지 않는 부분이 나올 때까지 탐색을 지속합니다.
픽셀이 나오지 않고 flag가 True인 상태라면 flag를 False로 바꿉니다.
다시 픽셀이 탐색 되고 flag가 False인 상태라면 flag를 True로 바꾸고 cnt를 1 증가 시킵니다.
잘 작동하는 것을 확인할 수 있습니다.
픽셀이 존재하는 부분이 몇번 등장하는지 탐색하는 부분은 functions.py에 함수로 만들어 놓겠습니다.
# functions.py
import cv2
import numpy as np
def count_pixels_part(image, area_top, area_bot, area_col):
cnt = 0
flag = False
for row in range(area_top, area_bot):
if not flag and image[row][area_col] == 255:
flag = True
cnt += 1
elif flag and image[row][area_col] == 0:
flag = False
return cnt
# recognition_modules.py
import functions as fs
import cv2
def recognize_note_tail(image, index, stem, direction):
(x, y, w, h) = stem
if direction: # 정 방향 음표
area_top = y # 음표 꼬리를 탐색할 위치 (상단)
area_bot = y + h - fs.weighted(15) # 음표 꼬리를 탐색할 위치 (하단)
else: # 역 방향 음표
area_top = y + fs.weighted(15) # 음표 꼬리를 탐색할 위치 (상단)
area_bot = y + h # 음표 꼬리를 탐색할 위치 (하단)
if index:
area_col = x - fs.weighted(4) # 음표 꼬리를 탐색할 위치 (열)
else:
area_col = x + w + fs.weighted(4) # 음표 꼬리를 탐색할 위치 (열)
cnt = fs.count_pixels_part(image, area_top, area_bot, area_col)
return cnt
# recognition_modules.py
import functions as fs
import cv2
def recognize_note(image, staff, stats, stems, direction):
(x, y, w, h, area) = stats
notes = []
pitches = []
note_condition = (
len(stems) and
w >= fs.weighted(10) and # 넓이 조건
h >= fs.weighted(35) and # 높이 조건
area >= fs.weighted(95) # 픽셀 갯수 조건
)
if note_condition:
for i in range(len(stems)):
stem = stems[i]
head_exist, head_fill, head_center = recognize_note_head(image, stem, direction)
if head_exist:
tail_cnt = recognize_note_tail(image, i, stem, direction)
pass
다음 챕터에서는 점음표인지 탐색하는 알고리즘을 짜도록 하겠습니다.
'인공지능 > 컴퓨터비전' 카테고리의 다른 글
[OpenCV/Python] 악보 인식(디지털 악보 인식) - 10 (0) | 2021.08.07 |
---|---|
[OpenCV/Python] 악보 인식(디지털 악보 인식) - 9 (0) | 2021.08.06 |
[OpenCV/Python] 악보 인식(디지털 악보 인식) - 7 (6) | 2021.08.06 |
[OpenCV/Python] 악보 인식(디지털 악보 인식) - 6 (2) | 2021.08.05 |
[OpenCV/Python] 악보 인식(디지털 악보 인식) - 5 (0) | 2021.08.05 |
댓글