[React] 웹캠 화면과 캡쳐 이미지의 비율을 맞추자

김혜림·2023년 12월 16일
0

react

목록 보기
4/12

키오스크에 안면인식 기능을 추가해야 해서 기기의 웹캠을 이용해서 File 객체를 얻는 연습을 하고 있다.

그런데 캡쳐 후 이미지랑 웹캠 비디오 출력 화면의 비율이 안맞는 문제가 있다!

문제 해결 전 캡쳐화면

내 코드는 아래와 같았다.

function WebcamCapture() {
	const [isCaptured, setIsCaptured] = useState(false);

  const videoRef = useRef(null);
  const canvasRef = useRef(null);
	
	useEffect(() => {
    navigator.mediaDevices
      .getUserMedia({ video: true })
      .then((stream) => {
        if (videoRef.current) {
          videoRef.current.srcObject = stream;
        }
      })
      .catch((error) => {
        console.error("Error accessing webcam:", error);
      });
  }, []);
	
	const captureImage = () => {
    setIsCaptured(true);
		
		const videoElement = videoRef.current;
    const canvasElement = canvasRef.current;
		
		if (videoElement && canvasElement) {
			const context = canvasElement.getContext("2d");
			context.drawImage(
        videoElement,
        0, //이미지를 그릴 캔버스의 x 좌표 
        0, //이미지를 그릴 캔버스의 y 좌표
        canvasElement.width, //그릴 이미지의 너비 지정
        canvasElement.height, //그릴 이미지의 높이 지정
      );
		}
	}
	
	return (
		<WebCapCaptureWrap>
			<WebCameVideo
				ref={videoRef}
        isCaptured={isCaptured}
        autoPlay />
			<WebCamCanvas 
				ref={canvasRef} 
				isCaptured={isCaptured} />
			{!isCaptured ? (
        <RegularButton onClick={captureImage}>촬영</RegularButton>
      ) : (
        <RegularButton
          onClick={() => {
            setIsCaptured(false);
          }}
        >
          취소
        </RegularButton>
      )}
		</WebCapCaptureWrap>
	);
}

위의 코드에서

if (videoElement && canvasElement) {
	const context = canvasElement.getContext("2d");
	context.drawImage(
        videoElement,
        0, //이미지를 그릴 캔버스의 x 좌표 
        0, //이미지를 그릴 캔버스의 y 좌표
        canvasElement.width, //그릴 이미지의 너비 지정
        canvasElement.height, //그릴 이미지의 높이 지정
	);
}

이 부분 코드를 보면
그릴 이미지의 너비를 canvasElement.width, canvasElement.height로 지정하고 있는데,
얘네는 style.width, style.height랑은 다른 값으로, 캔버스에 실제 그리기 영역의 너비를 설정하여 캔버스에 그려지는 내용의 해상도에 영향을 미치는 속성이다.

canvasRef.current.width, canvasRef.current.height를 따로 설정해 주지 않으면
값은 각각 300, 150으로 고정이 된다.

이렇게 캔버스에 그린 실제 이미지는 가로 300 * 세로 150인 이미지가 되었기 때문에 캡쳐 후 이미지와 비디오의 이미지가 달라 보였던 것이다.

그럼 video 이미지와 canvas이미지의 크기를 맞추려면 어떻게 해야할까?

<video/> 요소에는 videoWidth, videoHeight 라는 놈들이 있는데
이 값은 웹캠을 찍을 때 원본 video stream의 가로, 세로 해상도이다.

videoWidth, videoHeight 속성을 콘솔에 찍은 예시 코드

콘솔에 위와같이 videoRef.current.videoWidth , videoRef.current.videoHeight 를 찍어보면

내 컴퓨터에서는 가로640, 세로 480 비율로 나타난다.

따라서 canvasRef.current.width = 640, canvasRef.current.height = 480 으로 맞춰주면 된다.

문제 해결 후 캡쳐화면
짜잔! 문제가 잘 해결되었다 🫠
profile
개발 일기입니다. :-)

0개의 댓글