반응형

안녕하세요. 오늘은 Indoor Positioning에서 [cm]단위의 오차를 내는 UWB 관련 논문에 이야기하겠습니다. 

 

coding-yoon.tistory.com/136?category=910542

 

[무선 통신] Bluetooth Low Energy(BLE) 1. Physical Layer

microchipdeveloper.com/wireless:start Wireless Communications - Developer Help Microchip offers a broad portfolio of wireless solutions which are cost effective and very easy to implement. Depending..

coding-yoon.tistory.com

BLE는 기기간 수신신호세기(RSSI)를 이용해 Indoor Positioning을 하는 방면, UWB는 nanosecond(10e-9)의 길이를 갖는 매우 짧은 펄스를 이용하여 통신하는 방식입니다. 

 

시간 분해능이 매우 높아 최단 경로와 다중 경로간의 신호구별을 용이하여 수 cm이내의 정확도로 거리 측정이 가능하고 낮은 전력 밀도로 저전력 대용량 데이터 전송이 가능합니다. 

 

 

대표적으로 TWR(Two Way Ranging) 방식으로 Distance를 추정합니다. 

 

t_round A : 노드 A가 거리측적용 메세지를 송신한 순간부터 노드 B의 응답 메세지를 수신했을 때의 시간, 즉 거리 측정                 메세지의 왕복시간(Round Trip Time : RTT)

t_reply B : 노드 B의 응답시간 또는 처리 시간(Processing Time)

t_p : 거리 측정 메세지의 단방향 도달 시간

TOA = t_p, C : 전파속도, 광속도(3e8)

 

일반 TWR은 두 기기간의 하드웨어적 차이로 인해 시간 측정이 달라 TOA에 오차가 발생할 수 있어, SDS-TWR 등 많은 방식이 존재합니다.

< [UWB] IEEE 802.15.4a UWB 기반 실내 위치측정 시스템의 설계 및 구현 > 

 

 

기본적으로 UWR을 이용하여 거리를 구하는 방법을 알아보았으며, Non-Line of Sight 에 대해 알아보겠습니다. 

 

ieeexplore.ieee.org/document/9108193

 

UWB NLOS/LOS Classification Using Deep Learning Method

Ultra-Wide-Band (UWB) was recognized as its great potential in constructing accurate indoor position system (IPS). However, indoor environments were full of complex objects, the signals might be reflected by the obstacles. Compared with the Line-Of-Sight (

ieeexplore.ieee.org

 

논문의 아이디어는 UWB LOS/NLOS 분류를 딥러닝을 통해 성능을 향상시키는 것입니다. 

(Line of Sight, Non-Line of Sight)

 

실내 환경은 다양한 장애물(책상, 캐비넷, 책장 등)으로 가득차있으며, 이 장애물을 통해 UWB 신호는 반사될 수 있으며, 신호 수신은 직접 수신 된 신호에 비해 거리 정보에 더 긴 전송 시간을 가져오고 추가적인 Time-varying bias를 유발합니다. 

cf) UWB 신호의 오차는 대게 양의 값(+)을 가집니다. UWB 신호는 Nanosecond 단위로 시간측정 방식이기 때문에, 신호가 반사되면 지연 시간이 더해져 오차로 발생하기 때문입니다.

 

반사를 통해 오차를 일으킨 NLOS를 제거하면, 정확한 거리를 구할 수 있습니다. 

 

가장 직접적인 접근 방식은 UWB 신호 전파 경로 손실 모델 또는 CIR (Channel Impulse Response)을 기반으로 NLOS / LOS 신호 특성을 분석하는 것입니다.

 

위 논문은 Doctor Klemen Bregar providing the UWB NLOS/LOS open source data 를 이용

github.com/ewine-project/UWB-LOS-NLOS-Data-Set

 

ewine-project/UWB-LOS-NLOS-Data-Set

Repository with UWB data traces representing LOS and NLOS channel conditions in 7 different indoor locations. - ewine-project/UWB-LOS-NLOS-Data-Set

github.com

 

이 포스팅은 두 편을 걸쳐 진행됩니다. ( 1편 : 오픈소스 데이터셋 전처리, 2편 : 논문 기반 네트워크를 통해 학습 )

 

Doctor Klemen Bregar providing the UWB NLOS/LOS open source data를 딥러닝을 위해 전처리 과정이 필요합니다. 

 

오픈소스 데이터 구성

오픈소스는 csv, 데이터를 불러오는 모듈로 구성되어 있습니다. 

4년 전 데이터이므로 pandas 버전 오류 해결을 위해 uwb_dataset.py를 약간 변경했습니다.

 

uwb_dataset.py

"""
Created on Feb 6, 2017
@author: Klemen Bregar 
"""

import os
import pandas as pd
from numpy import vstack


def import_from_files():
    """
        Read .csv files and store data into an array
        format: |LOS|NLOS|data...|
    """
    rootdir = '../dataset/'
    output_arr = []
    first = 1
    for dirpath, dirnames, filenames in os.walk(rootdir):
        for file in filenames:
            filename = os.path.join(dirpath, file)
            print(filename)
            output_data = [] 
            # read data from file
            df = pd.read_csv(filename, sep=',', header=0)
            # ------------------------ update Mar 3, 2021 ----------------------------- #
            columns_name = df.columns.values
            # ------------------------ update Mar 3, 2021 ----------------------------- #
            

            # ------------------------ update Mar 3, 2021 ----------------------------- #
            # input_data = df.as_matrix()
            # df.as_matrix() was depriciated after the version 0.23.0 use df.values()
            input_data = df.values
            
            # ------------------------ update Mar 3, 2021 ----------------------------- #
            
            # append to array
            if first > 0:
                first = 0
                output_arr = input_data
            else:
                output_arr = vstack((output_arr, input_data))
    
    return columns_name, output_arr

if __name__ == '__main__':

    # import raw data from folder with dataset
    print("Importing dataset to numpy array")
    print("-------------------------------")
    data = import_from_files()
    print("-------------------------------")
    # print dimensions and data
    print("Number of samples in dataset: %d" % len(data))
    print("Length of one sample: %d" % len(data[0]))
    print("-------------------------------")
    print("Dataset:")
    print(data)

 

1. Load UWB data

import numpy as np
import pandas as pd
import uwb_dataset

# import raw data
data = uwb_dataset.import_from_files()

# divide CIR by RX preable count (get CIR of single preamble pulse)
# item[2] represents number of acquired preamble symbols
for item in data:
	item[15:] = item[15:]/float(item[2])

print("\nColumns :", columns.shape, sep=" ")
print("Data :", data.shape, sep=" ")
print(type(data))

 

2. Create UWB(CIR) Pandas Dataframe

cir_n = len(columns[15:])

print("Columns :", columns, sep=" ")
print("Channel Inpulse Response Count :", cir_n, sep=" ")

df_uwb = pd.DataFrame(data=data, columns=columns)
print("Channel 2 count :", df_uwb.query("CH == 2")['CH'].count())
print("Null/NaN Data Count : ", df_uwb.isna().sum().sum())
df_uwb.head(3)

# LOS/NLOS Count
los_count = df_uwb.query("NLOS == 0")["NLOS"].count()
nlos_count = df_uwb.query("NLOS == 1")["NLOS"].count()

print("Line of Sight Count :", los_count)
print("Non Line of Sight Count :", nlos_count)

# Columns CIR Extract
df_uwb_data = df_uwb[["CIR"+str(i) for i in range(cir_n)]]
print("UWB DataFrame X for Trainndarray shape : ",df_uwb_data.values.shape)
df_uwb_data.head(5)

 

Columns : Sampling 1016 CIR

LOS : 21000, NLOS : 21000  Pandas Dataframe 

 

다음 글은 생선된 위 데이터 프레임을 이용해 논문에 제시된 CNN+LSTM 모델을 Pytorch로 구현하겠습니다.

coding-yoon.tistory.com/139

 

[무선 통신] UWB LOS/NLOS Classification Using Deep Learning Method (2)

안녕하세요. WB LOS/NLOS Classification Using Deep Learning Method(1)에서 UWB CIR Dataset을 생성하였다면, 2편으로 논문에서 제시한 CNN_LSTM 네트워크를 약간 변형하여 구성하겠습니다. coding-yoon.tistory..

coding-yoon.tistory.com

 

728x90
반응형
반응형

안녕하세요. 

 

제가 평소에 자주 즐겨보는 빵형의 개발도상국에서 재미있는 딥러닝 예제가 있어서 가져 왔습니다.

 

www.youtube.com/watch?v=VxRCku4Bkgg

평소에는 눈으로만 보다가 재밌어 보여서, 실제로 저도 한 번 해보기로 했습니다.

 

댓글을 보니, 많은 사람들이 데이터 프로세싱 부분에서 힘들어 하십니다.

 

저도 따라해보았더니, 학습이 진또배기가 아니라 데이터 전처리 부분이 이 동영상의 꽃이란걸 알게 됐습니다. 

(역시 딥러닝은 데이터가 문제...)

 

 

 

1. 데이터셋 받기

 

www.kaggle.com/jessicali9530/celeba-dataset

 

CelebFaces Attributes (CelebA) Dataset

Over 200k images of celebrities with 40 binary attribute annotations

www.kaggle.com

1GB Face Dataset

하나 주의사항 !

 

컴퓨터 용량은 충분하신가요?

 

실제로 데이터를 받아보면, 1G 바이트 약간 넘습니다. 

 

하지만, 데이터 전처리를 하게 되면

 

지옥을 맛보시게 될겁니다. SSD 빵빵한거나 서버가 없으면 뒤로 돌아가시는걸 추천드립니다.

 

 

 

2. Git에서 코드 받기

 

github.com/kairess/super_resolution

 

kairess/super_resolution

Super resolution with Subpixel CNN using Keras. Contribute to kairess/super_resolution development by creating an account on GitHub.

github.com

 

download
오늘의 주인공

오늘은 preprocess.ipynb 전처리 부분을 봐보겠습니다. 

 

옵션사항입니다. 

 

저는 Pycharm으로 코딩을 할 예정이기 때문에 .ipynb를 .py로 변경했습니다.

 

jupyter nbconvert --to scripy preprocess.ipynb ( 해당 경로에서 )

 

 

 

3. 경로/디렉토리 준비하기

 

빵빵한 SSD를 준비합니다. 

 

 

저는 E 드라이브에 준비하겠습니다.

 

E 드라이브(자신의 드라이브)에 dataset 폴더를 하나 만듭니다.

 

1. E:\dataset 

제 기본 경로가 되겠습니다.

 

dataset 폴더에 이렇게 폴더를 만들어 주겠습니다. 

2. E:\dataset\img

 

 

우선 img 폴더는 학습을 시킬 실제 데이터가 들어가 있습니다. 아까 kaggle에서 받은 img_align_celeba를 옮겨서 이름만 바꿔준 것입니다. 그대로 사용하셔도 상관없습니다. 저는 간단한게 좋아서 img로 바꿨습니다. 

이 img 폴더에 있는 사진들은 학습할 데이터입니다. 간단히 X_data라 부르겠습니다.

 

X_data는 Train용, Validation용, Test용으로 나뉩니다. 

 

3. E:\dataset\list_eval_partion.csv

 

이미지에 각각 라벨링 한 것을 csv파일로 저장되있습니다. 다른 csv 파일은 그냥 휴지통에 던져 줍니다.

 

partition : 1 => train (162770장)

partition : 2 => val (19867장)

partition : 3 => test (19962장)

 

 

4. E:\dataset\x_train

 

이제 데이터를 전처리하게 되면 train, validation, test 용으로 데이터가 나뉘기 때문에 

 

저 이름 그대로 폴더를 만들어 주어야 합니다. 

 

x_train

x_val

x_test

y_train

y_val

y_test

 

 

이 폴더 안에는 학습하기 좋게끔 numpy(.npy) 로 전처리되어 저장될 예정입니다. 

 

굳이 몰라도 되지만, TMI로 scipy나, matplotlib 등 여러 과학, 수학, 딥러닝에서 numpy를 제공하는 이유는

 

numpy가 C코드로 작성된 라이브러리이기 때문에 파이썬 내장 list보다 속도가 훨씬 빠릅니다. 

 

파이썬 개발한 사람이 C 개발자였으니... 

 

 

4. 코드

 

import os, cv2
import numpy as np
from skimage.transform import pyramid_reduce 


# 경로
base_path = r'E:\dataset'  # E:\dataset
img_path = os.path.join(base_path, 'img')  # E:\dataset\img

eval_list = np.loadtxt(os.path.join(base_path, 'list_eval_partition.csv'), dtype=str, delimiter=',', skiprows=1)
print(eval_list[0])


# 이미지 확인
img_sample = cv2.imread(os.path.join(img_path, eval_list[0][0]))
print(os.path.join(img_path, eval_list[0][0]))
h, w, _ = img_sample.shape


# 이미지 전처리 
crop_sample = img_sample[int((h-w)/2):int(-(h-w)/2), :]
resized_sample = pyramid_reduce(crop_sample, downscale=4)

pad = int((crop_sample.shape[0] - resized_sample.shape[0]) / 2)

padded_sample = cv2.copyMakeBorder(resized_sample, top=pad, bottom=pad, left=pad, right=pad, borderType=cv2.BORDER_CONSTANT, value=(0,0,0))

print(crop_sample.shape, padded_sample.shape)


# main
downscale = 4
n_train = 162770
n_val = 19867
n_test = 19962

for i, e in enumerate(eval_list):
    filename, ext = os.path.splitext(e[0])
    
    img_path = os.path.join(img_path, e[0])
    
    img = cv2.imread(img_path)
    
    h, w, _ = img.shape
    
    crop = img[int((h-w)/2):int(-(h-w)/2), :]
    crop = cv2.resize(crop, dsize=(176, 176))
    resized = pyramid_reduce(crop, downscale=downscale)

    norm = cv2.normalize(crop.astype(np.float64), None, 0, 1, cv2.NORM_MINMAX)
    
    if int(e[1]) == 0:
        np.save(os.path.join(base_path, 'x_train', filename + '.npy'), resized)  
        np.save(os.path.join(base_path, 'y_train', filename + '.npy'), norm)  
    elif int(e[1]) == 1:
        np.save(os.path.join(base_path, 'x_val', filename + '.npy'), resized)
        np.save(os.path.join(base_path, 'y_val', filename + '.npy'), norm)
    elif int(e[1]) == 2:
        np.save(os.path.join(base_path, 'x_test', filename + '.npy'), resized)
        np.save(os.path.join(base_path, 'y_test', filename + '.npy'), norm)

 

 

 

5. 오류

 

아마 유튜브를 보고 따라하시는 분들 중에 대부분이 경로 문제입니다. 

 

 

----------------------------------------------------------------------------------------------------------------------------

 

첫 번째 오류 

대표적으로 이 분이  경로 문제로 막히신겁니다. 

 

Git에서 코드를 받으실 때 DataGenerator.py 도 같이 받으십니다. 

DataGenerator는 x_train 등 전처리한 .npy 파일을 불러와서 Batch로 묶고 shuffle 하여 데이터셋을 만드는 코드입니다.

 

하지만 에러문을 보게 되면, splited = ID.split('/') 에서 오류가 발생합니다. 

 

ID.split('/')는 불러온 경로를 '/' 기준으로 나누는 것입니다. 

 

예를 들어 

 

'E:/dataset/img' 가 있습니다.

 

'E:/dataset/img'.split('/')을 하게 되면 ["E:", "dataset", "img"]로 나뉩니다. 

 

눈치 빠르신 분이 있을까요??

 

제 코드에서 기본 경로는  r'E:\dataset' 입니다. 

 

r'E:\dataset'.split('/")는 어떻게 될까요?

 

결과는 ["r'E:\dataset'.split('/")"] 입니다. 우리들은 기본 경로를 절대경로로 표시했습니다.

 

"\"는 "/" 아닙니다!!!!!  우리는 DataGenerator.py에 들어가서 splited = ID.split('/')를 

 

splited = ID.split('\')로 변경해주면 해결됩니다.

 

ID가 왜 경로죠? 라고 궁금해하는 분이 계실 수도 있습니다. 

 

DataGenerator.py 45줄

__data_generation 함수에서 list_IDS_temp라는 파라미터를 받는 것을 알 수 있습니다. 

 

list_IDS_temp가 무엇인지 확인하겠습니다. 

DataGenerator.py 34줄

list_IDs에서 받아온거네요. list_IDs가 무엇인지 역추적해보겠습니다. 

 

DataGenerator.py 9줄

아하 DataGenerator에서 생성자에서 파라미터로 받는 것을 확인했습니다. 맨 처음 파라미터니까 찾기 쉽겠네요.

 

아마 데이터를 생성하는 클래스이기 때문에 train.py에서 사용했을겁니다. 

 

train.py

네. import 한 것을 바로 확인할 수 있습니다. 

 

 

x_train_list = list_IDs 라는 것을 역추적해 알 수 있게 되었습니다. 

 

위 댓글 분의 오류의 원인은 경로 문제라는 것을 제대로 확인할 수 있습니다. 

 

 

 

----------------------------------------------------------------------------------------------------------------------------

 

 

두번 째 오류

'NoneType' object has no attribute 'shape'

 

shape라는 속성이 없다라는 오류입니다. 

 

아마 shape를 쓴 걸로 보아 NoneType 자리에는 Numpy가 들어갈 수 있다는걸 추측할 수 있습니다. 

 

그런데 NoneType 이라는 것은 해당 경로에 .npy를 불러 왔지만 경로가 잘못되어 아무 것도 불러오지 못하였다고 말할 수 있습니다. 

 

 

----------------------------------------------------------------------------------------------------------------------------

 

 

이것도 경로 문제입니다. 

 

에러문에 나와있네요.

 

No such file or directory  파일이나 폴더를 찾을 수 없다...!

 

아마 경로를 확인해보니 첫 번째 오류와 비슷한 것 같습니다. 

 

경로구분이 "\\"으로 되있는데 split은 "/" 이니 제대로 분리가 되지 않았을겁니다. 

 

np.load( 경로 ) 에서 막힌 듯 싶습니다. !! 

 

 

----------------------------------------------------------------------------------------------------------------------------

 

이건 제가 올린 답글... 

 

도움이 되셨으면 좋겠습니다... 글을 마치도록 하겠습니다아아... 빵형 개발도상국님 항상 재밌게 잘 보고 있습니다!

728x90
반응형

+ Recent posts