엔지니어링 · 2024

시술 전후 사진 비교·계측 뷰어

전후 사진을 같은 배율과 위치로 나란히 놓고 길이와 각도를 재는 데스크톱 프로그램

시술 전후 사진을 눈대중으로 비교하던 상담 과정을, 사진을 분할 화면에 나란히 띄우고 cm 단위 길이와 각도를 직접 재서 주석이 들어간 이미지로 남기는 작업으로 바꿨습니다.

고객
비공개 고객
분야
엔지니어링
두 장의 사진을 좌우로 놓고 길이와 각도를 측정한 화면

개요

미용·성형 분야에서 시술 전후 사진을 비교하고 상담에 쓰기 위해 만든 Windows 데스크톱 프로그램입니다. 전용 촬영 장비로 찍은 사진을 불러와 2분할 또는 6분할 화면에 배치하고, 화면 위에서 바로 길이와 각도를 재고 주석을 답니다.

일반 이미지 뷰어와 다른 점은 두 가지입니다. 하나는 여러 사진의 확대 배율과 위치가 항상 함께 움직인다는 것이고, 다른 하나는 화면에서 잰 거리가 픽셀이 아니라 cm로 표시된다는 것입니다. 촬영 장비의 배율이 고정되어 있어 픽셀당 실제 길이를 환산할 수 있습니다.

두 장의 사진을 좌우로 놓고 길이와 각도를 측정한 화면
2분할 비교 화면

과제

전후 사진 비교는 일반 이미지 뷰어로도 할 수 있지만, 상담에 쓰기에는 걸리는 점이 있었습니다.

  • 사진을 각각 열면 확대 배율과 위치가 제각각이라 같은 조건에서 보기 어렵다
  • 변화의 크기를 말로만 설명하게 되고, 수치로 짚어 줄 방법이 없다
  • 비교한 결과를 기록으로 남기려면 캡처한 뒤 별도 편집 도구에서 선과 설명을 다시 그려야 한다
  • 촬영 조건에 따라 밝기나 색감이 달라도 보정할 수단이 없다

해결 방법

하나의 창 안에서 비교, 계측, 보정, 내보내기를 끝내도록 구성했습니다.

비교

2분할과 6분할 레이아웃을 버튼으로 전환합니다. 모든 뷰의 카메라가 서로 연결되어 있어 한 곳을 확대하거나 끌면 나머지도 같은 배율과 위치로 따라갑니다. 뷰 위에 십자 가이드라인을 띄워 사진 간 기준선을 맞출 수 있고, 가이드라인의 교차점은 끌어서 옮깁니다.

사진 여섯 장을 2행 3열로 배치해 비교하는 화면
6분할 비교 화면

계측과 주석

두 점을 찍으면 그 사이 거리가 cm로, 세 점을 찍으면 끼인각이 도 단위로 표시됩니다. 찍은 점은 나중에 끌어서 옮길 수 있고 값은 따라 갱신됩니다. 임의 위치에 텍스트도 넣습니다. 모든 편집은 되돌리기와 다시 실행이 됩니다.

보정

밝기, 대비, 채도, 컬러 밸런스, 선명도를 슬라이더로 조절해 저장해 두면, 버튼 하나로 원본과 보정본을 오갑니다. 설정 창은 비밀번호로 열리게 해 현장에서 실수로 값이 바뀌지 않도록 했습니다.

밝기, 대비, 채도, 컬러 밸런스, 선명도를 슬라이더로 조절하는 설정 창
이미지 필터 설정 창

내보내기

뷰별로 저장 버튼을 누르면 측정선, 수치, 텍스트가 합성된 이미지가 파일로 떨어집니다.

시스템 구조

구성

  • m_main: 메인 창과 아이콘 툴바. 버튼 상태와 캔버스 모드를 연결한다
  • m_canvas: VisPy 씬 그래프 기반 캔버스. 분할 레이아웃, 카메라, 마우스 이벤트를 담당한다
  • p_utils: 측정과 주석을 다루는 매니저 계층. 공통 추상 클래스 아래에 길이, 각도, 텍스트, 이미지 매니저를 둔다
  • p_vars: 아이콘 로딩과 보정 파라미터 저장
  • m_button: 눌림과 토글 상태를 가진 비트맵 버튼

데이터 흐름

  • 사진을 열면 이미지 매니저가 원본 배열과 보정본 배열을 함께 들고 있다가, 토글 상태에 따라 한쪽을 뷰에 올린다
  • 마우스 좌표는 화면 픽셀에서 이미지 좌표로 변환된 뒤 매니저에 전달되고, 매니저가 점 목록을 갱신해 다시 그린다
  • 모든 편집은 실행 명령과 취소 명령을 한 쌍으로 묶어 스택에 쌓인다
  • 저장은 화면을 캡처하지 않고, 원본 해상도 이미지 위에 측정 요소를 다시 그려 파일로 쓴다

구현

뷰마다 하나의 Visual

측정선이 늘어날수록 화면 요소가 늘어나면 그리기 비용이 커집니다. 뷰 하나당 선, 마커, 텍스트를 각각 한 개씩만 두고, 모든 측정 결과를 그 안의 좌표 배열로 합쳐서 그립니다. 점을 추가하거나 옮길 때는 배열을 다시 만들어 한 번에 올립니다. 각 요소에는 z축 이동을 주어 사진, 측정선, 마커, 가이드라인의 겹침 순서를 고정했습니다.

카메라 제한

기본 카메라는 사진 바깥까지 끌려 나가 빈 화면이 보일 수 있습니다. 이동과 확대를 재정의해 화면 영역이 항상 사진 안에 머물도록 가두고, 축소해서 사진이 화면보다 작아지면 가운데로 맞춥니다. 여러 뷰의 카메라를 한 카메라에 연결해 동기화합니다.

좌표 변환

측정은 이미지 좌표로 저장해 확대 배율과 무관하게 같은 지점을 가리키게 했습니다. 다만 점을 집을 수 있는 범위는 화면 픽셀 기준이어야 손에 익기 때문에, 가장 가까운 점을 찾을 때만 화면 좌표로 되돌려 거리를 계산합니다.

저장 시 재렌더링

화면 캡처로 저장하면 보이는 만큼만 남고 해상도도 떨어집니다. 저장할 때는 원본 해상도 이미지에 Pillow로 측정선과 글자를 다시 그립니다. 글자 크기는 이미지 높이의 일정 비율이 되도록 자동으로 계산하고, 선 굵기와 마커 반지름은 글자 높이에 비례시켜 사진 크기가 달라도 비슷하게 보이도록 했습니다.

대비와 선명도 보정을 적용해 질감이 또렷해진 화면
보정을 적용한 화면

결과

상담 자리에서 전후 사진을 같은 배율과 위치로 나란히 놓고, 변화를 cm와 각도로 짚어 가며 설명할 수 있게 되었습니다. 비교 결과는 측정선과 설명이 합성된 이미지 파일로 남아, 별도 편집 도구를 거치지 않고 그대로 기록에 쓰입니다.

촬영 조건에 따라 달라지는 밝기와 색감은 저장해 둔 보정값으로 맞추고, 원본과 보정본을 버튼 하나로 오가며 확인합니다.

사용 기술

  • Python
  • wxPython
  • VisPy
  • NumPy
  • Pillow
  • OpenGL

화면

진행하려는 프로젝트가 있으신가요?

해결하려는 문제와 지금 상황을 알려 주시면, 어떤 방식이 맞을지 함께 검토합니다.

프로젝트 문의하기