프로젝트 초기 구상
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