키오스크에 안면인식 기능을 추가해야 해서 기기의 웹캠을 이용해서 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의 가로, 세로 해상도이다.
콘솔에 위와같이 videoRef.current.videoWidth
, videoRef.current.videoHeight
를 찍어보면
내 컴퓨터에서는 가로640, 세로 480 비율로 나타난다.
따라서 canvasRef.current.width = 640
, canvasRef.current.height = 480
으로 맞춰주면 된다.