내보낼 때 Face Blur Patches가 정렬된 상태를 유지하는 방법
Source: Dev.to
얼굴을 흐리게 하는 것은 정적인 데모만 고려한다면 쉽습니다.
사용자가 얼굴을 다시 감지하고, 패딩을 확대하고, 패치를 이동하고, 크기를 조정하고, 개별 얼굴을 비활성화하고, 흐림 강도를 변경한 뒤, 모든 것이 정렬이 흐트러지지 않게 최종 이미지를 내보낼 수 있을 때는 상황이 더 복잡해집니다.
우리에게 가장 잘 맞았던 아키텍처는 패치 기반이었습니다.
전체 보조 가이드는 여기에서 확인할 수 있습니다:
먼저 하나의 흐린 원본 이미지를 만들기
각 패치를 개별적으로 흐리게 하는 대신, 편집기는 먼저 전체 원본 이미지의 흐린 버전을 생성합니다:
ctx.filter = `blur(${blurStrength}px)`;
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
ctx.filter = "none";
이렇게 하면 편집기는 감지된 모든 얼굴에 대해 재사용 가능한 하나의 흐림 소스를 갖게 됩니다.
실용적인 장점
- 흐림 강도를 변경하면 단일 소스 이미지를 다시 빌드합니다.
- 기존 패치는 그들의 기하학을 유지합니다.
- 얼굴 상호작용이 빠르게 유지됩니다.
모든 얼굴은 잘라낸 이미지 패치입니다
감지된 각 얼굴은 흐린 원본 이미지에 연결되는 FabricImage 패치가 됩니다:
const patch = new FabricImage(this.blurredSourceElement!, {
left: region.left + region.width / 2,
top: region.top + region.height / 2,
width: region.width,
height: region.height,
cropX: region.left,
cropY: region.top,
});
편집기는 필요에 따라 임의의 사각형을 흐리게 하는 것이 아니라, 사전 계산된 흐린 이미지에 대한 잘라낸 창을 표시합니다.
기하학과 잘라낸 소스는 함께 움직여야 합니다
사용자가 흐림 패치를 드래그하거나 크기를 조정하면, 패치의 보이는 사각형과 흐린 원본 내부의 잘라낸 창이 정렬된 상태를 유지해야 합니다. 구현에서는 패치를 실제 기하학으로 정규화하고 위치와 크기와 함께 cropX와 cropY를 업데이트합니다:
patch.set({
left: geometry.left + geometry.width / 2,
top: geometry.top + geometry.height / 2,
width: geometry.width,
height: geometry.height,
cropX: geometry.left,
cropY: geometry.top,
scaleX: 1,
scaleY: 1,
});
이 리셋은 일시적인 드래그/스케일 변환을 안정적인 원본 이미지 좌표로 되돌립니다.
편집 시작 전 패딩이 중요합니다
얼굴 감지는 보통 너무 촉박하기 때문에, 코드는 각 감지를 패치로 변환하기 전에 설정 가능한 비율만큼 확장합니다. 이는 사용자에게 더 좋은 시작점을 제공하고 얼굴 가장자리를 제대로 덮기 위해 수동으로 크기를 조정해야 하는 패치 수를 줄여줍니다. 작은 단계이지만 흐림 도구가 훨씬 덜 깨지기 쉬운 느낌을 줍니다.
내보내기는 현재 패치 세트를 재현해야 합니다
사용자가 내보낼 때, 편집기는 원래 크기의 새로운 StaticCanvas를 만들고, 손대지 않은 기본 이미지를 추가한 뒤, 현재 기하학과 잘라낸 소스를 가진 각 보이는 흐림 패치를 다시 추가합니다. 따라서 저장된 파일은 다음을 반영합니다:
- 현재 흐림 강도
- 현재 패치 위치
- 현재 패치 크기
- 현재 활성/비활성 상태
화면 뷰포트에 의존하는 것이 없습니다.
패치 기반 흐림이 작동하는 이유
이 모델은 실제 편집 압박 하에서도 이해하기 쉽습니다:
- 하나의 흐림 소스
- 다수의 편집 가능한 잘라낸 창
- 상호작용 후 정규화된 기하학
- 원본 픽셀에서 재구성된 내보내기
이것이 여러 차례 감지, 조정 및 내보내기 후에도 흐림 영역이 정렬된 상태를 유지하게 하는 이유입니다.
추가 구현 세부 사항: