중요 코드 모음
스크린샷 모음
에러 모음
API 문서
테이블 구조
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>이미지 텍스트화</title>
<link rel="stylesheet" href="../css/all.css" />
<link rel="stylesheet" href="../css/scan.css" />
<script src="<https://code.jquery.com/jquery-3.6.4.min.js>"></script>
<script src="<https://cdn.jsdelivr.net/npm/tesseract.js@4/dist/tesseract.min.js>"></script>
</head>
<body>
<video id="webcam" autoplay></video>
<header>
<a href="../index.html">
<img src="../img/x.png" id="x" />
</a>
</header>
<main>
<p id="scan-title">영수증을 스캔해 주세요</p>
<img src="../img/scan-line.png" id="scan-line" />
<div id="box"></div>
</main>
<footer>
<div id="gallery-div" onclick="triggerFileInput()">
<img src="../img/gallery.png" id="gallery" />
<input
type="file"
id="imageInput"
accept="image/*"
style="display: none"
onchange="handleImageChange()"
/>
</div>
<div id="scan-div">
<img src="../img/scan-box.png" id="scan-box" />
<canvas id="scanCanvas" style="display: none"></canvas>
<p id="box-title" onclick="scanImage()">스캔하기</p>
</div>
</footer>
<div id="result"></div>
<script src="../js/scan.js"></script>
</body>
</html>
// 이벤트 위임을 사용하여 footer p 요소의 배경색 변경
document
.getElementById("main-content")
.addEventListener("click", function (event) {
if (event.target.closest("#travel-box")) {
const footerP = document.querySelector("footer p");
footerP.classList.toggle("active");
}
});
// 웹캠을 시작하는 함수
const startWebcam = () => {
const video = document.getElementById("webcam");
navigator.mediaDevices
.getUserMedia({ video: true })
.then((stream) => {
video.srcObject = stream;
})
.catch((error) => {
console.error("웹캠에 접근하는 중 오류 발생:", error);
});
};
// 이미지 스캔 함수
const scanImage = () => {
const video = document.getElementById("webcam");
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
context.drawImage(video, 0, 0, canvas.width, canvas.height);
processImage(canvas);
};
// 파일 입력이 변경되었을 때 이미지를 처리하는 함수
const handleImageChange = () => {
const input = document.getElementById("imageInput");
const file = input.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function (e) {
const img = new Image();
img.src = e.target.result;
img.onload = function () {
processImage(img);
};
};
reader.readAsDataURL(file);
} else {
console.error("이미지 파일을 선택하세요.");
}
};
// 이미지를 인식하여 텍스트로 변환하는 함수
const processImage = (image) => {
showLoadingRedirect();
Tesseract.recognize(image, "eng+jpn", {
logger: (m) => console.log(m),
})
.then(({ data: { text } }) => {
console.log(text);
alert("텍스트: " + text);
sendTextToAPI(text);
})
.catch((err) => console.error(err));
};
// 일본식 숫자를 아라비아 숫자로 변환하는 함수
const convertJapaneseNumbers = (input) => {
const japaneseNumbers = {
"①": "1",
"②": "2",
"③": "3",
"④": "4",
"⑤": "5",
"⑥": "6",
"⑦": "7",
"⑧": "8",
"⑨": "9",
"⑩": "10",
"⑪": "11",
"⑫": "12",
"⑬": "13",
"⑭": "14",
"⑮": "15",
"⑯": "16",
"⑰": "17",
"⑱": "18",
"⑲": "19",
"⑳": "20",
};
let result = input.replace(/\\n/g, " ").replace(/\\\\[\\s\\n\\r]*/g, "");
for (const [japanese, arabic] of Object.entries(japaneseNumbers)) {
result = result.replace(new RegExp(japanese, "g"), arabic);
}
return result;
};
// 텍스트를 API로 전송하는 함수
const sendTextToAPI = (text) => {
const convertedText = convertJapaneseNumbers(text);
console.log(convertedText);
if (convertedText) {
const url = "<http://localhost:8085/api/openai/chat>";
const body = JSON.stringify({ prompt: convertedText.trim() });
fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: body,
})
.then((response) => {
if (!response.ok) throw new Error("Network response was not ok");
return response.text();
})
.then((data) => {
console.log("API 응답:", data);
// 예시 데이터
const receiptData = {
items: [
{ item: "라멘", price: 68, quantity: 1 },
{ item: "오니자이", price: 98, quantity: 1 },
{ item: "이치고 초콜릿", price: 228, quantity: 1 },
{ item: "톤카우", price: 88, quantity: 2 },
],
tax: 45,
total: 527,
};
localStorage.setItem("receiptData", JSON.stringify(receiptData));
// window.location.href = "scan-receipt.html";
})
.catch((error) => {
console.error("API 요청 중 오류 발생:", error);
alert("API 요청 중 오류 발생: " + error.message);
});
} else {
console.error("유효한 텍스트가 없습니다.");
}
};
// 선택한 이미지를 표시하는 함수
const displaySelectedImage = () => {
const input = document.getElementById("imageInput");
const img = document.getElementById("gallery");
if (input.files && input.files[0]) {
const reader = new FileReader();
reader.onload = (e) => {
img.src = e.target.result;
};
reader.readAsDataURL(input.files[0]);
}
};
// 파일 입력 트리거 함수
const triggerFileInput = () => {
document.getElementById("imageInput").click();
};
// 로딩 GIF를 표시하고 페이지를 리디렉션하는 함수
const showLoadingRedirect = () => {
const gifContainer = document.createElement("div");
gifContainer.className = "gif";
gifContainer.innerHTML = '<img src="../img/loading.gif" alt="Loading...">';
document.body.appendChild(gifContainer);
setTimeout(() => {
// window.location.href = "./scan-receipt.html";
document.body.removeChild(gifContainer);
}, 3000);
};
// DOM이 로드되면 웹캠을 시작
document.addEventListener("DOMContentLoaded", startWebcam);