feat(autoScale): detectClothBounds 폴백 + usePinchScale hook (v0-plan Task 8 마무리)
src/features/autoScale/detectClothBounds.ts: - v0 폴백: detectClothWidthPx → 항상 0 반환 → calculateScale가 confidence=0으로 fallback, 사용자가 핀치로 직접 보정 - 정식 구현은 Task 12: iOS Vision Saliency (VNGenerateAttentionBasedSaliencyImageRequest) src/features/autoScale/__tests__/detectClothBounds.test.ts: - 회귀 테스트 2 케이스: 정상 입력 / 빈 문자열 → 둘 다 0 (Task 12 정식 구현 시 spec 변경 명시점) src/features/autoScale/usePinchScale.ts: - react-native-gesture-handler v2 Pinch + Pan Simultaneous - .runOnJS(true) 명시 → worklet→JS thread 트램폴린 없이 setState 직접 (reanimated 의존 회피) - [MIN_SCALE, MAX_SCALE] 재사용 (calculateScale 모듈에서 import) - reset(): initialScale로 scale 복원 + tx/ty 0 - 검증은 Mac 실기기 manual test (Windows에서 hook 동작 검증 불가) 검증: - npx tsc --noEmit: 무에러 - 전체 npm test: 6 suites / 17 tests passed (sanity 1 + pose 1 + photoValidation 3 + maskSplit 4 + calculateScale 6 + detectClothBounds 2) 남은 Task 8 부분: 없음 (Step 4-6 완료, Step 7 Mac 검증) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
13
src/features/autoScale/__tests__/detectClothBounds.test.ts
Normal file
13
src/features/autoScale/__tests__/detectClothBounds.test.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { detectClothWidthPx } from '../detectClothBounds';
|
||||||
|
|
||||||
|
describe('detectClothWidthPx', () => {
|
||||||
|
it('v0 폴백: 자동 검출 미지원이므로 항상 0을 반환한다 (정식 구현은 Task 12)', async () => {
|
||||||
|
const result = await detectClothWidthPx('file://anyframe.jpg');
|
||||||
|
expect(result).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('빈 문자열 입력도 동일하게 0 폴백', async () => {
|
||||||
|
const result = await detectClothWidthPx('');
|
||||||
|
expect(result).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
12
src/features/autoScale/detectClothBounds.ts
Normal file
12
src/features/autoScale/detectClothBounds.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* v0 폴백: 카메라 프레임에서 사용자가 든 옷의 가로 픽셀 검출.
|
||||||
|
*
|
||||||
|
* v0에서는 항상 0을 반환 → calculateScale가 confidence=0으로 fallback,
|
||||||
|
* 사용자는 핀치 줌(usePinchScale)으로 직접 보정.
|
||||||
|
*
|
||||||
|
* 정식 구현은 Task 12: iOS Vision Saliency(VNGenerateAttentionBasedSaliencyImageRequest
|
||||||
|
* 또는 VNGenerateForegroundInstanceMaskRequest)로 손에 든 옷 mask → bbox 가로 너비.
|
||||||
|
*/
|
||||||
|
export async function detectClothWidthPx(_cameraFrameUri: string): Promise<number> {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
40
src/features/autoScale/usePinchScale.ts
Normal file
40
src/features/autoScale/usePinchScale.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { Gesture } from 'react-native-gesture-handler';
|
||||||
|
import { MIN_SCALE, MAX_SCALE } from './calculateScale';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 핀치 줌 + 팬 hook. 자동 스케일 추정값을 초기값으로 받고 사용자가 직접 보정.
|
||||||
|
*
|
||||||
|
* Mac 실기기 검증 항목:
|
||||||
|
* - .runOnJS(true)로 worklet→JS thread 트램폴린 없이 setState 직접 호출 (reanimated 의존 회피)
|
||||||
|
* - 핀치 줌 [MIN_SCALE, MAX_SCALE] 클램핑이 calculateScale과 동일 범위인지
|
||||||
|
* - 팬은 누적 translation, reset은 initialScale로 복원
|
||||||
|
*/
|
||||||
|
export function usePinchScale(initialScale: number = 1) {
|
||||||
|
const [scale, setScale] = useState(initialScale);
|
||||||
|
const [tx, setTx] = useState(0);
|
||||||
|
const [ty, setTy] = useState(0);
|
||||||
|
|
||||||
|
const pinch = Gesture.Pinch()
|
||||||
|
.runOnJS(true)
|
||||||
|
.onUpdate((e) => {
|
||||||
|
setScale((s) => Math.max(MIN_SCALE, Math.min(MAX_SCALE, s * e.scale)));
|
||||||
|
});
|
||||||
|
|
||||||
|
const pan = Gesture.Pan()
|
||||||
|
.runOnJS(true)
|
||||||
|
.onUpdate((e) => {
|
||||||
|
setTx((x) => x + e.translationX);
|
||||||
|
setTy((y) => y + e.translationY);
|
||||||
|
});
|
||||||
|
|
||||||
|
const gesture = Gesture.Simultaneous(pinch, pan);
|
||||||
|
|
||||||
|
const reset = useCallback(() => {
|
||||||
|
setScale(initialScale);
|
||||||
|
setTx(0);
|
||||||
|
setTy(0);
|
||||||
|
}, [initialScale]);
|
||||||
|
|
||||||
|
return { scale, tx, ty, gesture, reset };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user