Canva Ship Shape: 손그림 도형을 벡터로 바꾸는 Shape Assist
(canva.dev)- Canva의 Shape Assist는 Draw tool에서 흔들리게 그린 단일 스트로크 도형을 브라우저 안에서 인식해 깔끔한 벡터 그래픽으로 바꾸는 기능임
- 규칙과 임계값에 의존한 컴퓨터 비전 휴리스틱은 사각형·원·삼각형에는 쓸 수 있었지만, 구름·별·하트 같은 복잡한 도형과 새 도형 추가에는 한계가 있었음
- 모델은 스트로크를 이미지가 아니라 x·y 좌표 시퀀스로 다루며, 클라이언트 실행을 위해 CNN 대신 RNN/LSTM 기반 구조와 커스텀 추론 코드를 선택함
- 최종 모델은
P = 25,H = 100,N = 9설정의 단일 LSTM 레이어와 Gemm 레이어로 구성되며,64,109개 파라미터와 약 250KB 크기로 최신 노트북에서 10ms 미만에 실행됨 - 서버 왕복 없이 동작하되, 사용자가 도형을 그린 뒤 커서를 1초 이상 유지하고 사전 정의 도형과 충분히 일치할 때만 자동 교체되도록 설계됨
Draw tool과 Shape Assist의 역할
- Canva의 Draw tool은 사용자가 디자인에 직접 그린 그림을 추가할 수 있게 함
- Shape Assist는 손떨림이 있는 낙서를 더 매끄러운 벡터 그래픽으로 바꾸기 위해 만들어짐
- 분류 지연시간이 중요한 조건이라 서버 처리 대신 브라우저 내 실행을 선택함
- 사용자는 도형을 그리는 즉시 피드백을 받을 수 있음
- 서버 기반 처리에서 생기는 지연을 피할 수 있음
- 지속적인 인터넷 연결 없이도 오프라인에서 사용할 수 있음
휴리스틱에서 ML 모델로 전환한 이유
- 초기 Shape Assist는 사용자가 그린 좌표의 기하 속성을 분석하는 컴퓨터 비전 휴리스틱을 사용함
- 사각형, 원, 삼각형 같은 특정 도형을 규칙과 임계값으로 감지함
- 좌표는 카테시안 좌표계의 점들로 분석됨
- 기본 도형 인식에는 동작했지만, 새 도형을 추가하거나 더 복잡한 도형을 처리하기 어려웠음
- 초기 구현은 단일 스트로크로 그릴 수 있는 도형으로 제한됨
- 제안된 도형 목록에는 구름, 별, 하트처럼 휴리스틱 방식으로 처리하기 어려운 도형이 포함됨
- ML 모델은 사용자 손그림 데이터셋에서 다양한 스타일과 변형을 학습할 수 있어, 단순 기하 도형을 넘어 더 복잡한 도형으로 Shape Assist를 확장할 수 있었음
손그림 데이터와 좌표 기반 표현
- Canva는 단일 스트로크 도형을 그리는 간단한 UI로 사용자 손그림 데이터를 수집함
- 각 스트로크는 x·y 좌표 시퀀스로 기록됨
- 이 방식은 도형을 이진 이미지로 저장하는 것보다 전처리와 데이터 증강에 더 유연함
- 이미지 기반이면 뒤집기, 회전, 전단 같은 공간 증강을 적용할 수 있음
- 좌표 기반이면 좌표의 무작위 삭제, 점 위치의 무작위 흔들림, 점 순서 반전 같은 증강도 가능함
- 자원자 데이터만으로도 상당한 데이터셋을 모았지만, 엔지니어와 디자이너의 그림은 평균 Canva 사용자를 잘 대표하지 않았음
- ML 엔지니어는 적대적인 데이터를 제공하는 경향이 있었음
- 디자이너의 그림은 너무 잘 그려져 일부는 주로 쓰지 않는 손으로 그리도록 지시함
- 더 엄격한 가이드라인과 기대치를 제공한 뒤 상당한 데이터셋을 확보함
모델 설계와 학습 방식
- 모델은 클라이언트에서 실행되어야 했고 페이지 로드 시간에 나쁜 영향을 주면 안 됐기 때문에, 크기를 최소화해야 했음
- Canva는 점을 픽셀로 변환해야 하는 CNN 대신, 스트로크의 x·y 좌표를 직접 사용하는 RNN을 실험함
- 최적의 모델 속성을 찾기 위해 하이퍼파라미터 탐색을 수행함
- 입력 크기, 레이어 수, hidden state의 특성 수 같은 파라미터를 조정함
- 사용자마다 그리는 속도가 달라 같은 도형도 점 목록 길이가 달라짐
- 느리게 그리는 사용자는 더 많은 점을 남김
- 빠르게 그리는 사용자는 더 적은 점을 남김
- 점 개수를 고정하기 위해 균등 분포의 구간별 선형 보간을 사용할 수도 있었지만, 중요한 점이 제거되어 세부 정보 손실이 생겼음
- 대신 Canva는 Ramer-Douglas-Peucker 알고리듬의 변형을 개발함
- RDP는 곡선의 중요한 세부를 보존하면서 점 수를 줄이는 곡선 단순화 알고리듬임
- 단순화된 곡선에서 의미 있게 벗어나지 않는 점을 재귀적으로 제거함
잘못된 자동 교체를 줄이는 분류 방식
- Shape Assist는 손그림이 사전 정의 클래스 중 하나와 충분히 비슷하지 않으면 자동 교체하지 않아야 함
- 하나의 도형만 정답이 될 수 있으므로 softmax 활성화와 cross-entropy 손실이 자연스러운 선택이었음
- 최고 확률 클래스의 신뢰도가 임계값보다 낮으면 예측을 거부하는 방식임
- 하지만 이 접근에서는 모델이 틀렸을 때도 높은 신뢰도를 보이는 문제가 있었음
- 최종적으로는 각 출력 클래스에 sigmoid 활성화를 쓰는 다중 클래스·다중 레이블 분류기로 학습함
- 어떤 클래스도 임계값을 넘지 않으면 예측을 거부함
클라이언트 추론 구조
- ML 모델은 보통 크고 계산량이 많아 클라우드의 강력한 컴퓨터에서 실행되는 경우가 많음
- Shape Assist 모델은 작고 수학 연산도 적어, 모든 처리를 클라이언트 애플리케이션 안에서 실행할 수 있었음
- 이 방식은 서버 연결 필요성을 없애고, 서버 왕복 시간을 제거해 거의 즉시 도형을 인식하게 함
모델 아키텍처와 크기
- 최종 모델은 단일 LSTM 레이어 뒤에 Gemm 레이어를 붙인 구조임
- Gemm은 Dense 또는 Fully Connected 레이어로도 불림
- 주요 설정값은 다음과 같음
- 보간된 점 수:
P = 25 - hidden size:
H = 100 - 사전 정의 도형 수:
N = 9
- 보간된 점 수:
- 파라미터 수는 다음과 같이 계산됨
- LSTM:
4H * 2 + 4H * H + 8H = 41,600 - Gemm:
P * H * N + N = 22,509 - 총합:
64,109
- LSTM:
- IEEE754 32비트 부동소수점 기준 파라미터당 4바이트를 사용하면 모델 크기는 약 250KB임
- 압축하지 않은 360p 16:9 이미지 1장과 비슷한 크기임
- 더 낮은 정밀도로 파라미터를 저장하면 더 줄일 가능성이 있음
- Canva는 범용 ML 엔진 대신 LSTM과 Gemm 연산을 TypeScript로 직접 구현함
- 더 복잡한 모델에는 잘 일반화되지 않는 접근임
- 구현은 300줄 미만임
- 최신 노트북에서 10ms 미만에 실행됨
도형 교체와 정렬
- 모델이 손그림 도형을 판별한 뒤, Canva는 템플릿 매칭 방식으로 손그림 경로를 벡터 그래픽 표현에 맞춤
- 정렬 과정은 입력 도형과 템플릿 도형을 정규화한 뒤 진행됨
- 템플릿 도형을 15° 단위로 회전해 시도함
- 회전된 좌표 공간에서 입력 점들의 1차·2차 모멘트를 계산함
- 입력 점과 템플릿 도형 사이의 비유사도를 계산함
- 비유사도가 가장 작은 회전을 최적 각도로 선택함
- 사용자가 도형을 그린 뒤 커서를 제자리에 최소 1초 동안 유지하면, 사전 정의 도형과 충분히 일치하는 경우 Shape Assist가 도형을 교체함
댓글과 토론
Hacker News 의견들
-
이 문제에는 순환 신경망(RNN)이 과한 것 같고, 단순하고 우아한 $1 unistroke recognizer가 더 적절해 보임
제스처마다 샘플 하나만 학습해도 꽤 잘 동작하고, 어떤 프로젝트든 오후 한나절이면 붙여서 제스처 인식으로 UI를 더 친숙하게 만들 수 있음
각 글자가 한 획이면 Palm식 Graffiti 텍스트 입력에도 상당히 안정적으로 동작하며, 원 논문도 읽기 쉽고 이해하기 좋게 쓰여 있음
https://depts.washington.edu/acelab/proj/dollar/index.html- $1 recognizer의 큰 문제는 획을 특정 방식으로 그려야 한다는 점임
예를 들어 원을 그릴 때 반시계방향으로 그려야 하고, 더 자연스럽게 느껴지는 시계방향으로 그리면 캐럿으로 인식됨
사용자가 구현 세부사항을 모르는 자유 드로잉 맥락에서는 실제로 쓰기 어렵다 - 이 페이지의 예제를 테스트하고 오류를 보고하는 사람들이 놓치는 점은, 이 데모가 예제 하나로만 “학습”됐다는 사실임
링크한 논문[0]은 오류율을 다루고, 예제를 몇 개만 더 넣어도 꽤 빠르게 좋아짐
[0]https://faculty.washington.edu/wobbrock/pubs/uist-07.01.pdf , 8쪽 - 직접 해보니, 적어도 학습 없이 쓰기에는 꽤 별로였음
내가 그린 사각형은 캐럿으로, 지그재그는 중괄호로 인식됨
화살표처럼 두 획으로 그리는 도형도 지원하지 않음 - 잠깐 써보니 너무 단순했음. 예시 도형을 정확히 따라 그리지 않으면 서로 헷갈림
예시 도형의 “delete”와 “x”를 비교해 보면 성능이 얼마나 나쁜지 확인하기 좋음
매번 같은 방식으로 도형을 그린다고 기대하는 제스처 인터페이스의 출발점으로는 괜찮겠지만, 여기서 다루는 다이어그램 작성 용도에는 잘 맞지 않음 - 정말 단순한 것에 비해 너무 잘 동작한다는 데 동의함
대학 프로젝트로 ES6 구현체를 만들었는데 관심 있으면 여기 있음: https://github.com/gurgunday/onedollar-unistroke-es6
- $1 recognizer의 큰 문제는 획을 특정 방식으로 그려야 한다는 점임
-
“마우스나 트랙패드로 그은 단순한 직선도 취한 다람쥐가 지나간 길처럼 보일 수 있다”는 설명은 알겠지만, Canva에서 누가 마우스로 도형을 직접 그려야 하는지 모르겠음
예전에 Miro에는 마우스로 별을 대충 그리면 기하학적으로 정확한 별, 원, 삼각형 등으로 바꿔주는 기능이 있었고 멋지다고 생각했지만 실제로는 한 번도 필요하지 않았음
다이어그램을 만들 때는 미리 준비된 도형을 쓰는 편이 더 빠르고, 아이콘을 만들 때는 불리언 연산, 점 이동, Pen 도구 중심의 별도 작업 흐름을 쓰며 보통 Illustrator 같은 전용 프로그램을 사용함
실제 일러스트를 그릴 때는 태블릿을 꺼내 쓰기 때문에, 기술 자체는 멋져도 사용 사례가 무엇인지 궁금함- Canva는 다이어그램 도구가 아니라, 사용자층이 꽤 다른 시각 디자인 도구임
에셋 라이브러리가 엄청나게 크고 사진과 벡터 그래픽을 포함해 수백만, 어쩌면 수천만 개의 이미지가 있음
제한적으로 써본 경험상 이미 원하는 단순한 도형을 정확히 알고 있는데도 끝없는 라이브러리를 검색해야 하는 점이 특히 귀찮았고, 이 도구는 아마 그 고통을 줄이려는 것으로 보임
몇 년 전 Canva에서 일한 적 있음
내부 정보는 전혀 없지만, Canva가 경쟁력 있는 다이어그램 도구도 되고 싶어 하기 때문에 이 사용 사례가 중요할 수 있음. 다만 현재 사용자 99%의 디자인 경험을 근본적으로 바꿀 수 없다는 제약이 있을 것 같음 - 디자이너나 마케터 중 키보드 단축키를 익히지 않는 사람에게는 “마우스로 도형을 그리기”가 빠르고, “반쯤 되는 메뉴를 거쳐 적절한 도형을 고르고 배치한 뒤 크기를 조절하기”가 더 느림
도형이 메뉴 없이 바로 있더라도, 커서 하나로 전체를 그리는 편이 여러 아이콘을 배치·리사이즈하고 화살표 기능으로 전환해 화살표를 추가하는 것보다 빠를 수 있음
- Canva는 다이어그램 도구가 아니라, 사용자층이 꽤 다른 시각 디자인 도구임
-
Canva가 선 그리기에 쓰는 라이브러리도 흥미로울 수 있음: https://github.com/steveruizok/perfect-freehand
- Canva가 후원사는 아닌 것처럼 보임
-
“Ramer-Douglas-Peucker(RDP) 알고리즘의 변형을 개발했다”는 부분을 보니 예전 사이드 프로젝트가 떠오름
2018년 Strange Loop 발표에서 Douglas-Peucker를 Picasso에 적용했음
Picasso's Bulls: Deconstructing his design process with Python
https://rrherr.github.io/picasso/ -
20년도 훨씬 전 Macromedia Flash에서 비슷한 걸 어떻게 해냈는지 궁금해짐
당시 CPU 성능은 지금보다 훨씬 제한적이었는데, 자유곡선을 그릴 때 곡선을 매끄럽게 다듬는 걸 보고 생생하게 놀랐던 기억이 있음- LeCun 일행은 1995년에 손글씨 숫자 인식에서 99% 이상의 정확도를 얻었고, 이는 도형 식별과 꽤 비슷함
그래도 브라우저에서 가볍고 빠르게 돌아가게 만드는 건 여전히 성취임. 결국 중요한 것은 늘 사용자 경험임 - 1993년 Apple Newton은 20MHz ARM 프로세서로도 이 기능이 핵심 기능이었음
https://en.wikipedia.org/wiki/MessagePad#User_interface - 스무딩은 베지어 곡선에서 중복에 가까운 점을 제거해 단순화하는 별개의 작업임
거의 직선을 그렸을 때 제어점이 100개 생겼다면, 소프트웨어가 이를 4개 정도의 점으로 줄이는 식임 - 아마 마우스 이벤트를 받아 처음에는 이벤트 사이를 직선으로 이어 그렸을 것 같음. 1990년대 하드웨어에서는 직선 그리기가 빠르고, 빠르게 그려야 하니 필요했을 것임
그리기가 끝나면 같은 점들을 입력으로 삼아 스플라인 곡선 알고리즘으로 선을 다시 그렸을 듯함
스플라인을 그리는 계산 자체가 훨씬 어려운 것은 아니지만, 끝에 점 하나를 추가하면 이미 그린 선의 일부가 바뀐다는 점이 중요함
그러면 그 선 뒤에 있는 모든 것을 다시 그려야 하므로 계산 비용이 크고, 60fps로 확실히 처리할 수 있다고 보장하기 어렵다
- LeCun 일행은 1995년에 손글씨 숫자 인식에서 99% 이상의 정확도를 얻었고, 이는 도형 식별과 꽤 비슷함
-
좋은 글이고 작업도 아주 흥미로움
소수 취향이겠지만, 이상하게도 매끈한 벡터 그래픽보다 손으로 그린 흔들리는 낙서 느낌이 더 좋게 느껴짐
물론 맥락에 따라 선호가 달라질 수 있으니 기능 자체는 멋짐. 인공적인 완벽함이 넘치는 세상에서는 진짜 손그림 결과물에 본질적으로 끌리는 면이 있음 -
이런 기능을 구현한다면 꼭 선택 가능하게 만들고, 켜져 있을 때 명확히 보이게 해줬으면 함
도구가 너무 똑똑한 척하다가 완벽하게 맞히지 못하면 정말 화가 남. 나도 그런 실수를 해본 적 있음 -
최근의 기계학습/AI 유행보다 몇 년 앞서 아이들이 좋아하던 Scribblenauts라는 게임이 있었는데, 아주 거친 낙서를 놀랄 만큼 다양한 물체로 바꿔줬음
어떻게 했는지는 모르지만 나도 감탄했고, 아이들은 마법처럼 여겼음
https://store.steampowered.com/app/218680/Scribblenauts_Unli...- 해봤는데 정말 놀라웠음. 기억이 맞다면 iOS로도 나왔던 것 같음
-
이게 오픈소스였으면 좋겠음
최근에는 크기가 작은 모델들이 여럿 나오고 있음. 이 모델은 250KB이고, 큰 모델을 미세조정하는 단순 작업에서는 50KB 정도 모델도 있었음
유용한 애플리케이션에 다시 작은 모델을 실제로 쓸 수 있게 되는 시점이 기대됨 -
오각성과 반짝이는 별은 같은 것이 아님. 이게 과소적합의 예인가?