레슨 8 / 10·4개 토픽
객체 감지와 자연어 처리
TensorFlow.js의 사전학습 모델을 활용하면 객체 감지, 자세 추정, 텍스트 유사도 분석, 콘텐츠 검열 등 다양한 AI 기능을 브라우저에서 바로 구현할 수 있습니다. 이 레슨에서는 COCO-SSD, PoseNet/MoveNet, Universal Sentence Encoder, Toxicity 모델을 실습합니다.
COCO-SSD 실시간 객체 감지
javascript
import * as cocoSsd from '@tensorflow-models/coco-ssd';
// 모델 로드
const model = await cocoSsd.load();
// 비디오 요소에서 실시간 객체 감지
const video = document.getElementById('webcam');
const canvas = document.getElementById('overlay');
const ctx = canvas.getContext('2d');
async function detectFrame() {
const predictions = await model.detect(video);
// 캔버스 초기화
ctx.clearRect(0, 0, canvas.width, canvas.height);
predictions.forEach(pred => {
const [x, y, width, height] = pred.bbox;
// 바운딩 박스 그리기
ctx.strokeStyle = '#00ff00';
ctx.lineWidth = 2;
ctx.strokeRect(x, y, width, height);
// 라벨 표시
ctx.fillStyle = '#00ff00';
ctx.font = '14px Arial';
ctx.fillText(
pred.class + " " + (pred.score * 100).toFixed(0) + "%",
x, y > 15 ? y - 5 : y + 15
);
});
requestAnimationFrame(detectFrame);
}
// 웹캠 시작 후 감지 루프 실행
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = stream;
video.onloadeddata = () => detectFrame();PoseNet/MoveNet 자세 추정
javascript
import * as poseDetection from '@tensorflow-models/pose-detection';
// MoveNet 모델 생성 (SinglePose Lightning: 빠르고 가벼움)
const detector = await poseDetection.createDetector(
poseDetection.SupportedModels.MoveNet,
{ modelType: poseDetection.movenet.modelType.SINGLEPOSE_LIGHTNING }
);
// 자세 추정 실행
const poses = await detector.estimatePoses(video);
if (poses.length > 0) {
const keypoints = poses[0].keypoints;
keypoints.forEach(kp => {
if (kp.score > 0.3) {
// 키포인트 그리기
ctx.beginPath();
ctx.arc(kp.x, kp.y, 5, 0, 2 * Math.PI);
ctx.fillStyle = '#ff0000';
ctx.fill();
ctx.fillText(kp.name, kp.x + 8, kp.y);
}
});
// 스켈레톤 연결선 그리기
const connections = poseDetection.util.getAdjacentPairs(
poseDetection.SupportedModels.MoveNet
);
connections.forEach(([i, j]) => {
const kpA = keypoints[i];
const kpB = keypoints[j];
if (kpA.score > 0.3 && kpB.score > 0.3) {
ctx.beginPath();
ctx.moveTo(kpA.x, kpA.y);
ctx.lineTo(kpB.x, kpB.y);
ctx.strokeStyle = '#00ffff';
ctx.lineWidth = 2;
ctx.stroke();
}
});
}Universal Sentence Encoder 텍스트 유사도
javascript
import * as use from '@tensorflow-models/universal-sentence-encoder';
// 모델 로드
const model = await use.load();
// 문장 임베딩 생성
const sentences = [
'오늘 날씨가 좋습니다',
'오늘 날씨가 화창합니다',
'주식 시장이 하락했습니다',
];
const embeddings = await model.embed(sentences);
const vectors = await embeddings.array();
// 코사인 유사도 계산
function cosineSimilarity(a, b) {
let dotProduct = 0, normA = 0, normB = 0;
for (let i = 0; i < a.length; i++) {
dotProduct += a[i] * b[i];
normA += a[i] * a[i];
normB += b[i] * b[i];
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}
// 문장 간 유사도 비교
const sim01 = cosineSimilarity(vectors[0], vectors[1]);
const sim02 = cosineSimilarity(vectors[0], vectors[2]);
console.log("날씨-화창 유사도:", sim01.toFixed(4)); // 높음 (~0.85)
console.log("날씨-주식 유사도:", sim02.toFixed(4)); // 낮음 (~0.15)Toxicity 모델 콘텐츠 검열
javascript
import * as toxicity from '@tensorflow-models/toxicity';
// 독성 분류 모델 로드 (threshold: 판정 기준 확률)
const model = await toxicity.load(0.9);
const sentences = [
'You are a wonderful person!',
'I will destroy you completely!',
'Have a great day!',
];
const predictions = await model.classify(sentences);
predictions.forEach(category => {
console.log("카테고리:", category.label);
category.results.forEach((result, i) => {
const match = result.match;
const prob = result.probabilities;
console.log(
" " + sentences[i] + " -> " +
(match ? "독성" : match === false ? "안전" : "판단 불가") +
" (확률: " + (prob[1] * 100).toFixed(1) + "%)"
);
});
});
// 카테고리: identity_attack, insult, obscene,
// severe_toxicity, sexual_explicit, threat, toxicity💡
COCO-SSD는 80개 카테고리의 일상 객체를 감지할 수 있으며, MoveNet은 17개 신체 키포인트를 실시간으로 추정합니다. Universal Sentence Encoder는 512차원 벡터로 문장을 임베딩하여 의미적 유사도를 비교할 수 있습니다. 모든 모델은 최초 로드 시 네트워크 다운로드가 필요하므로 로딩 UI를 제공하세요.