JavaScript OCRカメラ実行
解決したいこと
JavaScript OCRカメラを実行する方法を教えて下さい。
<手順>
①カメラ画像クリック
②カメラLives映像表示
※あらかじめ長方形を表示し、読み取りたいテキストの標準としたい
③シャッターボタンをクリック
※”◯”やカメラアイコンを描画
④読みっとたテキストをそれぞれにテキストボックスに転送
出来れば画像は2値化して精度を向上さたいです
該当するソースコード
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ECSS3.0</title>
<link rel="stylesheet" href="css/stylesheet.css">
<link href="css/slick.css" rel="stylesheet" type="text/css">
<link href="css/slick-theme.css" rel="stylesheet" type="text/css">
</head>
<body>
<script src="script.js"></script>
<div class="header">
<div class="header-logo"font-weight:bold;>E<span style="font-size:0.3em;font-weight:normal;">lectronic</span>
C<span style="font-size:0.3em;font-weight:normal;">heck</span>
S<span style="font-size:0.3em;font-weight:normal;">heet</span>
S<span style="font-size:0.3em;font-weight:normal;">ystem</span>
</div>
<div id="container">
<div class="circle icon">
<span class="bar top"></span>
<span class="bar middle"></span>
<span class="bar bottom"></span>
</div>
</div>
<div id="containerLogo">
<a href="index.html"><img src="images/TCD_B.jpg"></a>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$("#container").click(function () {
$(".icon").toggleClass("close");
})
</script>
</div>
<div class="main">
<nav id="nav">
<ul>
<!-- <li><a href="#" onclick="window.close(); return false;">Close</a></li> -->
<li><a href="index.html">Menu</a></li>
</ul>
</nav>
<div class="contents">
<div class="contents-item">
<img src="images/Camera.png">
<p>Camera</p>
</div>
<div class="contents-item">
<img src="images/Create.png">
<p>Create</p>
</div>
</div>
</div>
<div class="SDkEP">
<div id="inputWrapper">
<input id="input" type="search" autocomplete="off" aria-live="polite" placeholder="ED を入力">
<input id="input" type="search" autocomplete="off" aria-live="polite" placeholder="DS を入力">
</div>
</div>
<!-- <script>
document.getElementById("close").onclick = () => {
window.close();
}
</script> -->
</body>
</html>
body {
font-family: "Avenir Next";
color: #202124;
}
li{
list-style:none;
}
.header{
background-color:#26d0c9;
color:#fff;
height:100px;
}
.header-logo{
/* float:left; */
font-size:46px;
padding:20px 40px;
text-align: center;
font-weight:bold;
}
.main{
padding:25px 40px;
}
.copy-container span{
color:#ff4a4a;
}
.contents{
display: flex;
justify-content: center;
}
.contents-item:nth-of-type(2) {
margin-left: 50px;
}
.contents-item{
/* width: 125px; */
height: auto;
float:left;
margin: 50px 50px 0px 50px;
text-align: center;
}
.contents-item:nth-of-type(2) {
margin-left: 50px;
}
/* .contents-item_Camera{
/* width: 125px; */
/* height: auto;
float:left;
margin: 50px 50px 50px 288px;
text-align: center;
} */
/* .contents-item_Create{
width: 125px;
height: auto;
float:left;
margin: 50px 50px;
text-align: center;
} */
.contents-item img{
width:100%;
}
.contents-item_Camera p{
font-size:46px;
margin: 0px;
}
.contents-item_Create p{
font-size:46px;
margin: 0px;
}
.contents-item p{
font-size:46px;
margin: 0px;
}
#container {
background: tomato;
display: inline-block;
border-radius: 500px;
margin: 10px;
position: fixed;
top: 0;
right: 0;
padding: 20px;
cursor: pointer;
}
#containerLogo {
display: inline-block;
border-radius: 500px;
margin: 10px;
position: fixed;
top: 0;
left: 0;
cursor: pointer;
}
.circle {
position: relative;
width: 45px;
height: 45px;
}
.bar {
position: absolute;
height: 6px;
width: 100%;
background: white;
border-radius: 4px;
transition: ease 0.3s;
}
.top {
top: 18%;
}
.middle {
top: 48%;
}
.bottom {
top: 78%;
}
.close .top {
transform: rotate(45deg);
top: 48%;
}
.close .middle{
opacity: 0;
}
.close .bottom {
transform: rotate(-45deg);
top: 48%;
}
nav {
opacity: 0;
visibility: hidden;
transition: 0.3s;
float:left;
}
nav.active{
opacity: 1;
visibility: visible;
float:right;
}
input {
background-color: var(--search-box-bg, white);
border: none;
border-radius: calc(0.5 * var(--ntp-realbox-height));
color: var(--search-box-text);
font-size: 16px;
height: 100%;
outline: none;
padding-inline-end: 40px;
padding-inline-start: 52px;
position: relative;
width: 100%;
}
.SDkEP {
flex: 1;
display: flex;
padding: 5px 8px 0 16px;
padding-left: 14px;
justify-content: center;
}
参考にしたコード
<html>
<head>
<!-- ③ viewportを追加してスマホでも見やすくする -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no">
<!-- ① CDNでCSSを読み込み -->
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
</head>
<body>
<div id="app">
<div ref="canvas-container" style="width:60%;margin:0 auto;">
<canvas ref="canvas"></canvas>
</div>
<div class="text-center pt-3">
<!-- ② Status によって表示ブロックを切り替える -->
<!-- play: カメラの映像をキャンバスにリアルタイムで表示 -->
<div v-if="status=='play'">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold px-8 py-3 rounded" @click="takeSnapshot">
スナップショットを取る
</button>
</div>
<!-- pause: スナップショットを撮ったので一次停止 -->
<div v-if="status=='pause'">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold px-8 py-3 mr-1 rounded" @click="runOcr">
ISBNを読み取る
</button>
<button class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 ml-1 border border-blue-500 hover:border-transparent rounded" @click="playVideo">
戻る
</button>
</div>
<!-- pause: スナップショットをOCRにかけてテキストを取得 -->
<div v-if="status=='reading'">
読み取り中です...
</div>
</div>
</div>
<!-- ① CDNでJavaScriptを読み込み -->
<script src="https://unpkg.com/vue@3.0.0/dist/vue.global.prod.js"></script>
<script src='https://unpkg.com/tesseract.js@v2.1.0/dist/tesseract.min.js'></script>
<script>
Vue.createApp({
data() {
return {
video: null,
canvas: null,
context: null,
dataUrl: '',
status: 'none'
}
},
methods: {
// ① カメラとキャンバスの準備
initialize() {
this.status = 'initialize';
navigator.mediaDevices.getUserMedia({
video: {
facingMode: {
ideal: 'environment'
}
}
})
.then(stream => {
this.canvas = this.$refs.canvas;
this.context = this.canvas.getContext('2d');
this.video = document.createElement('video');
this.video.addEventListener('loadedmetadata', () => { // メタデータが取得できるようになったら実行
const canvasContainer = this.$refs['canvas-container'];
this.canvas.width = canvasContainer.offsetWidth;
this.canvas.height = parseInt(this.canvas.width * this.video.videoHeight / this.video.videoWidth);
this.render();
});
// iOSのために以下3つの設定が必要
this.video.setAttribute('autoplay', '');
this.video.setAttribute('muted', '');
this.video.setAttribute('playsinline', '');
this.video.srcObject = stream;
this.playVideo();
})
.catch(error => console.log(error));
},
render() {
if(this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
this.context.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
}
requestAnimationFrame(this.render);
},
runOcr() { // ③ スナップショットからテキストを抽出
this.status = 'reading';
Tesseract.recognize(this.dataUrl, 'eng', {
logger: log => {
console.log(log);
}
})
.then(result => {
alert(result.data.text);
})
.catch(error => console.log(error))
.finally(() => {
this.playVideo();
});
},
playVideo() {
this.video.play();
this.status = 'play';
},
pauseVideo() {
this.video.pause();
this.status = 'pause';
},
takeSnapshot() { // ② スナップショットを取る(カメラは一時停止)
// this.makeSound(); // 音を鳴らす
this.pauseVideo();
this.dataUrl = this.canvas.toDataURL();
},
makeSound() { // ④ おまけ:スナップショットをとるときに音をならす
document.querySelectorAll('.notification-iframe').forEach(el => el.remove()); // 全ての通知用 iFrame を削除
// soundタグは使わず iFrame で直接音声ファイルへアクセスする
const iFrame = document.createElement('iframe');
iFrame.setAttribute('src', '/audios/insight.ogg');
iFrame.setAttribute('allow', 'autoplay');
iFrame.style.display = 'none';
iFrame.className = 'notification-iframe';
document.body.appendChild(iFrame);
}
},
mounted() {
this.initialize();
}
}).mount('#app');
</script>
</body>
</html>
1 likes
