LSD-SLAM에서 Semi-Dense의 의미

공대생의 팁 2019.03.19 20:56


 최근 자동차의 자율주행에 대한 연구가 지속됨으로 인해 자율주행과 관련된 분야들에서 각종 기술들일 발전하고 있는 오늘날입니다. 자동 제어와 자동차 역학을 기본으로 주행중 다양한 위험물들을 감지해 낼 수 있는 센서들을 사용함으로서 자율주행 기술은 한 걸음씩 나아가고 있습니다.


 특히 기존 로봇공학에서 연구되어온 SLAM(Simultaneous Localization and Mapping)으로 지도를 만드는 기술을 사용하여 자율주행중인 자동차가 위험물을 감지해내 회피하는 알고리즘 또한 연구가 진행되고 있습니다. 특히 카메라의 경우 Rader나 Lidar 센서에 비해 가격이 압도적으로 저렴하고 상대적으로 많은 동영상 정보를 수집할 수 있으나 이를 처리하기에는 상당히 많은 변수가 존재하기 때문에 이와 관련된 연구 또한 다양하게 진행되고 있습니다. 이러한 카메라를 사용하여 Visual SLAM또한 자율주행의 연구 대상이기도 합니다.


 이번 포스팅에서는 카메라로 SLAM을 사용하는 알고리즘 중 하나인 LSD-SLAM(Large-Scale Direct SLAM)에서 Semi-Dense의 의미에 대해 파악해보고자 합니다.


1. LSD-SLAM이란?



 LSD-SLAM은 카메라로 들어오는 이미지에서 Feature point를 검출하는 과정을 거치지 않고 바로 사진 자체에서 Semi-Dense를 사용하여 카메라에 감지된 물체의 거리를 가늠하여 이를 SLAM에 적용하는 과정입니다.


사진 출저 : https://medium.com/@j.zijlmans/lsd-slam-vs-orb-slam2-a-literature-based-comparison-20732df431d


 쉽게 설명드리기 위하여 보조자료를 가져와 보았습니다. 위에서 보시는 바와 같이 Feature-Based 방식을 사용하면 카메라로 들어오는 이미지에서 Feature를 추출하는 과정이 추가로 존자하여 LSD-SLAM보다 느릴 수 있다는 단점을 가지고 있습니다.

 물론 ORB-SLAM는 Feature-Based 방식으로 ORB 방식으로 Feature point를 추출하는 과정이 존재하지만 빠른 속도록 Feature를 감지할 수 있어 최근 각광받는 기술이 존재하기도 합니다.


2. Semi-Dense의 의미


 그렇다면 LSD-SLAM의 핵심 기술인 Semi-dense는 어떤 의미일까요? 밀도를 의미하는 dense와 semi의 접두어가 붙었을 때의 의미가 이해되기 쉽지 않으시리라 생각됩니다. 아래 예제를 통해 말씀드리도록 하겠습니다.



만약 다음과 같은 이미지가 있다고 가정합니다. 위 사진을 통해 Dense를 추측하면 아래와 같이 나타낼 수 있습니다.



위 사진에서 파란색의 경우 화면에서 상대적으로 가깝다는 의미이고 빨간색의 경우 화면에서 상대적으로 멀다는 의미로 생각하시면 됩니다. 이를 통해 사진에서 보이는 물체들의 거리를 짐작할 수 있습니다. 이 결과물을  dense depth map이라 하겠습니다.


 하지만 SLAM에서 dense depth를 모두 사용하기에는 상당히 많은 시간이 걸리는 데다가 결정적으로 모든 dense depth가 사용되지 않기 때문에 이를 SLAM에 사용하기엔 매우 부적절하다고 할 수 있습니다.


 그렇다면 이를 좀 더 가볍게 사용할 수 있는 방법은 없을까요? 이 때 semi-depth 라는 개념을 적용해봅니다.



 위 그림은 dense depth map에서 필요하지 않은 부분을 Gaussian 확률 분포를 사용하여 처리하고 남은 부분들을 나타낸 것입니다. Feature-based 방식에서 Feature를 검출하였을 때와 유사한 부분들이 남아있는 것을 볼 수 있습니다.


 즉 모든 dense depth map을 사용하지 않고 일부분만을 사용하기 때문에 (full) dense depth map의 방식에서 일부분만 사용한다는 의미로 semi-dense depth map으로 이름을 붙인 것이지요.


 이러한 특성을 가지고 있는 LSD-SLAM을 사용한다면 좀 더 빠른 방법으로 SLAM을 사용할 수 있을 것으로 기대할 수 있겠습니다.


 - Reference -

https://github.com/tum-vision/lsd_slam

https://ieeexplore.ieee.org/document/6751290

바닷가가 보이는 동해선 도보여행기(좌천역~월내역)(1)[2019.03.09]


 며칠동안 연속으로 미세먼지 문제로 인해 뿌연 하늘 아래 감기와 몸살 등으로 아픈 나날을 보내고 있었습니다. 마침 주말 날씨가 너무나 좋아서 간단하게 여행을 다녀보고자 갑작스레 여행을 다녀오게 되었습니다.


 우리나라에서 열차를 타고 바닷가를 볼 수 있는 구간들이 몇몇 존재합니다. 아마 많은 분들이 강릉에 있는 정동진의 이미지를 많이 떠오르시리라 생각합니다.

 부산 구간에서도 한 때 해운대~송정 이설 전 구간이 열차를 타고 바닷가의 풍경을 만끽할 수 있었던 곳이었습니다. 지금은 이설되면서 철로를 걷어내지 않고 도보 여행지로 남겨두고 있지요.


 이번에는 앞으로 선로가 이설되면서 바닷가를 볼 수 있게 되는 월내역 인근의 바닷가를 보기로 하였습니다. 동해선 좌천역~월내역 구간을 걸어다니며 이곳 저곳 남긴 사진들을 감상해보도록 합시다!



 이번에 여행하면서 걸어다닌 구간을 확인해보니 무려 1시간 넘게 걸어다녔군요. 도보 후기는 다음 포스팅에서 작성하도록 하겠습니다.





여행의 시작은 언제나 동대구에서 시작됩니다. 부전행 열차에 탑승합니다.



태화강역에서 발견한 태화강발 동대구행 열차.

태화강에서 출발하는 열차기 있는 것으로 보아 울산에서 대구로 가는 수요가 어느 정도 있는 모양입니다.



어느덧 좌천역에 도착하였습니다.

보아하니 승강장이 이설된 것 같아 보입니다.



기존의 승강장은 저 너머에 있는 좌천역 인근에 있는 모양입니다.

선로를 이설하기 위해 임시로 승강장을 옮겨 영업을 하고 있습니다.



좌천역의 바로 다음역인 일광역은 일찍이 부산시내까지 광역전철이 개통되었습니다.

곧 있으면 이 곳 좌천역에서도 광역전철을 타고 부산 시내로 갈 수 있게 됩니다.



동대구에서 출발하였던 열차는 좌천역을 떠나 부전역으로 향합니다.



떠나가는 열차를 보며 지난주에 보았던 경원선 통근열차가 떠오르는 이유는 무엇일까요?



좌천역도 조만간 광역전철을 탈 수 있는 역이 지어집니다.



새 역이 완공된다면 이 곳도 곧 없어지겠지요.



이제 역 바깥으로 나가봅니다. 이전에 경춘선 청평역처럼 역까지 나가는데 거리가 있군요.



승강장을 벗어나는 중에 바라본 좌천역 역명판



역 주변에는 온갖 건축자재들이 굴러다닙니다.

전차선을 띄울 기둥도 이렇게 가지런히 누워있군요.



이전에 사용했던 승강장의 흔적입니다. 이 곳도 이렇게 흔적만 남기고 사라지겠지요.



어느덧 역 출입구까지 걸어 나왔습니다.



왠지 간이역에 딱 어울리는 빗자루 두 자루가 보입니다.

이런 빗자루로 전철역을 쓸고 다니는건 조금 위화감이 느껴질 듯 보입니다.



좌천역의 모습은 흔하지만 조금씩 사라져가는 간이역의 모습입니다.



좌천역에서는 생각보다 많은 열차가 정차합니다.

앞으로 광역전철이 개통된다면 한 시간에 2대 이상은 들어오겠지요.



역 바깥의 첫 인상은 온통 주차장 모습입니다.



역 광장에서 새 좌천역이 한창 건설중인 모습을 바라봅니다.



앞으로 좌천역이 이설되면 이 구 역사는 철거될 예정이라고 합니다.



멀지않은 미래에 이 곳은 왠지 주차장이 될 것 같아보입니다.



이제 본격적으로 월내역으로 걸어가보도록 하겠습니다.



기존의 역사와 새로 지어지는 역사를 비교하면 격세지감이라는 말이 절로 나올듯 합니다.

한 편으로는 좀 더 편한 교통환경이 마련되지만 또 다른 한편으로는 또 다른 모습은 사라진다는 것이지요.



새로 지어지는 고가와 기존 구간의 고가의 모습



길을 걷다 건널목 하나를 지나갑니다.



월내역 방향으로 바라본 모습입니다. 왼편으로 새로 이설될 철길이 보입니다.



좌천역을 향해 바라본 모습입니다. 새로 지어지는 역이 한 눈에 들어옵니다.



임시건널목에서는 '월래역'으로 적혀있네요.



철도 건널목을 지나서 부터는 산과 찻길만이 펼쳐집니다.



기존 철길과 새로 지어지고 있는 철길이 동시에 보이는군요.



이 곳에서 낚시를 하시는 분들이 보이네요.

바닷가와 가까운 위치인데 과연 어떤 물고기가 잡힐까요?



30분 정도 걸어가보면 작은 마을에 도착합니다.



작을 마을 사이로 철길 또한 지나갑니다.



마을에 도착하고 나서 부터는 도보가 사라지고 좁은 갓길만 걸어다닐 수 있어 불편해집니다.



길 바로 옆에는 보호수가 떡하니 서있습니다.

이 나무 때문에 길을 확장하지 못하는 듯 보입니다.



좁아터진 길을 피해 다른 길로 가볼까 했더니 마침 저 멀리 바닷가가 보입니다.



2019년이 되어서 처음 보는 바닷가로군요!



좌천역과 월내역 사이에 임랑해수욕장이 위치해 있습니다!



해수욕장을 바라보는 방향으로 놓인 밴치의 모습.

잠시 앉아서 쉬어가고 싶게 생겼습니다.



저 멀리에 원자력발전소가 보입니다.



임랑해수욕장에서 다시 월내역 방향으로 걷다보면 묘관음사라는 절 하나가 있습니다.



절의 입구에서 바라본 바닷가의 모습입니다.

매번 부산을 올 때 마다 항상 처음 오는 해수욕장들 중에 기찻길 바로 옆에서 바닷가를 보기는 미포 이후로 처음인 것 같습니다.



선로가 이설되는 구간에는 센스있게도 미관음사의 입구를 이렇게 잘 꾸며놓았습니다.



절 앞에 이렇게 철길이 지나가는 모습이 한 편으로는 신기한 모습이네요.



임랑해수욕장에는 임랑건널목이 있습니다.



월내역 쪽을 바라본 모습입니다. 이설구간의 모습도 보입니다.



부산역을 향해 바라본 모습입니다. 산 사이를 훓고 지나가는 듯한 모습이네요.



앞으로 사라질 건널목에서 바라본 이설구간의 모습입니다. 이제 이 모습도 곧 사라지겠지요.



 다음 포스팅에서 월내역에 도착하기 까지의 내용을 이어서 올리도록 하겠습니다!

이 장소를 Daum지도에서 확인해보세요.
부산 기장군 장안읍 좌천리 211-1 | 좌천역
도움말 Daum 지도

시골길을 달리는 꼬마열차 이야기 - 경원선 통근열차(대광리~백마고지)[2019.03.01]


 지난 2017년 5월, 경의선과 동해북부선에서 남과 북의 철길이 연결되는 감동의 순간을 기억합니다. 비록 실질적으로는 경의선만 서울까지 연결되어 있지만 단절되었던 철길이 연결되었다는 것 만으로도 상당히 큰 의미를 갖고 있는 것이지요.


 비록 경원선은 현재 철원 백마고지 까지만 연결되어 있지만 머지않아 경원선 또한 북과 연결될 날이 곧 올 것이라 믿고 있습니다. 그렇게 된다면 금강산 까지 기차를 타고 갈 수 있었던 시절로 돌아갈 수 있는 것이지요.

 

 그러나 안타깝게도 경원선 통근열차는 경원선이 복구되는 그 순간에는 이미 폐차가 되어 사라져 버리게 될 것이라는 것이 참으로 슬픈 일입니다. 마치 북녘에 남겨둔 이산가족들이 다시 만나자는 꿈을 이루지 못한 것만 같은 상황처럼 말이지요.


 이번 포스팅에서는 나머지 구간인 대광리역에서부터 현재 경원선 최북단역인 백마고지역 까지 통근열차가 운행하였던 모습을 남겨보기로 합니다.



대광리역 맞이방의 모습입니다. 바로 전 역인 신망리역보다는 확실히 규모가 큰 역입니다.



비록 큰 역이지만 역무원이 없어 승차권을 열차 안에서 직접 구매해야 하는 곳이기도 합니다.

인건비 또한 운영에 있어서 무시할 수 없는 요소다보니 역은 더욱 사람이 없어 보입니다.



대광리역 바깥의 모습입니다. 나름 상권이 갖추어져 있습니다.



한적한 대광리역의 모습입니다.

어르신들께서 벤치에 앉아 쉬고 계시군요.



대광리역 입구 모습입니다. 인사하는 그림이 인상적입니다!



역 입구에서 멀리 바라본 모습입니다. 그래도 나름 큰 편입니다.



대광리역이 가장 인상적인 것은 다름아닌 역 바로 앞에 최신 브랜드의 카페가 마련되어 있던것이었습니다.

휴가나온 군인들이 쓰기에 더 없이 중요한 곳처럼 보입니다!



제 예상대로 많은 군인들이 음료수를 마시기 위해 대기하고 있더라고요.



역에서 좀 더 걸어나가면 거대한 편의점도 있습니다.

아무래도 흔한 시골의 편의점이 그렇듯이 마을 주민들의 슈퍼마켓 역할을 하고 있는 듯 보입니다.



어느덧 열차 시간이 되어 불이나케 역으로 뛰어와 통근열차에 몸을 싣습니다.



출발 전에 전방을 확인하는 차장님의 모습입니다.

통근열차도 수도권 전철처럼 2인 승무인 듯 보입니다.



10년 전에도 이 곳 신탄리역을 방문했던 것이 기억나는데

어느덧 다시 한 번 방문하게 되었군요.



왼편에는 DMZ 트레인이 신탄리역에서 운행대기를 하고 있었습니다.

그나저나 DMZ 트레인도 다음달부터는 운행이 중단되는걸까요?



신탄리역 내리는 곳으로 나가기 직전 바로 왼편에는 작은 쉼터가 마련되어 있습니다.

시 문구가 걸려있군요.



한 때 경원선 최북단이기도 했던 역이다보니 북한의 풍경을 담은 사진들이 몇 장 걸려 있었습니다.

마침 TV에서는 실향민 할아버지의 이야기를 다룬 국제시장이 방송되고 있었더군요.



한때 최북단의 역이기도 해서 인지 역무원이 근무하는 곳이었습니다.

옛모습을 간직한 간이역은 볼 때 마다 정겨운 기분이 감돕니다.



본래 이 자리에는 철도중단점 조형물이 설치되어 있었는데

경원선이 백마고지역까지 연장되면서 철거된 듯 합니다.



최신 코레일의 CI가 적용된 모습입니다.

백마고지역이 개통되기 전 까지는 옛날 역명판이었었지요.



백마고지역에서는 대피선이 없기 때문에 DMZ 트레인은 신탄리역으로 내려와 대기합니다.

대기중에도 시동은 끄지 않아서인지 주변에서 굉음이 들려옵니다.



과연 경원선도 경의선처럼 북으로 연결될 날은 올까요?



DMZ 트레인의 가장 큰 장점은 서울역에서 백마고지역까지 직통으로 올 수 있다는 점입니다.

그러나 통근열차를 개조한 열차인데다 새마을호 특실 요금을 받기 때문에 가격은 썩 저렴하지는 않습니다.



경원선에서 청량리역을 빼고는 아마도 유일하게 고객대개실이 설치된 곳이 이 곳 신탄리역이 아닐까 생각됩니다.

최근에는 작은 간이역에도 이렇게 고객대기실을 만드는 코레일의 배려가 돋보입니다.



이제 백마고지역으로 이동해보도록 합시다.



터널을 뚫고 나오면 넓디넓은 철원평야갸 펼처지다가 백마고지역에 도착합니다.



21세기에 처음으로 등장한 간이역의 스타일은 매우 적절한 모습입니다.

요즘처럼 몇 명 없는 시골역에 거대한 역을 지어서 예산낭비를 하느니

필요한 시설만 갖춘 백마고지역이 수요를 받아내는데 적당하다는 생각이 듭니다.



자세히 보니 백마고지역에서 출발하는 열차는 신탄리행으로 적혀 있습니다.

왜 굳이 동두천행으로 적어두지 않았는지 조금은 의야합니다.



간이역 주제에 큰 규모의 주차장이 마련되어 있습니다.

6.25 전쟁 이후 철원에 개통된 최초의 역이라는 상징성 때문인지 관광객도 많이 이 곳을 찾아오는듯 합니다.



백마고지역 주변에는 마을 조차도 멀리 떨어져 있어 역세권은 전혀 갖추어져 있지 않은 곳입니다.

오직 관광객만을 위해 존재하는 역이라는 것이지요.



백마고지역 출입구의 모습입니다.

사실상 매표 업무를 하지 않기 때문에 악천일 때에만 이용되는 대기실이라 할 수 있겠습니다.



역의 끝자락에는 철도중단점 조형물이 설치되어 있습니다.

한 컨에는 북녘으로 보낼 수 있는 우체통이 마련되어 있습니다.



조금 아쉬운 점이 있다면 철원 시내까지는 철도글 개통했으면 어떨까 하는 생각이 듭니다.

차후 철원역 재건 이후 시내 방향으로 철길을 이을 계획이 있는 것으로 보입니다.



동두천역과 백마고지역을 오가는 통근열차의 마지막 모습. 과연 어떤 모습일까요



운행을 위해 승무원께서 열차 안을 청소 하고 계십니다.



CDC 통근열차의 제작사가 대우중공업이었다니...

현재는 철도 제작은 현대로템이 맡고 나머지는 두산인프라코어가 되었다고 하지요.

순간 이 열차가 얼마나 오랫동안 사용되었는지 감이 오지 않습니다.

정말 오래 된 열차였다는 사실이 놀랍기도 합니다.



그래도 열차는 전체적으로 장항선에서 말년을 보낸 새마을호보다는 상태가 좋았습니다.

이 대로 몇 년은 더 다닐 줄 알았는데 사라진다는게 참으로 아쉽기만 합니다.



여행을 마치고 동두천역으로 돌아왔습니다.



그렇게 동두천역에서 통근열차의 마지막 순간을 지켜보며

백마고지가 새겨진 승차권을 주머니에 담고 다시 현실로 돌아갑니다.


비록 옛모습이 하나둘씩 역사속으로 사라지지만

이러한 오늘을 사는 우리들에게는 이를 추억속으로 남겨둘 수 있다는 것이 유일합니다.

이제 이 구간을 돌아다니던 열차는 교과서에만 남게 되겠지만

이후 북녘으로 힘차게 달릴 열차를 상상해 본다면 이 또한 얼마나 두근거리는 설레임일까요?

시골길을 달리는 꼬마열차가 원산까지 달릴 수 있는 그 날을 기약하며 글을 마쳐봅니다.


2019년 3월 1일 다녀옴

2019년 3월 11일 작성


시골길을 달리는 꼬마열차 이야기 - 경원선 통근열차(신망리역)[2019.03.01]


 어느덧 경원선 통근열차의 운행종료일이 20일 앞으로 다가왔습니다. 어느덧 경원선에서 시한부 인생을 살고 있는 통근열차를 보면서 안타까운 마음만이 가득한 나날을 보내고 있습니다. 그렇게 소중한 하루하루가 지난다는 생각을 하면 오늘 하루도 더 열심히 살아보고자 하는 생각이 들기도 하네요!



동두천역에서 신탄리까지 운행하는 39-2번 버스를 타고 경원선을 구경해보기로 했습니다.



소요산역에서 버스가 전동차가 도착하기를 기다린 후 내린 손님들을 기다리고 있습니다.

그렇게 사람들이 소요산역에서 하나둘 나오고 버스는 손님들을 태우고 신탄리를 향해 갑니다.


그렇게 저는 신망리역 인근 버스정류장에서 하차합니다.





신망리역 인근 마을은 철길과 거의 붙어 있는 모습입니다.



선로 바로 옆에 붙어있는 마을들을 보니 군산에 있던 철길마을의 모습이 떠오릅니다.

그곳은 아예 한 마을을 관통하던 모습이었지요.



저 멀리 신망리역의 모습이 보입니다.



아직 열차가 지나가지 않는 시간에는 상당히 조용한 동네입니다.



철도 건널목 바로 옆에는 조그마한 신망리역이 자리잡고 있습니다.



연천 관광객들을 위한 지도와 태풍전망대의 모습을 담은 돌이 서 있습니다.



신망리역의 고객대기실(?)의 모습입니다.

주변 동네 주민들의 작은 모임터 역할을 하는 듯 합니다.



백마고지행 방향을 바라본 모습

철길이 쭉쭉 뻗어있는 모양입니다.



현재 연장중인 전동열차는 연천역까지만 공사가 진행중입니다.

연천역까지 전철이 개통된다면 이 곳 주민들은 이 역을 자주 사용하지는 않을 듯 보입니다.



역 크기가 아담하다 보니 화장실 크기 또한 아담한 모습입니다.



역 앞에는 바로 한 민가가 위치해 있습니다.

흰식 강아지가 낮선 저를 보고 경계하는 모습입니다.



놀랍게도 신망리역의 입구 모습입니다.

역세권 치고는 너무나 초라한 모습입니다.



역 바로 앞에는 어떠한 가게도 없이 민가가 자리잡고 있습니다.

이 쯤 되면 3초 역세권이랄까요?



신망리역의 입구입니다.

확실히 운영중인 역 치고는 너무나 초라해 보입니다.



한국철도공사의 안내판은 아무것도 붙어 있지 않습니다.

역장이 상주하지 않아서 그런 듯 보입니다.



역 내부는 상당히 잘 꾸며져 있었습니다. 마을 주민들이 꾸며놓은 듯 보입니다.



탁자 위에 올려진 신문은 최근 날짜 인걸 보니 방문자는 종종 있는 듯 보입니다.



역무실은 주민들의 미술관으로 단장되어 있는 듯 보입니다.



역무원실 반대편에는 실제 주민들이 미술을 배우는 장소인 듯 보입니다.



확실히 신망리역은 역무 기능보다는 주민들을 위한 예술 공간으로 탈피한 모습입니다.



신망리의 역사를 기록한 모습입니다.

연천에서 가장 먼저 다방이 들어온 곳이라고 하네요!



열차 타는곳을 바라본 모습입니다.

저 곳으로 열차가 들어옵니다.



아까도 보았듯이 역무실은 주민들의 공간으로 평소에는 잠겨있습니다.



침목 위헤 주민들의 작품이 붙어 있습니다.

확실히 주민들의 관리를 받는 덕인지 역의 분위기는 상당히 친근감이 듭니다.



신망리역의 열차시간표입니다.

최근 시내버스보다 저렴한 요금 덕에 통근열차는 적자를 면치 못하는 신세가 되었다지요.



신망리역의 역명판 앞에 벤치가 이를 지탱하고 있는것처럼 보이네요.



뭔가 투박하지만 이런 모습이야 말로 간이역을 방문하는 재미가 아닐까요?



열차 시간이 다가오자 마을 주민들이 신망리역으로 하나 둘 모이기 시작합니다.



어느덧 건널목이 경고음을 내더니 차단기가 내려옵니다.



건널목의 경고음과 함께 저 멀리서 통근열차가 달려옵니다.



마을 사이를 달리는 열차의 모습.

이제 이 모습도 추억의 한켠에 남게 되는군요.



열차는 덜컹거리는 소리와 함께 주민들이 기다리는 역으로 들어옵니다.



신망리역에 그렇게 열차가 도착하고

주민들은 하나 둘 객실에 들어갑니다.



연천 시내로 달리는 통근열차의 모습입니다.

자리별로 손님을 채울 정도니 나름 열차로서의 일은 잘 하고 있어 보입니다.



연천역을 지나 전곡역으로 가는 길목에서 새로운 철길이 깔리는 모습을 목격할 수 있었습니다.

그런데 최근 뉴스에서 어느 땅 주인의 허가 없이 철길이 깔려 소송이 진행중이라는 이야기를 들었는데

그 때문인지 현재 경원선 공사는 지연되고 있다고 하네요.

부디 좋게 해결되고 이 곳에서도 열차들이 달리는 모습을 하루 빨리 볼 수 있었으면 합니다!




이 장소를 Daum지도에서 확인해보세요.
경기도 연천군 연천읍 |
도움말 Daum 지도

C++ 클래스 객체를 stream으로 통신 및 전달방법 - Boost Serialization(2) [Class를 TCP 소켓 통신으로 전송]

공대생의 팁 2019.03.08 00:09
 이전에 Java를 사용하여 Object(객체)를 소켓 통신으로 전송하는 방법에 다루었던 적이 있었습니다. 확실히 Java는 이러한 기능이 구현되어 있어 프로그래밍을 하는 데 있어 상당히 훌륭한 기능을 수행합니다.

안드로이드 - Java 서버간 Object 객체 소켓 프로그래밍
https://elecs.tistory.com/147


 그러나 C++의 경우 아직까지 Java처럼 객체를 전송함에 있어 불편한 점이 있습니다. C를 사용할 경우 전송하기 위해 사용되는 Struct의 크기를 직접 확인하여야 하며 대용량 파일의 경우 한정된 버퍼의 크기에 맞추어 분리하여 전송하여야 하기 때문에 고려해야할 점이 상당히 많습니다.

 C++ 라이브러리 중 하나인 Boost에서는 향상된 소켓 프로그래밍인 ASIO와 Class를 직렬화 할 수 있는 Serialization을 제공합니다. 이름에서 볼 수 있듯이 Serialization를 사용하여 C++의 클래스를 직렬화 하여 Byte 형태로 변환할 수 있기 때문에 이를 다른 컴퓨터에 전송한 후 이를 역직렬화(De-serialization)하여 전송 받은 컴퓨터에서도 똑같은 Class 변수를 생성할 수 있게 되는 것입니다. 자세한 이야기는 아래의 링크를 참조해주시기 바랍니다.

C++ 클래스 객체를 stream으로 통신 및 전달방법 - Boost Serialization(1) [직렬화된 클래스 만들기]
https://elecs.tistory.com/289



 또한 이번 포스팅에서는 TCP 비동기 통신을 사용하여 class 객체값을 전달받는 과정이 구현되어 있습니다. 이와 관련된 정보에 대해 자세히 알고자 하시는 분들께 아래 링크를 참조해주시길 바랍니다.

C++에서 Boost ASIO를 사용하여 TCP 비동기(Unblocked) 통신 프로그래밍
https://elecs.tistory.com/314


 이번 프로그램의 경우 소스코드의 양이 크기 때문에 일부분을 설명하는 방식으로 진행하겠습니다. 먼저 아래에 자신의 환경에 맞는 소스코드를 다운로드 받습니다.

Ubuntu 18.04 버전 이전(Boost 1.65 버전 이전)

asio_serialization_1804.zip


Ubuntu 18.10 버전 이후(Boost 1.66 버전 이후)

asio_serialization_2004.zip


 위 소스코드의 알고리즘은 다음과 같이 구성되어 있습니다.



 서버측에서 stock라는 struct 타입의 object를 가지고 있으며 이를 Serialization하여 Binary 파일로 변환한 후 Server는 Client의 접속을 accept할 준비를 합니다. 서버에서 이와 같은 과정이 완료되면 client에서 connect를 요청합니다.

 client로부터의 connect 요청을 받은 server는 write를 하여 client에게 직렬화 된 object를 수신받습니다. 이후 handler에 등록된 handle_read 함수가 실행되어 수신된 Binary 파일을 역직렬화 한 후 이를 server에서 사용하던 대로의 파일 형식으로 되돌려놓는 방식입니다.



위 소스코드를 다운로드 받으신 후 해당 폴더에서 다음과 같은 명령어를 입력합니다.


$ mkdir build

$ cd build

$ cmake ..

$ make


 위와 같이 실행하셨을 경우 server와 client라는 이름의 실행 파일이 생성됩니다. 해당 파일들은 각각 다음과 같은 명령어로 실행하실 수 있습니다.

$ ./server 포트번호
$ ./client 서버IP 포트번호

 이와 같이 실행하면 client 화면에서 다음과 같은 결과를 확인하실 수 있습니다.






C++에서 Boost ASIO를 사용하여 TCP 비동기(Unblocked) 통신 프로그래밍

공대생의 팁 2019.03.07 23:04
 C++에서 소켓 통신을 할 때 동기식(Blocked, sync)과 비동기식(Unblocked, async)방식으로 TCP 통신을 구현합니다. 그러나 Java에 비교하였을 때 C에서 기본으로 제공하는 socket 프로그래밍을 사용하는 것은 여간 불편한 일이 아닙니다.

 이러한 환경에서 Boost 라이브러리에서 제공하는 ASIO 소켓 통신 프로그램을 사용하게 되면 이전보다 코딩 환경이 매우 쾌적함을 경험할 수 있습니다.

 이번 포스팅에서는 Boost 라이브러리에서 제공하는 ASIO를 사용하여 Unblock(Asynchronization)방식의 소켓 통신 프로그램을 구현해 보았습니다.


 위 그림은 Boost library에서 ASIO의 비동기(Asynchronization)방식의 소켓 통신 프로그래밍의 알고리즘을 나타낸 것입니다.

 프로그램을 실행하게 되었을 때 Socket에 IP주소와 Port 번호를 등록하고 이를 io_service(1.66 버전 이후에서는 io_context)에 이 때 handle_connect, handle_read, handle_write와 같은 handler 또한 함께 등록합니다. 이 때 등록된 handler는 server 혹은 client에서 실행되었을 때 바로 handler를 실행하는 방법으로 어느 한 쪽으로부터 데이터 전달을 기다리지 않고 있다가 요청이 들어왔을 때 실행하는 것이지요.

 시작하기에 앞서 Ubuntu 환경에서 다음과 같이 Boost 라이브러리를 설치합니다.

$ sudo apt install libboost-all-dev

자세한 내용은 소스코드의 주석을 통해 설명을 달아보았습니다.

server.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
 
using boost::asio::ip::tcp;
using namespace std;
 
class session
{
public:
  session(boost::asio::io_service& io_service)
  //boost 1.66이후 (Ubuntu 18.10 이후) 버전의 경우 io_context를 사용
  //session(boost::asio::io_context& io_service)
    : socket_(io_service)
  {
  }
 
  tcp::socket& socket()
  {
    return socket_;
  }
 
  void start()
  {
    //client로부터 연결됨
    cout << "connected" << endl;
    //client로부터 비동기 read 실행
    socket_.async_read_some(boost::asio::buffer(data_, max_length),
        boost::bind(&session::handle_read, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }
 
private:
  void handle_read(const boost::system::error_code& error,
      size_t bytes_transferred)
  {
    if (!error)
    {
      cout << data_ << endl;
    }
    else
    {
      delete this;
    }
  }
 
  tcp::socket socket_;
  enum { max_length = 1024 };
  char data_[max_length];
};
 
class server
{
public:
  server(boost::asio::io_service& io_service, short port)
  //boost 1.66이후 (Ubuntu 18.10 이후) 버전의 경우 io_context를 사용
  //server(boost::asio::io_context& io_service, short port)
    : io_service_(io_service),
      //PORT 번호 등록
      acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
  {
    start_accept();
  }
 
private:
  void start_accept()
  {
    session* new_session = new session(io_service_);
    //client로부터 접속될 때 까지 대기한다.
    acceptor_.async_accept(new_session->socket(),
        boost::bind(&server::handle_accept, this, new_session,
          boost::asio::placeholders::error));
  }
 
  //client로부터 접속이 되었을 때 해당 handler 함수를 실행한다.
  void handle_accept(session* new_session,
      const boost::system::error_code& error)
  {
    if (!error)
    {
      new_session->start();
    }
    else
    {
      delete new_session;
    }
    //client로부터 접속이 끊겼을 대 다시 대기한다.
    start_accept();
  }
 
  boost::asio::io_service& io_service_;
  //boost 1.66이후 (Ubuntu 18.10 이후) 버전의 경우 io_context를 사용
  //boost::asio::io_context &io_service_;
  tcp::acceptor acceptor_;
};
 
int main(int argc, char* argv[])
{
  try
  {
    if (argc != 2)
    {
      std::cerr << "Usage: async_tcp_echo_server <port>\n";
      return 1;
    }
 
    boost::asio::io_service io_service;
    //boost 1.66이후 (Ubuntu 18.10 이후) 버전의 경우 io_context를 사용
    //boost::asio::io_context io_service;
 
    server s(io_service, atoi(argv[1]));
    //asio 통신을 시작한다.
    io_service.run();
  }
  catch (exception& e)
  {
    cerr << "Exception: " << e.what() << "\n";
  }
 
  return 0;
}
cs

client.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<boost/asio.hpp>
#include<boost/bind.hpp>
 
using boost::asio::ip::tcp;
using namespace std;
 
enum { max_length = 1024 };
 
class client
{
public:
  client(boost::asio::io_service& io_context,
  //client(boost::asio::io_context& io_context,
      const string& host, const string& port) : socket_(io_context)
  {
    boost::asio::ip::tcp::resolver resolver(io_context);
    boost::asio::ip::tcp::resolver::query query(host, port);
    boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
 
    //비동기(Unblock) 상태로 서버와 접속한다.
    boost::asio::async_connect(socket_, endpoint_iterator,
        boost::bind(&client::handle_connect, this, boost::asio::placeholders::error));
  }
 
  void handle_connect(const boost::system::error_code& e){
    if(!e){
      cout << "Connected!" << endl;
      string msg = "Hello! Server!";
      //Server로부터 비동기 write를 시도한다.
      boost::asio::async_write(socket_, boost::asio::buffer(msg, msg.length()),
          boost::bind(&client::handle_write,this,boost::asio::placeholders::error)); 
    }
  }
 
  void handle_write(const boost::system::error_code& e){
    if(!e){
      cout << "Done!" << endl;
    }
  }
 
private:
  tcp::socket socket_;
  char data_[max_length];
};
 
int main(int argc, char* argv[])
{
  try
  {
    // Check command line arguments.
    if (argc != 3)
    {
      std::cerr << "Usage: client <host> <port>" << std::endl;
      return 1;
    }
 
    boost::asio::io_service io_context;
    //boost::asio:io_context io_context;
    client c(io_context, argv[1], argv[2]);
    io_context.run();
  }
  catch (std::exception& e)
  {
    cerr << e.what() << endl;
  }
 
  return 0;
}
cs

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cmake_minimum_required(VERSION 3.0)
 
project(asio_async)
find_package(Boost REQUIRED system)
find_package(Threads)
 
include_directories(${Boost_INCLUDE_DIR})
 
add_executable(client
    client.cpp
)
 
add_executable(server
    server.cpp
)
 
target_link_libraries(client
    ${Boost_LIBRARIES}
    ${CMAKE_THREAD_LIBS_INIT}
)
 
target_link_libraries(server
    ${Boost_LIBRARIES}
)
cs


Linux 환경에서 위의 3개의 소스코드를 한 폴더에 넣으신 후 다음과 같이 실행합니다.


$ mkdir build

$ cd build

$ cmake ..

$ make


 위와 같은 과정을 거치면 client와 server라는 실행파일이 build 폴더 안에 생성됩니다. 이 두 프로그램을 실행하면 다음과 같은 결과가 나옵니다.


1
2
3
4
$ ./server 2580
 
Connected!
Hello! Server!
cs



1
2
3
4
./client 127.0.0.1 2580
 
Connected!
Done!
cs


관련 자료

C++에서 Boost ASIO를 사용하여 TCP 동기화(Blocked) 통신 프로그래밍

https://elecs.tistory.com/332

  • Wordbe 2019.06.09 04:04 신고 ADDR 수정/삭제 답글

    도움이 되었습니다 감사합니다.

  • 나그네 2019.08.06 15:09 ADDR 수정/삭제 답글

    클라이언트는 일회성인가요? 한번읽고 닫고
    다시 연결하고 쓰고 닫고..

    • Justin T. 2019.08.06 15:34 신고 수정/삭제

      서로 연결된 소켓이 한 쪽에서 close를 하게 되면 반대편의 소켓에서 통신이 종료되었다는 signal을 보내어 종료 요청을 합니다. 즉 한 쪽에서 통신을 종료하게 되면 양쪽의 소켓은 사용이 종료됩니다. 그러므로 양측이 다시 통신을 하기 위해서는 소켓을 다시 열어야합니다.
      자세한 내용을 알고 싶으시다면 아래의 링크를 참고해주세요.
      https://sunyzero.tistory.com/m/167

  • 나그네 2019.08.06 17:18 ADDR 수정/삭제 답글

    답변 감사합니다.
    소켓이 뭔지도 잘 모르고 프로그래밍은 무리였네요.

    한가지 더 질문이 있는데,
    보통 소켓통신은 1:1접속후 클라이언트가 서버에 무엇인가 요청을 하고, 서버는 요청 데이터를 보내주는것 같은데 맞나요?

    항상 모든 예제가 클라이언트는 write만 있어서 어떤식으로 구성할지 막막하네요
    보통 핸들러에는 어떤걸 구현하나요?

  • Justin T. 2019.08.06 18:50 신고 ADDR 수정/삭제 답글

    클라이언트와 서버가 소켓으로 연결되면 상호간에 데이터를 주고 받는것이 가능합니다.
    핸들러에서는 클라이언트 혹은 서버가 연결된 상대에게 데이터를 보냈을 때 이를 메인스레드와는 독립적으로 동작시키기를 원할 때 따로 구현한 것이라고 할 수 있겠습니다.

    • 나그네 2019.08.07 13:41 수정/삭제

      감사합니다.
      그럼 한가지 질문이 있는데,
      https://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/chat/chat_client.cpp
      예제에서 보이듯
      클라이언트가 한번 커넥트가 되면, 그 뒤로 계속 읽기 모드로 동작합니다.
      handle_connect -> handle_read_header -> handle_read_body -> header -> body ...
      이처럼 read 는 항상 읽고 있는 상태여야, 다른 소켓에서 데이터를 보낼때 반응을 할 수 있는게 맞는건가요?

    • Justin T. 2019.08.16 15:03 신고 수정/삭제

      정확히 말씀드리자면 handler를 사용하여 상대방에서 데이터를 보냈다는 신호가 오는지 기다리다가 소켓과 연결된 상대가 데이터를 보내는 것이 감지되면 handler가 이를 수신하고 이를 read로 읽은 것이라고 할 수 있겠습니다.

시골길을 달리는 꼬마열차 이야기 - 경원선 통근열차(전곡역)[2019.03.01]


 언제나 사라지는 것을 사진으로 남길 때마다 사라져가는 추억은 아쉬움이 남습니다. 그러한 추억들을 남기기 위해서 이렇게 사진이라도 한 장 더 남기고 싶은 마음이랄까요?


 이번에는 전곡역 주변을 돌아다니며 여러 모습들을 사진으로 남겨보았습니다.




점심시간 무렵 전곡역에 도착하였습니다.



나름 전곡읍내에 위치한 곳이다 보니 역무원이 상주하고 계시군요.



전곡역 대기실에서 타는곳을 바라본 모습입니다.



전곡역의 모습입니다. 바로 옆의 시계탑이 보입니다.



읍내를 좀 더 들어가서 바라본 모습입니다.



동네 안을 걸어다니다가 역 근처 건널목까지 걸어오게 되었습니다.



희안하게도 건널목 옆에는 육교가 우뚝 서있습니다.

현재 이 육교는 입구가 봉쇄되어 있습니다.



열차가 지나갈 시간이 임박해서인지 관리인이 밖으로 나와계십니다.



또 한분은 건너편으로 넘어가 준비하고 계십니다.



건널목에서 바라본 전곡역의 모습



관리하는 분들께서 계신 대기실에 장치가 설치되어 있습니다.

이 것을 조작하여서 차단봉을 잠시 올려 통행할 수 있게 해주십니다.



연천역 쪽에서 오는 열차를 기다리고 있었는데 생각치도 못하게 서울쪽에서 DMZ 트레인이 지나갑니다.

DMZ 트레인을 서울역에서 백마고지까지 입석으로 타고 갔다온 적이 있었는데 생각보다 탈 만합니다.



물론 DMZ 트레인 또한 베이스는 통근열차이기 때문에

특유의 디젤 모터의 진동을 이 열차에서도 느낄 수 있습니다.



그렇게 DMZ Train이 전곡역을 통과하고 뒤이어 대기중이던 통근열차가 전곡역을 떠납니다.



방금전에 DMZ 트레인이 지나갔던 건널목을 통근열차 또한 빠르게 지나갑니다.



이제 다음달 부터는 이 광경은 더이상 볼 수 없다는게 참 아쉽기만 합니다.



이제 꽤 오랫동안 돌아다녔으니 전곡역 인근에서 점심을 먹기로 하였습니다.




해장국집에서 주는 고기 양이 상당히 푸짐하여 좋았습니다.



다시 전곡역으로 돌아옵니다.



집표함에 철도청 시절의 로고가 보이는군요.



열차가 출발하기 약 10분 전부터 역무원께서 표를 팔기 시작합니다.

지금 봐도 확실히 통근열차의 운임은 상당히 저렴합니다. 그동안 물가가 오르는 동안에도 그대로였으니 말이죠.



동두천에서 출발한 열차가 전곡역으로 들어옵니다.



과연 이 곳에 수도권 광역철도 1호선이 들어온다면 어떻게 변화할까요?



열차가 멈추자 많은 사람들이 열차를 오르내립니다.

확실히 사람들이 많이 거주하는 곳이다보니 타는 사람은 확실이 많습니다.




이 장소를 Daum지도에서 확인해보세요.
경기 연천군 전곡읍 전곡리 308-6 | 현대 뼈다귀해장국
도움말 Daum 지도

시골길을 달리는 꼬마열차 이야기 - 경원선 통근열차(초성리~한탄강)[2019.03.01]


 평소같이 지내던 어느날 코레일 홈페이지 공지사항을 보게 되었습니다. 다름 아닌 경원선 통근열차가 올해부터 운행이 중단될 예정이라는 소식이었습니다.



 그렇게 또 하나의 기억이 현실에서 사라져가게 된다는 안타까운 소식을 듣고 경원선 끝자락까지 다녀와 보았습니다.



통근열차를 타고 초성리역에 도착하였습니다. 역에서 내린 손님은 저 한 사람 뿐이더군요.



열차는 저만 이 곳에 내려다놓고 역을 떠납니다.



소요산역을 떠나자마자 가장 먼저 우리를 맞이하는 초성리역입니다.



아직까지 경기도에서 이러한 모습의 운영중인 간이역을 본다는 것은 종종 신기한 일입니다.



물론 바로 다음역인 소요산역까지 통근열차보다는 버스를 이용해 한승하는 사람들이 많기 때문에

승차권을 발권해주는 역무원은 근무하지 않고 있습니다.



경원선 통근열차가 다니는 구간의 역들에는 다음과 같이 역을 소개하는 안내문이 붙어있습니다.



역 입구에서 바라본 모습.



역앞의 모습만 봐도 사람들이 거의 이용하지 않을것 같이 작아보입니다.



역 인근 건널목에서 바라본 초성리역의 모습



역 바로 앞 슈퍼에 고양이 한 마리가 문 앞에서 낮잠을 곤히 자고 있습니다.



이 정도 규모의 역은 부산에 있는 사상임시역과 조금 비슷한 크기인 것 같습니다.



열차타는곳 출입문과 열차시간표



지역에 있는 시골역이서도 구경하기 힘든 집표함이 보입니다.



초성리역의 플랫폼 모습입니다. 저 멀리 시멘트 사일로가 보입니다.



가로등에 붙어있는 초성리역 역명판



동두천~연천 구간 공사를 위한 사무실이 있군요.



어느덧 역에서는 열차가 들어온다는 안내가 들려오고



소요산에서부터 출발하는 열차가 다가옵니다.



백마고지행 통근열차가 역으로 들어옵니다.



다음역인 한탄강역을 떠나가는 통근열차



열차는 유유히 한탄강철교를 건너 초성리역으로 건너갑니다.



바로 옆 다리의 태극기의 무리가 상당히 인상적입니다.

특히 3.1절에는 더욱 와닿는 모습입니다.



임시역인 한탄강에도 집표함이 설치되어 있었군요.



집표함 안을 살펴보았는데 생각보다 많은 승차권이 들어있었습니다.



비록 역건물은 없지만 갖출 시설은 모두 가지고 있는 역의 모습입니다.



한탄강역 역명판의 모습입니다.

간체자와 일본어 표기로 보아 역명판을 최근에 다시 만든 것으로 보입니다.



그 옆에는 버스정류장 같이 생긴 대기공간이 마련되어 있습니다.



열차시간표는 간단하기 생겼습니다.



한탄강역에도 역에 대한 정보가 걸려있습니다.



역 밖을 나오면 바로 도로가 보입니다.



진짜 역 바깥에 있는 눈에 보이는 건물은 버스정류장이 다입니다.



방금 보았던 태극기가 휘날리는 도로의 모습입니다.

38선 이북이다 보니 상징성이 매우 강한 곳이라 할 수 있겠습니다.



아까 그 버스정류장에서 바라본 한탄강역의 모습입니다.



이 역명판만이 이 곳이 한탄강역임을 알리고 있습니다.

이전의 역명판에는 글자가 떨어져 나갔었는데 그래서 새로 역명판을 달아둔 듯 보입니다.



한탄강역 주변을 걸어다니면 상당히 좋은 풍경을 감상할 수 있습니다.



한탄강철교가 높게 뻗은 모습 또한 은근 주변 풍경과 어울려 보입니다.



한탄강역 인근에 캠핑장이 있어 가족 단위의 여행객들이 자주 눈에 들어옵니다.



이제 전곡역으로 이동하기 위해 한탄강역으로 돌아옵니다.



사실 한탄강역은 2019년 3월 30일을 끝으로 더이상 열차를 탈 수 없게 됩니다.

선로 자체가 직선화되어 이설되기 때문에 이 곳을 지나가지 않게 되었기 때문이지요.



볼 때 마다 느끼지만 통근열차의 운전실은 객차간 통로와 비슷하게 생겼습니다.

그래서 승객들이 착각하고 문을 열려고 하곤 합니다. 기관사분이 깜짝 놀라시지는 않을까 합니다.


https 차단을 우회하는 방법 - GoodbyeDPI [2019.02.13]

공대생의 팁 2019.02.13 16:07


 블로그를 운영하면서 생각하였던 목표 중 하나는 방문하는 분들께서 조금이나마 도움을 드리고자 하는 방향으로 글을 쓰는 것이었습니다. 비록 제가 공부하는 분야들 중에서 인터넷에서 자세히 나오지 않는 부분에 대한 글들이 대부분이라 방문하는 모든 분들께 만족할 수 없기에 조회수는 제가 쓴 글들이 하루에 한 개씩 읽히는 정도로 생각해왔지요.


 그러던 어느날 정말로 깜짝 놀랄 만한 일이 벌어졌습니다.



 무려 3년 전에 작성하였던 글의 조회수가 갑자기 폭등하는 상황이 벌어진 것입니다. 제가 작성하였던 글이지만 대체 무슨 논란이 벌어져서 이런 현상이 일어났는지 생각해보니 최근 몇몇 해외 사이트가 접속되지 않는 현상이 나타난다는 이야기를 친구로부터 들었던 것이 기억이 났습니다.


 도대체 무슨 상황이길래 우리나라의 인터넷 세상에서 이토록 난리가 난 것일까요?


 우선 이를 설명하기 위해 우리는 https의 원리에 대해 알아보도록 하겠습니다.



 기존의 http는 컴퓨터 간의 정보를 교환하는 프로토콜(Protocol) 역할을 합니다. http는 초창기에 만들어진 연결이다 보니 암호화가 되어 있지 않아 보안이 매우 취약합니다.




 반면 https의 경우 기존 http에 TLS(SSL) 암호화가 적용되어 데이터 전송의 매체인 패킷(Packet)을 암호화하여 이를 도중에 감청을 시도하더라도 암호를 해독하기 위한 key가 없으면 내용을 알아낼 수 없도록 설계되어 있습니다. 그렇기에 특정 사이트를 차단을 시도한다 하더라도 이를 막을 수 있는 방법이 없었던 것입니다.


 그런데 이러한 https 프로토클을 막을 수 있는 방법이 하나 있습니다. 바로 DNS Spoofing을 사용하는 것이지요.



 이번 https 차단 사태에서 사용된 방법으로 우리가 인터넷으로 접속할 때엔 해당 서버의 IP주소를 사용해야 하지만 숫자로 되어 있는 주소를 외우기엔 어렵기 때문에 이를 도메인 (예를 들어 https://elecs.tistory.com) 을 입력하면 DNS 서버가 해당 도메인의 IP 주소를 사용자에게 가르쳐 줌으로서 원하는 사이트에 접속할 수 있는 것이지요.

 그런데 이러한 역할을 해주는 DNS 서버를 변조하여 다른 사이트로 바꿔버리면 사용자는 해당 홈페이지에 접속할 수 없는 상황이 벌어집니다. 만약 해당 사이트가 인터넷뱅킹 사이트였는데 해커가 보이스피싱 사이트로 DNS를 변조한다면 막대한 피해가 생기는 것이지요.


 


 문제는 앞으로 이보다 더 나아가 SNI(Server Name Indication) 필드를 감청하여 차단하는 방식을 적용하게 되면 이는 통신보호법 제 5조 2항이 '헌법불합치' 판정으로 인해 헌법에 위배되는 행위가 됩니다. 만약 이를 허용하게 된다면 타인이 자신이 접속하는 사이트를 알 수 있으며 이는 매우 심각한 인권 침해가 될 수 있다는 것이지요.

 이러한 상황이 염려되기 때문에 많은 사람들이 국민청원으로 목소리를 내고 있는 것이지요. 그렇다면 지금 상황에서 https가 차단된 해외 사이트 접속은 불가능한 것일까요?


 현재의 상황에서 차단된 해외 사이트에 접속할 수 있는 방법으로 러시아 개발자가 만든 GoodbyeDPI를 사용하여 심층 패킷 감청(Deep Packet Inspection)을 피하는 것입니다. 흔히 우리나라에서 불법 사이트에 접속하였을 때 나타나는 Warning 사이트의 원리가 DPI를 사용하는 것인데 이를 우회하는 것이지요


 먼저 GoodbyeDPI 공식 사이트에 접속하여 프로그램을 다운로드 받습니다.


https://github.com/Include-sys/GUI-for-GoodbyeDPI


 접속하시면  아래와 같은 화면이 나타나는데 자신의 컴퓨터 환경(32비트 or 64비트)에 해당되는 링크를 클릭하여 다운로드 받습니다.



 프로그램이 인터넷 접속에 영향을 주기 때문에 보안경고가 나타납니다. '자세히' 버튼을 눌러 실행 버튼을 누르면 실행 전 경고 화면이 나타납니다. 해당 화면에서도 실행 버튼을 눌러주면 GoodbyeDPI 프로그램을 실행하실 수 있습니다.




 위와 같은 화면이 나오면 빨간색으로 표시된 버튼을 누르면 프로그램이 실행됩니다. 이제 https 차단을 우회하여 해외 사이트에 접속하실 수 있습니다.



 이 프로그램의 문제점으로 창을 닫는다고 해서 프로그램이 종료되지 않습니다. 작업 관리자(ctrl+alt+delete) 버튼을 눌러 직접 프로세스를 선택한 후 '작업 끝내기'를 눌러 프로그램을 완전히 종료시킵니다.



Co-visibility graph(공가시성 그래프)

공대생의 팁 2019.01.22 01:34


 로보틱스에서 motion planning을 하게 될 때 visibility graph(가시성 그래프)를 사용하는 경우가 있습니다. visibility graph란 로봇이 이동을 할 때 자신의 앞에 보이는 장애물을 어떻게 하면 회피해서 갈 수 있는지에 대해 알 수 있는 방법을 고안하는 단계에서부터 시작하게 됩니다. 설명하기에 앞서 간단한 그림을 사용하여 설명해드리겠습니다.



 위 그림은 두 개의 직사각형 모양의 장애물이 있고, 로봇은 검은 점과 붉은 점을 이동해야 하는 상황을 나타낸 것입니다. 먼저 로봇이 지나갈 수 있는지를 visibility graph를 그려 확인하는 과정으로 시작점과 도착점에서 장애물까지 직선으로 선을 긋습니다. 위 그림에서 파란색으로 그려진 부분에서 시작점과 도착점의 visibility graph가 만나고 있음을 알고 있습니다. visibility graph를 그릴 때 주의할 점은 점에서부터 시작되는 visibility graph는 곡선이 될 수 없으며 도달하는 부분까지 직선으로 이어져 있어야 한다는 점입니다.


 이번 포스팅에서 설명하게 될 co-visibility graph(공가시성 그래프)를 이해하기 위해 사전지식으로 visibility graph에 대해 간단히 설명드렸습니다. 이름에서 알 수 있듯이 co-visibility graph는 두 개 이상의 점에서 나오는 직선이 특정 점에 도달하게 되었을 때 visibility graph의 갯수를 나타냅니다.


 Vision 분야에서의 visibility graph를 먼저 설명드리도록 하겠습니다.



 이 그림에서 파란 삼각형은 카메라를 나타낸 것이며 초록색 도형은 카메라에 비치는 물체를 나타낸 것이며 노란 점은 카메라에서 해당 도형에 도달하는 visibility graph를 나타낸 것입니다. 실제 점은 훨신 더 촘촘하게 나타낼 수 있으나 보기 쉽게 설명드리기 위해 일부 점만을 나타낸 것입니다.


 다음 그림은 두 개의 카메라로 도형을 바라보게 된 경우입니다.



 두 대의 카메라를 사용하여 특정 물체를 바라보게 되었을 때 보시는 바와 같이 붉은 점으로 표현된 부분은 두 대의 카메라의 시야에 모두 들어오는 부분입니다. 이렇게 두 대 이상의 카메라에서 영사되어 겹치게 되는 부분의 갯수를 표현하는 것을 co-visibility graph라 합니다.

 위의 그림을 보았을 때 노란점의 경우 한 대의 카메라에서만 해당 부분이 보이며 붉은점의 경우 두 대의 카메라에서 해당 부분을 볼 수 있음을 알 수 있습니다.


 이러한 co-visibility graph의 특성은 Visual-SLAM에서 시각정보로 지도를 그리게 되었을 때 주로 사용됩니다. 각 카메라의 영사 정보를 사용하여 상관관계를 판단하여 실제와 최대한 비슷한 지도를 만들 수 있는 것이지요.

Pixel Intensity(화소 강도)

공대생의 팁 2019.01.13 01:57


 이미지 처리에 있어 해당 이미지의 기초 단위인 화소는 매우 중요한 요소라 할 수 있습니다. Pixel intensity란 특정 화소의 밝은 정도를 나타낸다고 할 수 있겠습니다. 직관적인 예제를 보도록 합시다.



 위 그림은 Grayscale 관점에서 Pixel intensity를 나타낸 것입니다. 검은색의 경우 low값을 나타내고 흰색의 경우 high값을 나타내고 있으며 그 중간인 회색의 경우 middle값을 가지고 있음을 볼 수 있습니다.

 만약 각 픽셀이 0에서 255 사이의 값을 가진다 하였을 때 검은색은 0을, 흰색은 255, 회색은 0~255 사이의 값을 가질 것으로 예상할 수 있습니다.


 아래의 그림은 15×15 크기의 이미지입니다.



 각 픽셀의 intensity는 아래와 같은 숫자로 나타내게 됩니다. 위에서 보았듯이 검은색에 가까울수록 값은 0에 가깝고 흰색에 가까울수록 255에 가까운 값이 나타남을 알 수 있습니다. 



 여기까지 설명을 들으셨다면 pixel intensity의 개념에 대해 어느 정도 감이 잡혔으리라 생각합니다. 이번에는 grayscale과 같은 단색이 아닌 흔히 쓰이는 RGB 컬러 사진을 보도록 하겠습니다.



 우리들이 흔히 사용하는 이미지는 빨강,초록,파랑의 3개의 색을 조합하여 색을 만듭니다. 각각의 색상 또한 grayscale처럼 색깔의 강도를 조절함으로서 다양한 색을 나타낼 수 있게 되는 것이지요.

 RGB 이미지는 마치 3개의 grayscale로 이루어져 있다고 생각할 수 있습니다. 즉 픽셀 1개당 3개의 값을 가진 벡터 (r, g, b)로 표현할 수 있으며 각 값은 0에서 255 사이의 값을 갖고 있는 것입니다.


 그렇다면 위 이미지의 pixel intensity를 histogram을 통해 확인해보도록 하겠습니다. 이를 위해 Matlab을 사용하여 histogram을 그려보았습니다.


1
2
3
4
5
6
7
8
9
10
11
img = imread('sample.png')
 
Red = imag(:,:,1);
Green = img(:,:,2);
Blue = img(:,:,3);
 
[yRed, x] = imhist(Red);
[yGreen, x] = imhist(Green);
[yBlue, x] = imhist(Blue);
 
plot(x, yRed, 'Red', x, yGreen, 'Green', x, yBlue, 'Blue');
cs


 위 코드를 Matlab에서 실행하면 다음과 같은 그래프를 얻을 수 있습니다.


 위 이미지와 만들어진 histogram을 비교해본다면 각 column에서 가장 많이 차지하는 색상을 어느정도 비슷하게 나타내고 있음을 확인할 수 있습니다.


 특정 이미지에서의 pixel intensity는 의학 분야에서 상당히 중요하게 사용되고 있습니다.



 신체검사 등을 할 때 컴퓨터단층촬영을 한 모습입니다. 각 단면의 pixel intensity의 차이값으로 환자의 몸에 어느 부분에서 문제가 발생하였는지 쉽게 확인할 수 있습니다.

 또한 최근에는 Vision 분야가 발전함으로서 카메라에 들어오는 image를 처리하여 정보를 얻는 등의 방법으로 유용하게 사용되고 있습니다.


Nonparametric methods(비모수적 접근법)

공대생의 팁 2018.12.31 15:17


 우리가 통계 자료를 사용함에 있어서 평균 μ과 표준편차 σ를 사용합니다. 여기서 μ와 σ라는 두 개의 parameter(모수, 매개변수) 를 사용하여 특정 분포에서 원하는 결과를 추론하는 과정을 Parametric method(모수적 접근법)이라 할 수 있습니다. 즉 μ와 σ는 우리들이 원하는 결과값을 얻음에 있어 사용되는 도구라 할 수 있겠습니다.


 반면 Nonparameteric method(비모수적 접근법)은 어떠한 parameter를 사용하지 않거나 매우 제한된 조건을 사용하여 원하는 결과를 얻는 과정이라 할 수 있습니다. 만약 주어진 데이터가 정규분포와 같은 모양을 하고 있지 않아 parametric method를 사용함에 적절하지 않을 경우 Nonparametric method는 이를 대체할 수 있는 좋은 방법이라고 할 수 있겠습니다.


 Nonparametric method를 사용함에 있어 다음과 같은 장점들이 있습니다.


1. 엄격한 모수적 추론을 요구하지 않는다.

2. 모수적 추론을 거의 사용하지 않아 분포를 추론함에 있어 더 많은 수단을 사용할 수 있다.

3. 평균과 표준편차와 같은 파라미터를 사용하지 않는다.

4. 최소한의 추론만 사용하므로 부적절하게 사용될 경우가 적다.

5. 데이터가 약한 측정척도로 측정되더라도 적용이 가능하다.

6. 이해하기 쉽다.

7. 계산이 빠르고 쉽게 수행된다.

 

반면, 다음과 같은 단점을 가지고 있습니다.


1. Parametric method를 사용하는 것이 더 효율적인 데이터의 경우 Nonparametric method가 더 비효율적일 수 있다.

2. 샘플이 커질 경우 직접 계산하는 것이 어려워진다.

3. 상당히 중요한 값이 항상 계산되지 못한다.


 최근 AI의 요소 중 하나인 Neural Network의 경우 Parametric method와 Nonparametric method가 모두 사용되는 경우라 할 수 있겠습니다. 따라서 AI를 연구함에 있어 두 요소를 모두 고려해야 하는 것이 상당히 중요하며 이를 적절히 해결할 수 있다면 좋은 결과를 만들어낼 수 있을 것으로 기대할 수 있겠습니다.



출저 : https://www.researchgate.net/publication/322677728_INTRODUCTION_TO_NONPARAMETRIC_STATISTICAL_METHODS