동그란 도그린
깊이 추정을 이용한 조난자의 위치 추정 및 어플에서 조난자 위치 보여주기 본문
현재 저희 팀이 진행하고 있는 프로젝트는 '깊이 추정과 객체 검출을 사용한 조난자 수색 자율주행 드론'으로,
주요 기능 중 하나가 깊이 추정을 통해 조난자의 위치를 추정하는 것입니다.
특히 저희 팀은 두 개의 카메라가 아닌, 하나의 카메라만 이용한 깊이 추정(Depth estimation)을 통해 해당 기능을 구현하였습니다.
깊이 추정(Depth Estimation)이란?
간단히 말해, 이미지로부터 깊이(depth)를 추정하는 기술을 뜻합니다.
저희는 RGB 이미지와 그에 대응되는 depth 이미지를 (지도학습 방법으로) 학습시킨 DenseDepth 모델을 이용하였습니다.
좌측의 이미지로부터 깊이를 추정(Depth estimation)한 결과는 우측과 같습니다.
가까이 있을수록 어둡게 나타납니다. 해당 이미지에서는 제가 제일 가까이에 있기 때문에 제일 어둡게 나타나는 것을 확인할 수 있습니다.
조난자 위치 추정 구현 과정
어플을 통해 구조대에게 조난자의 위치를 알릴 때,
북쪽 기준으로 ~시 방향(~˚) ~m 거리에 조난자가 발생했습니다 |
위와 같이 드론과 조난자 사이의 거리 & 조난자의 방향을 알려주면 좋겠다고 생각했습니다.
따라서 저희가 구해야 하는 것은 드론과 조난자 사이의 거리 & 조난자의 방향(몇시 방향인지, 각도가 몇도인지)이었습니다.
위의 세가지를 구할 때, 조난자의 위치를 추정하기 위해 드론과 조난자 실제 위치 사이의 관계를 이용하였습니다.
위의 그림에서 dx와 dy 값을 구하여 드론과 조난자 사이의 거리를 도출해냈습니다.
- dy 값 구하기
dy 값은 이 논문을 참고하여 depth 값과 실제 거리 사이의 관계를 나타내는 함수를 도출해냈습니다.
논문 속의 함수 형태는 위와 같은 이차함수 형태이며, 저희는 depth 값과 실제 거리를 직접 측정하여 위의 상수들을 구하여 함수를 작성하였습니다.
저희가 도출해낸 함수는 아래와 같습니다.
(단, 그래프를 예쁘게 보여주기 위해 depth'=(실제 depth 값) x 100을 하였고, dy'의 단위는 m로 하였습니다.)
이처럼 dy 값은 depth 값을 위의 함수에 대입하여 구했습니다.
- dx 값 구하기
dx 값은 드론과 조난자의 실제 위치 관계 및 드론 카메라 영상 속의 조난자 위치를 통해 도출해냈습니다.
도출해낸 식은 아래와 같습니다.
( cx : 카메라 영상 속 조난자 bounding box center의 x좌표,
dy : 위에서 구한 dy 값,
FOV : 드론 카메라 화면의 수평 영역(82.6˚))
- 조난자 방향 구하기
조난자의 방향은 위의 그림에서 az에 해당합니다.
az는 드론의 진행 방향과 조난자 사이의 각도로, 위에서 구한 dx와 dy를 이용하여 아래와 같이 구했습니다.
또한, 이를 북쪽 기준으로 어느 방향에 있는지를 나타내기 위해서는 북쪽 기준으로 드론의 진행 방향 & 드론의 진행 방향과 조난자 사이의 각도를 이용하여야 합니다. 이때 두 가지 경우로 나눌 수 있는데요.
1. 조난자가 드론 진행 방향의 좌측에 있는 경우
조난자의 방향 = yaw (드론의 진행 방향) - az(드론의 진행 방향과 조난자 사이의 각도)
2. 조난자가 드론 진행 방향의 우측에 있는 경우
조난자의 방향 = yaw (드론의 진행 방향) + az(드론의 진행 방향과 조난자 사이의 각도)
위와 같이 두 가지 경우로 나누어 계산하여 조난자의 방향을 구했습니다.
- 코드로 구현하기
위의 식들을 이용하여 아래와 같이 python 코드로 구현하였습니다.
# dist_y = dy
dist_y = 0.012 * (avg_depth * 100 + 50) * (avg_depth * 100 + 50) + 100
# dist_x = dx
dist_x = dist_y * abs(cx - width / 2) / (width / 2) * math.tan(math.radians(41.3))
# az = drone direction과 조난자 사이의 각도
# az = math.atan(dist_x/dist_y)
az = math.atan(dist_x / dist_y)
# dist = 드론과 조난자 사이의 거리
# dist = math.sqrt(dist_y * dist_y + dist_x * dist_x)
dist = math.sqrt(dist_y * dist_y + dist_x * dist_x)
# degree = 조난자 방향 (북쪽 기준 시계 방향으로)
# yaw = 드론의 진행 방향 (북쪽 기준 시계 방향으로)
# width = 드론 카메라 화면 가로 길이
if cx >= width / 2:
degree = yaw+(int(math.degrees(az)))
else:
degree = yaw-(int(math.degrees(az)))
# direction = 조난자 방향 (몇시 방향인지 반올림하여 나타냄)
direction = int(degree / 30 + 0.5)
- 테스트 결과
야외에서 직접 테스트를 해보았는데요,
위의 사진처럼 제가 북쪽 기준으로 1시 방향(15˚ 각도)에 189cm 떨어져있다고 정확히 탐지하는 것을 볼 수 있습니다.
android 앱에서 조난자의 위치 정보 보여주기
조난자가 조금씩 움직일 수 있는 상황을 고려하여 저희는 android 앱에서 조난자의 위치 정보를 실시간으로 보여주도록 구현하였습니다.
이를 위해 저희는 firebase를 이용하였습니다.
- firebase에 조난자 위치 정보 업데이트하기
저희는 firebase의 Realtime Database를 이용하였으며, 데이터베이스를 아래와 같이 구성해주었습니다.
사진에서 survivor가 조난자 위치 정보를 업데이트하기 위해 사용할 노드입니다.
위와 같이 데이터베이스를 구성해준 뒤, 아래와 같이 python 코드를 구현하였습니다.
# 'survivor'를 가리키는 데이터베이스 참조
dir = db.reference('survivor')
# 조난자의 위치 정보 데이터베이스에 저장하기
dir2.update({'degree': degree})
dir2.update({'direction': direction})
dir2.update({'distance': distance})
- android studio에서 firebase의 데이터 읽고 텍스트뷰로 해당 조난자 위치 정보 보여주기
android studio에서 firebase 데이터를 읽는 방법은 firebase documentation에 자세히 적혀있습니다.
1. 데이터 베이스 가져오기
private DatabaseReference mDatabase;
mDatabase = FirebaseDatabase.getInstance().getReference();
2. 데이터 읽고 텍스트 뷰에 보여주기
// 조난자 위치 정보 - 각도
deData=mDatabase.child("survivor").child("degree");
deData.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
degree=dataSnapshot.getValue(float.class);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
});
// 조난자 위치 정보 - 방향
dirData=mDatabase.child("survivor").child("direction");
dirData.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
direction=dataSnapshot.getValue(float.class);
// 텍스트뷰에 조난자 위치 정보 넣기
TextView textView = (TextView)findViewById(R.id.survivor);
Log.d(this.getClass().getName(), (String)textView.getText());
textView.setText("북쪽 기준으로 "+direction+"시 방향("+degree+"º) \n'"+distance+"'m 거리에 조난자가 발생했습니다.");
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
});
// 조난자 위치 정보 - 거리
disData=mDatabase.child("survivor").child("distance");
disData.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
distance=dataSnapshot.getValue(float.class);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
}
});
- 테스트 결과
위의 depth estimation 테스트 시 함께 테스트해보았는데요,
android 앱에서 조난자의 위치 정보를 실시간으로 잘 보여주는지 테스트하기 위하여 오른쪽으로 이동해보았습니다.
그 결과 위의 사진과 같이 변동된 위치 정보를 실시간으로 잘 보여주는 것을 확인할 수 있습니다.
이처럼 오늘 글에서는 Depth estimation을 이용한 조난자 위치 추정 및 해당 위치 정보 android 앱에서 보여주는 것을 구현해보았는데요, 테스트 결과 모두 잘 실행되는 것을 확인할 수 있었습니다.
그럼 이만 글을 마치겠습니다.
'프로젝트 > 졸업프로젝트' 카테고리의 다른 글
Yolov3를 이용한 화재 탐지 (1) | 2021.11.24 |
---|