프로젝트 초기 구상
hardware
에서 측정한 Data를 Web
에 전송한다.Web
에서 Data를 DB에 저장하고 AI
를 동작시켜서 예측한 혈압 정보를 출력한다.초기에는 논리적인 흐름에 따라 위와같이 프로젝트를 구상했다. 프로젝트를 진행할수록 Web
에서 AI
를 동작시키는 것이 불필요하다고 느꼈다. 차라리 hardware
에서 AI
를 동작시키고 SpO2, PPG, 예측 혈압 정보를 한꺼번에 Web
에 전달한다면, 불필요한 동작들이 많이 제외되고 수월하게 제작할 수 있지 않을까? 라는 생각이 들었다. 마침 사용하는 라즈베리파이에서 파이썬 3.7과 텐서플로우 2.0.0이 동작하는 것을 확인했기에, 아이디어를 실현시키기로 했다.
기존의 방식
Web → Hardware → Web → AI → Web
새로 구상한 방식
Web → Hardware → AI → Web
rp_preprocess()
def rp_preprocess(self, file_name, info_dir):
"""
라즈베리파이에서 수집한 데이터 전처리
:return:
"""
read_path = self.set_path(file_name)
info_path = self.set_path(info_dir)
spo2_wave_first = [5, 70]
# spo2_wave_start = []
select_wave_pd = pd.DataFrame()
spo2_wave_all_avg_list = []
select_wave_full_avg_list = []
ppg_pd = self.load_collection_data(path=read_path)
info_pd = self.load_collection_data(path=info_path)
# ppg_pd = ppg_pd[['PPG']]
# ppg_tp = ppg_pd.transpose()
# ppg_pd = ppg_tp.transpose()
# print(ppg_pd)
first_interval = ppg_pd.iloc[spo2_wave_first[0]: spo2_wave_first[1], :]
# print(first_interval)
first_ppg = first_interval.iloc[:,0]
first_index = first_ppg.astype(float).idxmax()
# spo2_wave_start.append(first_index)
ppg_pd = ppg_pd.iloc[first_index:, :]
spo2_wave_all = 0
for spo2_wave in ppg_pd.iloc[:, 0]:
spo2_wave_all = spo2_wave + spo2_wave_all
spo2_wave_all_avg = spo2_wave_all / len(ppg_pd.iloc[:, 0])
# x = range(len(ppg_pd.iloc[:, 0]))
# y = [spo2_wave_all_avg for _ in x]
min = ppg_pd.iloc[:, 0].max()
min_1_count = 0
j_over = 0
for j in range(len(ppg_pd.iloc[:, 0])):
if min > ppg_pd.iloc[j, 0]:
min = ppg_pd.iloc[j, 0]
if min_1_count > 0:
j_over = min_1_count
min_1_count = 0
else:
min_1_count = min_1_count + 1
if min_1_count == 20:
min_1 = ppg_pd.iloc[:j, 0].min()
min_1_idx = ppg_pd.iloc[:j, 0].astype(float).idxmin()
min = ppg_pd.iloc[:, 0].max()
min_1_count = 0
j = j - 20 + j_over
break
max = ppg_pd.iloc[:, 0].min()
max_1_count = 0
k_over = 0
for k in range(len(ppg_pd.iloc[:, 0])):
if max < ppg_pd.iloc[j + k, 0]:
max = ppg_pd.iloc[j + k, 0]
if max_1_count > 0:
k_over = max_1_count
max_1_count = 0
else:
max_1_count = max_1_count + 1
if max_1_count == 10:
max_1 = ppg_pd.iloc[j: j+k, 0].max()
max_1_idx = ppg_pd.iloc[j: j+k, 0].astype(float).idxmax()
max = ppg_pd.iloc[:, 0].min()
max_1_count = 0
k = k - 10 + k_over
break
for l in range(len(ppg_pd.iloc[:, 0])):
if min > ppg_pd.iloc[j + k + l, 0]:
min = ppg_pd.iloc[j + k + l, 0]
if min_1_count > 0:
min_1_count = 0
else:
min_1_count = min_1_count + 1
if min_1_count == 20:
min_2 = ppg_pd.iloc[j + k: j + k + l, 0].min()
min_2_idx = ppg_pd.iloc[j + k: j + k + l, 0].astype(float).idxmin()
min_1_count = 0
break
max = ppg_pd.iloc[:, 0].max()
min = ppg_pd.iloc[:, 0].min()
one_wave_len = min_2_idx - min_1_idx
start_point = [ppg_pd.index[0]]
end_point = [start_point[0] + 127]
# print(ppg_pd)
x = range(len(ppg_pd.loc[:,'PPG']))
"""
환자 감시 장치에서 2분동안 수집한 PPG 신호 전체
"""
# plt.rcParams["figure.figsize"] = (18, 7)
# plt.plot(x, ppg_pd.loc[:,'PPG'])
# # plt.axis([0, len(ppg_pd.loc['SpO2 Wave']), ppg_pd.loc['SpO2 Wave'].min(),
# # ppg_pd.loc['SpO2 Wave'].max()])
# # plt.savefig(plt_save_path + "\\\\{0}_1_Full.png".format(num_1_file_name))
# # plt.show()
# # plt.cla()
"""
-250 ~ 250 박스
"""
y = -250 + spo2_wave_all_avg
y = [y for _ in x]
plt.plot(x, y, c='k')
y = 250 + spo2_wave_all_avg
y = [y for _ in x]
plt.plot(x, y, c='k')
# plt.savefig(plt_save_path + '\\\\{0}_6_wave_all_avg_line.png'.format(num_1_file_name))
# plt.show()
# plt.cla()
"""
파형 한개의 크기를 표시
빨간색 점 = 시작하는 지점
파란색 점 = 파형의 최고점
초록색 점 = 파형의 끝점
"""
# min 1
plt.scatter(min_1_idx, min_1, c = 'r')
# max 1
plt.scatter(max_1_idx, max_1, c = 'b')
# min 2
plt.scatter(min_2_idx, min_2, c = 'g')
color = ["b", "g", "r", "c", "m", "y"]
for m in end_point:
if m + one_wave_len < ppg_pd.index[-1]:
check_point = m
check_point_end = check_point + one_wave_len
min_wave = ppg_pd.loc[check_point:check_point_end, 'PPG'].min()
min_wave_idx = ppg_pd.loc[check_point:check_point_end, 'PPG'].astype(float).idxmin()
check_point = min_wave_idx
check_point_end = check_point + (one_wave_len // 1)
max_wave = ppg_pd.loc[check_point:check_point_end, 'PPG'].max()
max_wave_idx = ppg_pd.loc[check_point:check_point_end, 'PPG'].astype(float).idxmax()
start_point.append(max_wave_idx)
if max_wave_idx + 127 < ppg_pd.index[-1]:
end_point.append(max_wave_idx + 127)
else:
end_point.append(ppg_pd.index[-1])
# plt.plot(x, ppg_pd.loc[:, "PPG"], c='k')
for n in range(len(start_point[:-1])):
# print(len(start_point))
x = range(start_point[n], end_point[n] + 1)
y = ppg_pd.loc[start_point[n]:end_point[n], 'PPG']
# print(len(x))
# print(len(y))
plt.plot(x, y, c=color[n%len(color)])
bio_index = []
for p in range(128):
bio_index.append(p)
select_wave_one_avg_list = []
for o, wave_start in enumerate(start_point[:-1]):
select_wave_one = copy.deepcopy(ppg_pd.loc[wave_start:end_point[o], 'PPG'])
height = info_pd.iloc[0, 0]
weight = info_pd.iloc[0, 1]
h_w_Seris = pd.Series({'height': height,
'weight': weight})
select_wave_one_one = 0
for r in select_wave_one:
select_wave_one_one = select_wave_one_one + r
select_wave_one_avg = select_wave_one_one / len(select_wave_one)
if max in select_wave_one.unique():
continue
if min in select_wave_one.unique():
continue
# if ((select_wave_one_avg - spo2_wave_all_avg) > 250) or ((select_wave_one_avg - spo2_wave_all_avg) < -250):
# continue
select_wave_one_avg_list.append(select_wave_one_avg)
x = range(wave_start - start_point[0], wave_start + 128 - start_point[0])
y = [select_wave_one_avg for _ in x]
#
# plt.plot(x, select_wave_one, c='cornflowerblue') # cornflowerblue #steelblue
plt.plot(x, y, c=color[o % len(color)])
for s in range(len(select_wave_one)):
select_wave_one.iloc[s] = select_wave_one.iloc[s] - spo2_wave_all_avg
for q in range(len(select_wave_one)):
select_wave_one.iloc[q] = select_wave_one.iloc[q] / 1024
select_wave_one.index = bio_index
select_wave_one = pd.concat([h_w_Seris, select_wave_one])
select_wave_pd = select_wave_pd.append(select_wave_one, ignore_index=True)
plt.show()
select_wave_full_avg_list.append(select_wave_one_avg_list)
select_wave_pd.to_csv("rp_text.csv", mode='w', header=True)
load_collection_data()
def load_collection_data(self, path):
"""
수집데이터를 불러옴
불러오는 데이터의 형식은 csv
csv파일을 pandas형식으로 저장
:param path:
데이터가 저장된 위치
:return:
pandas 자료형 데이터
"""
read_data = pd.read_csv(path, index_col=0)
return read_data
predict()
def predict(self, dir_name):
"""
인공지능 모델 예측을 위한 함수
기존에 학습한 모델 정보를 통해 새로운 데이터(PPG)의 혈압 정보(수축기 혈압, 이완기 혈압)를 예측함
:param dir_name:
예측할 데이터가 있는 디렉터리명
ex) data\\\\unknown.csv
:return:
"""
path = self.set_path(dir_name)
csv_data = self.load_collection_data(path=path)
wave = csv_data.iloc[:,0:128]
HW = csv_data.iloc[:,-2:]
wave_list = wave.values.tolist()
Height = HW.iloc[:, 0]
Weight = HW.iloc[:, 1]
Height = Height.values
Weight = Weight.values
Height_gray_code_list = self.convert_DEC_to_GrayCode(Height)
Weight_gray_code_list = self.convert_DEC_to_GrayCode(Weight)
HW_gray_code_list = self.list_append(Height_gray_code_list, Weight_gray_code_list)
X_np = self.list_append(wave_list, HW_gray_code_list)
X_data = self.make_np_array(X_np)
model = self.load_model()
model.summary()
print(model.predict(X_data[1:2], batch_size=self.batch_size))
predict = model.predict(X_data[:], batch_size=self.batch_size)
print("X_test[1] : \\n", X_data[0:10])
print("model.predict(X_test[1:2], batch_size=5) : \\n", predict)
BP_D_dec, BP_S_dec = self.postprocess(predict)
print("\\n====predict 값====\\n")
print("BP_D_dec", BP_D_dec)
print("BP_S_dec", BP_S_dec)
#
for i in range(len(BP_D_dec)):
print("\\n====predict 값====\\n")
print("BP_D_dec", BP_D_dec[i])
print("BP_S_dec", BP_S_dec[i])
X_test_Series = pd.DataFrame(X_data)
return BP_D_dec, BP_S_dec