일단 DJMAX와 Beat Saber를 선택한 이유는 리듬게임이며 집중도가 높은 게임이기 때문에 선택했다. BeatSaber의 경우 VR를 착용하고 하기 때문에 몰입이 될 수 있어서 집중도를 측정하기에 더 좋았다.
참고로 VR의 경우 VIVE PRO 1을 착용하고 했었다.
일단 영상 찍고 확인을 해보니.. 의외로 집중도가 낮게 나온다..
내가 이전 부터 이 기기를 테스트 하면서도 집중도가 확실히 낮게 나오기는 했었는데.. (ADHD인가..?)
DJMAX에서는 짧은 노트의 경우 집중도가 의외로 낮게 나온다. 그에 반면 긴 노트에서는 집중도가 높게 나왔다..
나도 게임을 클리어 하면서 짧은 노트들은 어느정도 칠 수 있어서 그나마 쉽게 넘어가는 반면 긴 노트의 경우 긴 노트를 눌르며 다른 노트들도 쳐야하다 보니 집중을 많이 하게 되는 것 같은데.. 심지어 지금도 그렇고 이때도 그렇고 장갑을 끼고 있다보니.. 더 키보드 치는 느낌이 잘 안들어서 저렇게 된 것 같다.
뭐 그래도 대부분 높게 나오기는 했다.
(장갑 끼는건 그냥 키보드 더러워질까봐.. 다한증..)
Beat Saber에서는 이상하게 전체적으로 낮게 나왔다..
이건 잘 모르겠다.. 내가 게임을 잘 못하는게 이것 때문인건가.. 하는 생각도 들긴 하는데..
일단 의심되는건.. 내 방이 덥다. 그래서 땀이 많이 나기도 하는데 그것 때문에 전극에 수분 때문에 전기가 잘 통해서 전극이 잘 요동치고 있다는 것을 알 수 있다. 이것 때문일 가능성도 있고.. 또 손을 엄청 움직이고 하기에 그 움직임도 같이 반영됬을 것으로 추정된다.. 또한 VR과 Muse 2를 같이 착용하고 측정하기 때문에 Muse 2가 제대로 측정이 안되었거나 VIVE PRO의 안면 폼이 방해했을 가능성이 있을 수 있다. 그리고 운동을 안해서인지.. FitBeat 하면서 다리를 굽혔다 피니깐.. 이후에 몇시간 동안 일어나거나 앉을려 하면 힘이 빠져서 움직이기도 어려울 정도였다.
그런데 그걸 제외해서라도 집중도가 낮은건 좀 이상하긴 하다.. 아니면 그냥 내가 게임에 집중을 잘 안했던 것일 수도 있고..
그리고 위에서도 말했지만 공통적으로 한가지 문제라면 Muse 2가 민감한건지 뭔지 자세를 움직인다거나 키보드를 친다거나 손을 많이 움직인다거나 이를 쎄게 닫는 경우 뇌파가 심하게 요동친다.. 이것 때문에 뇌파가 제대로 측정이 안되기도 한다. 그래도 모든 전극이 같이 반영되기 때문에 아마도 그에 따라서 바뀌니깐 딱히 상관은 없을 수도 있을 것 같다.
그리고 조금 문제가 생겼다.. 당시에는 EEG를 알아내고 brainflow를 C++로도 사용하고 Python으로도 사용해서 집중도나 이런 거 구하는 거를 했었는데.. 학교를 다니면서 기숙사에서 작업하다 보니 정신이 별로 없던 것 같다.. 2~4주 안에 이 모든 걸 다 했으니..
그렇다 보니 지금 다시 확인해 봤는데 코드가 좀 엉망이다.. 잘못된 정보들이 대부분일 수 있다.
최대한으로 찾아서 해보고 있지만 코드적인 실수가 어디선가 있을 수도 있긴 하다..
참고로 대학교 수업 자료로 쓴 것이기에.. 잘못 정보를 전달했다는 걸 지금 느꼈다..
솔직히 어디서부터 써야 될지 감이 안 잡히긴 하는데.. 어떻게든 적어보겠다..
아무튼 시작!
집중도 구하는 코드 먼저!
from time import sleep
from brainflow.board_shim import BoardShim, BrainFlowInputParams, BoardIds
from brainflow.data_filter import DataFilter, FilterTypes
board_id = BoardIds.MUSE_2_BOARD
params = BrainFlowInputParams()
params.serial_number = "Muse-0465" # Muse 2의 고유 시리얼 넘버
board_shim = BoardShim(board_id, params)
use_data_seconds = 1 # n초 동안 데이터 수집
sampling_rate = BoardShim.get_sampling_rate(board_id)
eeg_channels = BoardShim.get_eeg_channels(board_id)
num_points = use_data_seconds * sampling_rate # 몇 초 동안의 데이터를 가져올지
# Muse 2 연결
board_shim.prepare_session()
# Muse 2 데이터 수집 시작
board_shim.start_stream()
# n초 + 1초 동안 데이터 수집
sleep(use_data_seconds + 1)
# 수집한 데이터를 변수에 저장
data = board_shim.get_current_board_data(num_points)
# 데이터 처리
for count, channel in enumerate(eeg_channels):
DataFilter.perform_bandpass(data[channel], sampling_rate, 2.0, 45.0, 4, FilterTypes.BESSEL_ZERO_PHASE, 0) # 분석할 파형 밖의 범위 제거
DataFilter.perform_bandstop(data[channel], sampling_rate, 48.0, 52.0, 4, FilterTypes.BUTTERWORTH_ZERO_PHASE, 0) # 50Hz의 주변 전기 노이즈 제거
DataFilter.perform_bandstop(data[channel], sampling_rate, 58.0, 62.0, 4, FilterTypes.BUTTERWORTH_ZERO_PHASE, 0) # 60Hz의 주변 전기 노이즈 제거
# 예측에 필요한 데이터 추출
bands = DataFilter.get_avg_band_powers(data, eeg_channels, sampling_rate, False)
feature_vector = bands[0]
# 집중도 예측
print(f"Attention: {feature_vector[3] / feature_vector[2]}") # Beta / Alpha
# Muse 2 데이터 수집 정지
board_shim.stop_stream()
# Muse 2 연결 해제
board_shim.release_session()
이번 코드는 이것이다.
최대한 이해하기 쉽게 하기 위해 이전 코드에서 데이터 처리 부분만 추가해서 작동하도록 했다.
그렇다 보니 코드 설명에선 이전에 한 부분은 제외하고 하겠다..
참고로 저번에 데이터를 확인했기 때문에 여기에선 집중도만 구할 것이기에 데이터를 저장하는 코드는 넣지 않았다.
넣고 싶으면 이전 코드에서 가져와서 넣길..
그리고 이번에는 n초로 주석이 되어있다. 이유라면 집중도를 측정하기 때문에 1초 정도로는 부족한 것 같아서 5초로 했다. 하지만 저건 변경할 수도 있으니 n초로 한 것
코드 설명 전 이해할 것
뇌파로 분석을 할 때 보통 사용되는 특정 주파수의 파형이 있다. (바로 아래 사진)
(바로 아래 사진 말고 그 사진 아래 있는 사진은 한국어로 되어있으니 그걸 먼저 보는 것을 추천합니다.)
그 파형은Delta(델타), Theta(세타), Alpha(알파), Beta(베타), Gamma(감마)인데 위의 Muse 공식 사이트 안에 설명되어 있는 내용 중 사진에서 가져온 걸 보면 된다.
수집된 데이터에서 FFT(고속 푸리에 변환) 방법으로 저렇게 특정 파형을 뽑아낼 수 있다.
각 파형은 각각의 특색이 있다. 그 특색은 사진의 오른쪽에 적혀있다. 그냥 현재 뇌의 상태를 알 수 있는 파형이라 생각하면 된다.
뭐 잠든 건지 깨어있는지 집중도가 강한지 등을 알 수 있게 된다.
아무튼 저런 파형은 적혀있는 대로 Delta(0.5, 4.0), Theta(4.0, 8.0), Alpha(8.0, 13.0), Beta(13.0, 32.0), Gamma(32.0, 100.0) 이런 범위로 되어있다. 저 범위에 있는 걸 추출하면 현재 뇌 상태를 알 수 있다는 의미? 가 된다.
어디서는 0.5에서 델타가 시작하고 어디에서는 3.5에서 시작하고 어디에서는 2로 시작하고 그런다..
암튼 저 범위는 무시하고 그냥 각각 파형에 따라 그 파형이 무슨 역할을 하는지만 이해하면 될 것 같다.
참고로 아래에서 말하겠지만 집중도 구할 때 사용하는 파형은 베타파와 알파파이다.
코드 설명 및 이해하기
use_data_seconds = 1 # n초 동안 데이터 수집
sampling_rate = BoardShim.get_sampling_rate(board_id)
eeg_channels = BoardShim.get_eeg_channels(board_id)
num_points = use_data_seconds * sampling_rate # 몇 초 동안의 데이터를 가져올지
이전 글에서 설명한 코드에 추가적으로 eeg_channels에 대한게 있어서 그것만 추가로 적어보겠다.
지금은 코드를 정상적으로 고쳤는데.. 저기 뒤에 get_avg_band_powers 함수의 뒤에 False인 부분을 처음에는 True로 했었다. True로 하게 되면 저게 Apply Filter인데 바로 위에 데이터 처리 코드 부분을 수행한 뒤에 데이터를 반환해 준다..
즉 지금은 False로 해서 위에서 전처리한 게 소용이 있는데.. True로 하면 전처리를 하고 또 전처리를 하게 되어서 좀 별로다.. 암튼 그럼..
이 코드는 수집된 데이터에서 Delta(델타), Theta(세타), Alpha(알파), Beta(베타), Gamma(감마) 데이터(band_powers)를 뽑아서 그중 평균값만 뽑아 feature_vector에 저장하는 코드이다. (위에 파형에 대한 설명을 적어놓았으니 델타 세타파 저런 게 뭔지 모르겠다면 위에 적은 걸 보시길..)
그리고 feature_vector에는 bands[0]을 저장하는데 위에 적혀있는 것처럼 평균값만 뽑는다.
그럼 bands에 저장되어 있는 다른 건 무엇이냐.. 하면.. get_avg_band_powers가 뭘 리턴하는지 보면 된다.
# 코드 설명을 하기 위한 코드
def get_avg_band_powers(cls, data, channels: List, sampling_rate: int, apply_filter: bool) -> Tuple:
"""calculate avg and stddev of BandPowers across all channels, bands are 1-4,4-8,8-13,13-30,30-50
:param data: 2d array for calculation
:type data: NDArray[Shape["*, *"], Float64]
:param channels: channels - rows of data array which should be used for calculation
:type channels: List
:param sampling_rate: sampling rate
:type sampling_rate: int
:param apply_filter: apply bandpass and bandstop filtrers or not
:type apply_filter: bool
:return: avg and stddev arrays for bandpowers
:rtype: tuple
"""
bands = [(2.0, 4.0), (4.0, 8.0), (8.0, 13.0), (13.0, 30.0), (30.0, 45.0)]
return cls.get_custom_band_powers(data, bands, channels, sampling_rate, apply_filter)
이게 그 함수의 코드이다.
아래 bands에 정의되어 있는 건 Delta, Theta, Alpha, Beta, Gamma 파형의 범위 값이다. 위에서 말했듯이 여기에서 사용하는 파형의 범위도 약간 다르다.
아무튼 코드 보단 주석을 보면 되는데..
주석을 보면 return이 뭐를 반환하는지 적혀있다.
avg는 평균값을 의미하고 stddev는 표준편차를 의미한다. 배열로 2가지 값들을 반환하기 때문에 0번 인덱스인 평균값만 불러오도록 코드를 제작한 것이다.
참고로 분석에는 보통 평균값을 이용하고 데이터의 안전성이나 변동성을 확인할 때는 표준편차를 이용한다 한다.
그리고 리턴되는건 Delta, Theta, Alpha, Beta, Gamma 각각의 평균 값과 표준편차 값이다. 즉 입력된 모든 데이터의 5개 뇌파가 나오는게 아니라 모든 전극 뇌파에서 Delta, Theta, Alpha, Beta, Gamma를 추출하고 그것으로 평균과 표준편차 값을 구해서 반환한 것이다. 그래서 리턴되는 것에서 평균과 표준편차 각각은 5개의 실수가 리스트로 담겨서 리턴된다.
추가적으로 원하는 범위를 사용하여 추출하고 싶으면 저기 return 부분에 적혀있는 것처럼 get_custom_band_powers 이 함수에 원하는 범위를 담은 리스트를 넘겨서 받아내면 된다. (난 잘 모르기에 brainflow에서 사용하는 걸 사용)
추가적으로 위에 왜 함수 사용할 때 False로 해놓았냐에 대한 설명이 있는데.. 그걸 좀 더 자세하게 설명해 보면..
저 apply_filter가 어디에서 사용되는지 따라가 봤다. 따라가 봤는데 DataHandlerDLL의 함수에 사용된다고 한다.. DLL를 본 순간.. 이 brainflow는 C++로 제작된 거니깐 C++ 코드에 있겠다 생각하고 C++ 코드를 찾아보았다..
그리고 찾아냈는데.. 아래 C++ 코드가 있었다.
# 코드 설명을 하기 위한 코드
if (apply_filters)
{
exit_codes[i] = detrend (thread_data, cols, (int)DetrendOperations::CONSTANT);
if (exit_codes[i] == (int)BrainFlowExitCodes::STATUS_OK)
{
exit_codes[i] = perform_bandstop (thread_data, cols, sampling_rate, 48.0, 52.0, 4,
(int)FilterTypes::BUTTERWORTH_ZERO_PHASE, 0.0);
}
if (exit_codes[i] == (int)BrainFlowExitCodes::STATUS_OK)
{
exit_codes[i] = perform_bandstop (thread_data, cols, sampling_rate, 58.0, 62.0, 4,
(int)FilterTypes::BUTTERWORTH_ZERO_PHASE, 0.0);
}
if (exit_codes[i] == (int)BrainFlowExitCodes::STATUS_OK)
{
exit_codes[i] = perform_bandpass (thread_data, cols, sampling_rate, 2.0, 45.0, 4,
(int)FilterTypes::BUTTERWORTH_ZERO_PHASE, 0.0);
}
}
봤을 때 바로 알 수 있을 것이다.. 이 코드 설명 바로 위 코드 설명에 있는 코드하고 닮았다..
즉 apply_filter를 켜게 되면 위에서 했던 데이터 처리 코드가 작동한다는 것..
그 때문에 apply_filter를 켜면 데이터 처리를 했는데 또 처리를 하게 된다는 의미..
뭐 그래도 약간은 달라서 괜찮을지도..?
(근데 함수와 괄호 사이가 왜 띄어져 있는 거지? brainflow 코드 살펴보면서 제일 신경 쓰이는 것..)
원래는 저걸 Attention이라 안 적고 Mindfulness 라 적었는데.. 이유는 다음 글에서 설명할 인공지능으로 집중도 구하는 것과 관련되어 있는데.. 거기에서는 Mindfulness를 사용한다.. 그런데 저 Beta / Alpha 이게.. 집중도를 구하는데 Mindfulness 보단 Attention으로 번역하는 게 더 맞아서 수정했다. 그리고 찾아보니 다음 글에서 할 Mindfulness는 현재의 집중도와 약간 다르긴 하다.. 뭐 딱히 중요하진 않으니 넘어가도 괜찮지 않을까라는.. 생가..ㄱ
암튼 저거 위에서 가져온 feature_vector 변수에는 어쨌든 평균값의 델타 베타 이런 값들이 가져와지게 되는데
거기에서 순서대로 델타부터 해서 해보면..
Delta(델타) : feature_vector[0]
Theta(세타) : feature_vector[1]
Alpha(알파) : feature_vector[2]
Beta(베타) : feature_vector[3]
Gamma(감마) : feature_vector[3]
이렇게 인덱싱할 수 있다고 생각하면 된다.
그렇기에 3번과 2번을 가져와서 나누는 거니깐 암튼 Beta / Alpha를 한다는 소리..
이걸 하면 집중도가 구해진다는 의미가 된다.
저 Beta / Alpha 수식은 보통적으로 집중도를 구할 때 많이 사용되는 수식 같다. 솔직히 나는 저게 집중도를 구할 수 있는 건지는 잘 모르겠다. 뭐 그래도 아래에 Beta / Alpha가 언급된 논문 2개를 걸어놓겠다.. (참고로 영어라서 거의 보진 않았다..)
from time import sleep
from brainflow.board_shim import BoardShim, BrainFlowInputParams, BoardIds
from brainflow.data_filter import DataFilter
board_id = BoardIds.MUSE_2_BOARD
params = BrainFlowInputParams()
params.serial_number = "Muse-0465" # Muse 2의 고유 시리얼 넘버
board_shim = BoardShim(board_id, params)
use_data_seconds = 5 # n초 동안 데이터 수집
sampling_rate = BoardShim.get_sampling_rate(board_id)
eeg_channels = BoardShim.get_eeg_channels(board_id)
num_points = use_data_seconds * sampling_rate # 몇 초 동안의 데이터를 가져올지
# Muse 2 연결
board_shim.prepare_session()
# Muse 2 데이터 수집 시작
board_shim.start_stream()
# n초 + 1초 동안 데이터 수집
sleep(use_data_seconds + 1)
# 수집한 데이터를 변수에 저장
data = board_shim.get_current_board_data(num_points)
# 예측에 필요한 데이터 추출
bands = DataFilter.get_avg_band_powers(data, eeg_channels, sampling_rate, True)
feature_vector = bands[0]
# 집중도 예측
print(f"Attention: {feature_vector[3] / feature_vector[2]}") # Beta / Alpha
# Muse 2 데이터 수집 정지
board_shim.stop_stream()
# Muse 2 연결 해제
board_shim.release_session()
이 코드는 위에서 말했듯이 get_avg_band_powers에서 자동으로 필터 적용해 주는 apply_filter를 켜서 데이터 전처리를 따로 안 하고 되도록 하는 코드이다.
위에 코드는 잊어버리고 이거 사용하면 될 듯하다..
암튼 바로 실행해 보자! 이번엔 귀찮긴 하지만 착용하고 측정했다!
그리고 위에서도 말했듯이 이번에는 1초가 아니라 5초 측정이다.
1초로도 되기는 하는데.. 조금 부족해 보여서 5초로 했고.. 좀 더 길게 할수록 정확도는 높아질 것 같다 생각은 들긴 한다..
코드 실행!
[2025-02-19 07:46:39.169] [board_logger] [info] incoming json: {
"file": "",
"file_anc": "",
"file_aux": "",
"ip_address": "",
"ip_address_anc": "",
"ip_address_aux": "",
"ip_port": 0,
"ip_port_anc": 0,
"ip_port_aux": 0,
"ip_protocol": 0,
"mac_address": "",
"master_board": -100,
"other_info": "",
"serial_number": "Muse-0465",
"serial_port": "",
"timeout": 0
}
[2025-02-19 07:46:39.170] [board_logger] [info] Use timeout for discovery: 6
[INFO] SimpleBLE: D:\a\brainflow\brainflow\third_party\SimpleBLE\simpleble\src\backends\windows\Utils.cpp:33 in initialize_winrt: CoGetApartmentType: cotype=-1, qualifier=0, result=800401F0
[INFO] SimpleBLE: D:\a\brainflow\brainflow\third_party\SimpleBLE\simpleble\src\backends\windows\Utils.cpp:41 in initialize_winrt: RoInitialize: result=0
[2025-02-19 07:46:39.203] [board_logger] [info] found 1 BLE adapter(s)
[2025-02-19 07:46:39.409] [board_logger] [info] Found Muse device
[2025-02-19 07:46:41.070] [board_logger] [info] Connected to Muse Device
[2025-02-19 07:46:42.072] [board_logger] [info] found control characteristic
Attention: 0.5993206298011964
다른 정보 출력들은 이전 글에서 말했으니 무시하고 Attention만 봐보자!
처음 실행하고 코드의 한 함수를 보면서 집중했을 때 (글 쓰느라 머리 엄청 아픈 상태였음 글 쓰는데 6시간쯤 됐을 때)
Attention: 1.172955634748009
값이 작아지나 머리 흔들거나 집중 안 했을 때 (딴 데 보거나 머리 흔듦.. 집중해서 머리 아픈 상태라 높게 나올까 봐..)
Attention: 0.5993206298011964
도대체 값이 어디까지가 최대인거지? 집중 한번 해볼까? 하다가 한곳에 집중하지 코드를 훑어보고 있었을 때
Attention: 0.7456045268742625
어라? 왜 낮은 거지.. 하고 함수 안을 살펴보고 있었을 때 (함수 들어갈 때 화면이 바뀌면서 집중력 더 떨어짐)
Attention: 0.45490847948134255
그냥 한곳에 집중해 보자 하고 한 함수만 가까이서 집중하며 보고 있었을 때
Attention: 1.2981097661167502
측정하면서 어떤 상황인지 함께 적어봤다..
확실히 그 상황마다의 집중도를 확실하게 캐치하는 것 같다. 정규화는 되어있지 않아서 확인하기는 좀 힘들긴 하지만..
저게 0 ~ 1의 값이 아닌 이유는 뭐 당연하지만 값의 범위가 달라서이다.. 저거를 0 ~ 1로 맞추는 방법이 있긴 하겠지만.. 뭐 있겠지만 생각한다. 참고로 뭐 max 값 min 값 해서 범위 찾아서 그걸로 0 ~ 1로 맞추는 걸 생각해 보긴 했는데 어차피 측정할 때 데이터를 이상하게 하는 방법도 있고 개인마다 다 차이 나서 맞추기가 어려울 것 같긴 하다. 뭐 찾아보면 어딘가에는 0 ~ 1로 맞추는 게 있긴 하겠다만.. 어차피 다음 글에서 인공지능으로 하는 게 0 ~ 1 값이다.
추가로 이전에 말했던 것 같은데 왼쪽은 근육이 발달하지 않은 건지 잘 안되지만 오른쪽은 뭔가 귀를 위로 올린다 생각하며 힘준 상태로 이를 물어버리면 오른쪽 귀 쪽이 뭔가 위로 올라가며 힘을 주는 듯한 느낌이 난다.
이 상태로 측정해 버리면 베타 값인가? 그게 파워가 확 높아져버림..
그렇게 되면 집중도를 조작할 수 있다. 심각하게..
그 상태로 측정하게 되면 이렇게 나온다..
Attention: 4.007621255928729
저거 힘주는 건 기숙사 방에서 해보다가 어쩌다가 집중하려고 힘줬더니만 진짜 돼버려서 알게 된 것..
참고로 기기를 벗은 상태로 측정하면 -1000 같은 결측값과 이상한 값들 때문에 이렇게 나온다.
Attention: 19.663765197669104
암튼 이상하게 나온다. 이래서 0 ~ 1 값으로 맞추기는 좀 어려울 것 같긴 하다.. 뭐 극단적으로 지금 생각나는 방법으로는 범위를 -1000 ~ 1000으로 해서 하면 될 것 같긴 한데, 이러면 집중을 해도 값이 작게 나올 테니 패스
그리고 추가로 실시간으로 측정하는 걸 원한다면.. 아래 코드로 해보는 걸 추천한다.
from time import sleep
import keyboard
from brainflow.board_shim import BoardShim, BrainFlowInputParams, BoardIds
from brainflow.data_filter import DataFilter
board_id = BoardIds.MUSE_2_BOARD
params = BrainFlowInputParams()
params.serial_number = "Muse-0465" # Muse 2의 고유 시리얼 넘버
board_shim = BoardShim(board_id, params)
use_data_seconds = 5 # n초 동안 데이터 수집
sampling_rate = BoardShim.get_sampling_rate(board_id)
eeg_channels = BoardShim.get_eeg_channels(board_id)
num_points = use_data_seconds * sampling_rate # 몇 초 동안의 데이터를 가져올지
# Muse 2 연결
board_shim.prepare_session()
# Muse 2 데이터 수집 시작
board_shim.start_stream()
# n초 + 1초 동안 데이터 수집 - 안하면 오류남
sleep(use_data_seconds + 1)
while True:
# 나가기 조건
if keyboard.is_pressed('q'):
break
# 수집한 데이터를 변수에 저장
data = board_shim.get_current_board_data(num_points)
# 예측에 필요한 데이터 추출
bands = DataFilter.get_avg_band_powers(data, eeg_channels, sampling_rate, True)
feature_vector = bands[0]
# 집중도 예측
print(f"Attention: {feature_vector[3] / feature_vector[2]}") # Beta / Alpha
# Muse 2 데이터 수집 정지
board_shim.stop_stream()
# Muse 2 연결 해제
board_shim.release_session()
실행하려면 pip install keyboard로 keyboard 라이브러리 설치하고 실행할 수 있다.
간단하게 설명하면 처음에 데이터 수집을 위해 수집 초 + 1초를 기다린 후
while로 반복하면서 반복될 때마다 최근의 5 * 256 데이터를 가져오고 그걸로 집중도를 계산해서 바로 출력하는 코드이다. 그리고 키보드로 q를 누르면 종료된다.
이 코드의 함정이라면 집중을 한 것을 보고 싶다면 집중한 후에 바로 보는 것은 하기 힘들고 집중하고 설정한 초가 지난 후에 봐야 집중도를 잴 수 있다는 점이다. (ㅋㅋ)
뭐 저 초를 1초로 바꿔도 되기는 하지만.. 정확도는 낮아지니 추천은 안 하지만.. 수업 자료(PPT)에서는 1초로 했었기 때문에.. 해봐도 문제 될 건 아마 없지 않을까.. 하는..
암튼 이걸로 Beta / Alpha 수식으로 집중도를 계산해 보는 건 여기에서 끝!
이거 새벽 2시에 작성하기 시작했는데.. 벌써 8시네.. 허허.. 심지어 더 길어 보이네..