AI 생성 및 조작된 미디어를 식별하는 최신 기술
딥페이크는 AI 기술을 사용하여 실제처럼 보이는 가짜 비디오, 오디오, 이미지를 생성하는 기술입니다. 정치적 조작, 금융 사기, 개인 명예 훼손 등 심각한 위협이 되고 있습니다.
탐지하기 위해서는 먼저 생성 기술을 이해해야 합니다.
| 기술 | 설명 | 주요 용도 | 탐지 난이도 |
|---|---|---|---|
| GAN | 생성적 적대 신경망 | 얼굴 생성, 스타일 전이 | 중간 |
| VAE | 변분 오토인코더 | 이미지 재구성 | 낮음 |
| Diffusion | 확산 모델 | 고품질 이미지 생성 | 높음 |
| FaceSwap | 얼굴 교체 | 비디오 조작 | 중간 |
| Voice Cloning | 음성 복제 | 오디오 조작 | 높음 |
합성곱 신경망(CNN)은 이미지의 미세한 아티팩트를 감지할 수 있습니다.
// TensorFlow.js를 사용한 CNN 딥페이크 탐지
import * as tf from '@tensorflow/tfjs-node';
class CNNDeepfakeDetector {
private model: tf.LayersModel | null = null;
// 모델 구조 정의
async buildModel(): Promise {
const model = tf.sequential();
// 첫 번째 합성곱 블록
model.add(tf.layers.conv2d({
inputShape: [224, 224, 3],
filters: 32,
kernelSize: 3,
activation: 'relu',
padding: 'same'
}));
model.add(tf.layers.batchNormalization());
model.add(tf.layers.maxPooling2d({ poolSize: 2 }));
// 두 번째 합성곱 블록
model.add(tf.layers.conv2d({
filters: 64,
kernelSize: 3,
activation: 'relu',
padding: 'same'
}));
model.add(tf.layers.batchNormalization());
model.add(tf.layers.maxPooling2d({ poolSize: 2 }));
// 세 번째 합성곱 블록
model.add(tf.layers.conv2d({
filters: 128,
kernelSize: 3,
activation: 'relu',
padding: 'same'
}));
model.add(tf.layers.batchNormalization());
model.add(tf.layers.maxPooling2d({ poolSize: 2 }));
// 완전 연결 층
model.add(tf.layers.flatten());
model.add(tf.layers.dense({
units: 256,
activation: 'relu'
}));
model.add(tf.layers.dropout({ rate: 0.5 }));
// 출력 층 (진짜/가짜 이진 분류)
model.add(tf.layers.dense({
units: 2,
activation: 'softmax'
}));
// 모델 컴파일
model.compile({
optimizer: tf.train.adam(0.001),
loss: 'categoricalCrossentropy',
metrics: ['accuracy']
});
this.model = model;
console.log('✅ CNN 모델 구축 완료');
}
// 이미지 전처리
async preprocessImage(imagePath: string): Promise {
const sharp = await import('sharp');
// 이미지를 224x224로 리사이즈
const imageBuffer = await sharp.default(imagePath)
.resize(224, 224)
.raw()
.toBuffer();
// 텐서로 변환 및 정규화
const tensor = tf.tensor3d(
new Uint8Array(imageBuffer),
[224, 224, 3]
).toFloat().div(255);
return tensor as tf.Tensor3D;
}
// 딥페이크 탐지 수행
async detectDeepfake(imagePath: string): Promise<{
isFake: boolean;
confidence: number;
details: any;
}> {
if (!this.model) {
throw new Error('모델이 로드되지 않았습니다');
}
// 이미지 전처리
const tensor = await this.preprocessImage(imagePath);
const batchedTensor = tensor.expandDims(0);
// 예측 수행
const predictions = this.model.predict(batchedTensor) as tf.Tensor;
const probabilities = await predictions.data();
// 메모리 정리
tensor.dispose();
batchedTensor.dispose();
predictions.dispose();
const realProb = probabilities[0];
const fakeProb = probabilities[1];
return {
isFake: fakeProb > realProb,
confidence: Math.max(realProb, fakeProb),
details: {
realProbability: realProb,
fakeProbability: fakeProb
}
};
}
// 모델 훈련
async train(
trainImages: tf.Tensor4D,
trainLabels: tf.Tensor2D,
epochs: number = 10
): Promise {
if (!this.model) {
throw new Error('모델이 구축되지 않았습니다');
}
await this.model.fit(trainImages, trainLabels, {
epochs,
batchSize: 32,
validationSplit: 0.2,
callbacks: {
onEpochEnd: (epoch, logs) => {
console.log(
`에포크 ${epoch + 1}: ` +
`손실=${logs?.loss.toFixed(4)}, ` +
`정확도=${logs?.acc.toFixed(4)}`
);
}
}
});
console.log('✅ 모델 훈련 완료');
}
}
// 사용 예제
const detector = new CNNDeepfakeDetector();
await detector.buildModel();
const result = await detector.detectDeepfake('suspect_image.jpg');
console.log(`딥페이크 여부: ${result.isFake ? '가짜' : '진짜'}`);
console.log(`신뢰도: ${(result.confidence * 100).toFixed(2)}%`);
Transformer 아키텍처는 시공간적 일관성을 분석하여 딥페이크를 탐지합니다.
// Vision Transformer를 사용한 딥페이크 탐지
class ViTDeepfakeDetector {
private model: any;
async loadPretrainedModel(): Promise {
// 사전 훈련된 Vision Transformer 로드
// (실제로는 Hugging Face Transformers 사용)
console.log('✅ Vision Transformer 모델 로드 완료');
}
// 패치 분할
splitIntoPpatches(
image: tf.Tensor3D,
patchSize: number = 16
): tf.Tensor3D[] {
const [height, width] = image.shape;
const patches: tf.Tensor3D[] = [];
for (let y = 0; y < height; y += patchSize) {
for (let x = 0; x < width; x += patchSize) {
const patch = image.slice(
[y, x, 0],
[patchSize, patchSize, 3]
) as tf.Tensor3D;
patches.push(patch);
}
}
return patches;
}
// 어텐션 맵 시각화
async visualizeAttention(
imagePath: string,
outputPath: string
): Promise {
// 어텐션 가중치 추출
// 모델이 주목하는 영역을 히트맵으로 시각화
console.log('✅ 어텐션 맵 생성 완료');
}
}
오디오-비주얼 불일치를 감지하여 딥페이크를 식별합니다.
// 멀티모달 딥페이크 탐지
class MultimodalDeepfakeDetector {
// 립싱크 분석
async analyzeLipSync(
videoPath: string
): Promise<{
synchronized: boolean;
syncScore: number;
}> {
// 1. 비디오에서 오디오 추출
// 2. 얼굴 랜드마크 검출
// 3. 입술 움직임과 오디오 동기화 검사
// 간소화된 예제
const syncScore = 0.85; // 0-1 스코어
return {
synchronized: syncScore > 0.7,
syncScore
};
}
// 오디오 아티팩트 분석
async analyzeAudioArtifacts(
audioPath: string
): Promise<{
isSynthetic: boolean;
confidence: number;
}> {
// 1. 오디오를 스펙트로그램으로 변환
// 2. GAN 생성 오디오의 특징적 패턴 검출
// 3. 주파수 이상 탐지
return {
isSynthetic: false,
confidence: 0.92
};
}
// 통합 분석
async detectMultimodal(
videoPath: string
): Promise<{
isDeepfake: boolean;
confidence: number;
evidence: any;
}> {
// 비주얼 분석
const visualResult = { isFake: false, confidence: 0.95 };
// 오디오 분석
const audioResult = await this.analyzeAudioArtifacts(videoPath);
// 립싱크 분석
const lipSyncResult = await this.analyzeLipSync(videoPath);
// 앙상블 결정
const evidenceCount = [
visualResult.isFake,
audioResult.isSynthetic,
!lipSyncResult.synchronized
].filter(Boolean).length;
const avgConfidence = (
visualResult.confidence +
audioResult.confidence +
lipSyncResult.syncScore
) / 3;
return {
isDeepfake: evidenceCount >= 2,
confidence: avgConfidence,
evidence: {
visual: visualResult,
audio: audioResult,
lipSync: lipSyncResult
}
};
}
}
각 GAN 모델은 고유한 지문을 남깁니다. 이를 분석하여 생성 모델을 역추적할 수 있습니다.
// GAN 지문 분석기
class GANFingerprintAnalyzer {
// 주파수 영역 분석
async analyzeFrequencyDomain(
imagePath: string
): Promise<{
hasGANFingerprint: boolean;
likelyModel: string | null;
}> {
const sharp = await import('sharp');
// 이미지 로드
const { data, info } = await sharp.default(imagePath)
.raw()
.toBuffer({ resolveWithObject: true });
// FFT 적용하여 주파수 분석
// GAN은 특정 주파수 패턴을 남김
// 알려진 GAN 지문과 매칭
const knownFingerprints = {
'StyleGAN2': [/* 주파수 패턴 */],
'ProGAN': [/* 주파수 패턴 */],
'DCGAN': [/* 주파수 패턴 */]
};
// 매칭 수행 (간소화)
const hasGANFingerprint = true;
const likelyModel = 'StyleGAN2';
return {
hasGANFingerprint,
likelyModel
};
}
// 업샘플링 아티팩트 검출
detectUpsamplingArtifacts(
imageBuffer: Buffer
): {
hasArtifacts: boolean;
locations: Array<[number, number]>;
} {
// GAN의 업샘플링 층에서 발생하는 체커보드 패턴 검출
// 픽셀 격자 분석
return {
hasArtifacts: false,
locations: []
};
}
}
진짜 인간 비디오는 미세한 생물학적 신호를 포함합니다.
// 생물학적 신호 분석
class BiologicalSignalAnalyzer {
// 심박 신호 검출 (PPG)
async detectHeartbeat(
videoPath: string
): Promise<{
heartbeatDetected: boolean;
bpm: number | null;
}> {
// 얼굴 피부에서 미세한 색상 변화 추적
// PPG (Photoplethysmography) 신호 추출
// 1. 얼굴 영역 검출
// 2. 프레임별 RGB 평균 계산
// 3. 시간적 신호에서 주파수 분석
// 4. 60-100 BPM 범위의 피크 찾기
return {
heartbeatDetected: true,
bpm: 72
};
}
// 눈 깜빡임 패턴 분석
async analyzeBlinkPattern(
videoPath: string
): Promise<{
naturalBlinking: boolean;
blinkRate: number;
}> {
// 자연스러운 눈 깜빡임 패턴 분석
// 딥페이크는 종종 비정상적인 깜빡임 패턴을 보임
// 1. 눈 랜드마크 추적
// 2. Eye Aspect Ratio (EAR) 계산
// 3. 깜빡임 빈도 및 지속시간 분석
return {
naturalBlinking: true,
blinkRate: 15 // 분당 깜빡임 횟수
};
}
// 호흡 패턴 검출
async detectBreathing(
videoPath: string
): Promise<{
breathingDetected: boolean;
respiratoryRate: number | null;
}> {
// 가슴/어깨 영역의 미세한 움직임 추적
return {
breathingDetected: true,
respiratoryRate: 16 // 분당 호흡수
};
}
}
디지털 포렌식 기법을 사용하여 조작 흔적을 찾습니다.
// 디지털 포렌식 분석
class ForensicAnalyzer {
// ELA (Error Level Analysis)
async performELA(
imagePath: string,
outputPath: string
): Promise {
const sharp = await import('sharp');
// 1. 이미지를 낮은 품질로 재압축
const recompressed = await sharp.default(imagePath)
.jpeg({ quality: 90 })
.toBuffer();
// 2. 원본과 재압축 이미지 차이 계산
// 3. 차이를 증폭하여 시각화
// 4. 편집된 영역은 다른 오류 레벨을 보임
console.log('✅ ELA 분석 완료');
}
// JPEG 압축 아티팩트 분석
analyzeJPEGArtifacts(
imagePath: string
): {
multipleCompressions: boolean;
compressionHistory: number[];
} {
// JPEG 압축 이력 분석
// 여러 번 압축된 영역은 딥페이크 조작 가능성
return {
multipleCompressions: false,
compressionHistory: [95, 90, 85]
};
}
// 메타데이터 검사
async examineMetadata(
filePath: string
): Promise<{
suspicious: boolean;
findings: string[];
}> {
const findings: string[] = [];
// EXIF 데이터 검사
// - 카메라 정보 일관성
// - 타임스탬프 검증
// - GPS 데이터 검증
// - 소프트웨어 서명
return {
suspicious: false,
findings
};
}
}
실시간 스트리밍에서 딥페이크를 탐지합니다.
// 실시간 딥페이크 탐지
class RealtimeDeepfakeDetector {
private detector: CNNDeepfakeDetector;
private frameBuffer: any[] = [];
private readonly BUFFER_SIZE = 30; // 1초 분량 (30 FPS)
constructor() {
this.detector = new CNNDeepfakeDetector();
}
// 비디오 스트림 처리
async processVideoStream(
streamUrl: string,
callback: (result: any) => void
): Promise {
// WebRTC 또는 RTMP 스트림 처리
// 프레임 추출 및 버퍼링
// 매 프레임마다:
// 1. 프레임을 버퍼에 추가
// 2. 버퍼가 가득 차면 분석
// 3. 결과를 콜백으로 전달
console.log('📹 실시간 스트림 처리 시작');
}
// 프레임 분석
private async analyzeFrameBuffer(): Promise<{
isDeepfake: boolean;
confidence: number;
frameTimes: number[];
}> {
// 버퍼의 모든 프레임 분석
// 시간적 일관성 검사
return {
isDeepfake: false,
confidence: 0.95,
frameTimes: []
};
}
}
여러 탐지 기법을 결합하여 정확도를 향상시킵니다.
// 앙상블 딥페이크 탐지 시스템
class EnsembleDeepfakeDetector {
private cnnDetector: CNNDeepfakeDetector;
private ganAnalyzer: GANFingerprintAnalyzer;
private bioAnalyzer: BiologicalSignalAnalyzer;
private forensicAnalyzer: ForensicAnalyzer;
async detectWithEnsemble(
mediaPath: string,
mediaType: 'image' | 'video'
): Promise<{
isDeepfake: boolean;
confidence: number;
breakdown: any;
}> {
const results: any[] = [];
// CNN 탐지
if (mediaType === 'image') {
const cnnResult = await this.cnnDetector.detectDeepfake(mediaPath);
results.push({
method: 'CNN',
weight: 0.3,
isFake: cnnResult.isFake,
confidence: cnnResult.confidence
});
}
// GAN 지문 분석
const ganResult = await this.ganAnalyzer.analyzeFrequencyDomain(mediaPath);
results.push({
method: 'GAN Fingerprint',
weight: 0.25,
isFake: ganResult.hasGANFingerprint,
confidence: ganResult.hasGANFingerprint ? 0.9 : 0.1
});
// 포렌식 분석
const forensicResult = await this.forensicAnalyzer.examineMetadata(mediaPath);
results.push({
method: 'Forensic',
weight: 0.2,
isFake: forensicResult.suspicious,
confidence: forensicResult.suspicious ? 0.85 : 0.15
});
// 비디오인 경우 생물학적 신호 분석
if (mediaType === 'video') {
const heartbeat = await this.bioAnalyzer.detectHeartbeat(mediaPath);
results.push({
method: 'Biological Signals',
weight: 0.25,
isFake: !heartbeat.heartbeatDetected,
confidence: heartbeat.heartbeatDetected ? 0.1 : 0.9
});
}
// 가중 평균 계산
let weightedSum = 0;
let totalWeight = 0;
for (const result of results) {
const score = result.isFake ? result.confidence : (1 - result.confidence);
weightedSum += score * result.weight;
totalWeight += result.weight;
}
const finalConfidence = weightedSum / totalWeight;
const isDeepfake = finalConfidence > 0.5;
return {
isDeepfake,
confidence: isDeepfake ? finalConfidence : (1 - finalConfidence),
breakdown: results
};
}
}
// 사용 예제
const ensemble = new EnsembleDeepfakeDetector();
const result = await ensemble.detectWithEnsemble('suspect_video.mp4', 'video');
console.log(`딥페이크 여부: ${result.isDeepfake ? '가짜' : '진짜'}`);
console.log(`신뢰도: ${(result.confidence * 100).toFixed(2)}%`);
console.log('상세 분석:');
result.breakdown.forEach((r: any) => {
console.log(` ${r.method}: ${r.isFake ? '가짜' : '진짜'} (${(r.confidence * 100).toFixed(2)}%)`);
});
弘益人間 (홍익인간) · 널리 인간을 이롭게 하라