@frswataru (本石 渉)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

JavaScript OCRカメラ実行

解決したいこと

JavaScript OCRカメラを実行する方法を教えて下さい。
スクリーンショット 2020-12-24 165300.jpg
<手順>
①カメラ画像クリック
②カメラ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

1Answer

tesseract.jsを使ったOCRのプログラムを貼っておきます。
jsフォルダを作り、jquery-3.5.1.min.jsとtesseract-1.0.10.jsを置いてください。
あとはhtmlファイルを作り、下記をコピペすれば動きます。
カメラでのOCRではありませんが、参考になればと思い、投稿しました。
[動かし方]
上側のcanvasで文字を書く。recognizeボタンを押下する。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src='js/tesseract-1.0.10.js'></script>
<script src='js/jquery-3.5.1.min.js'></script>
<title>tesseract.js</title>
<style>
#my-canvas {
    border: 1px #888 solid;
}
</style>
<script>
$(() => {
    let writeFlag = false,
        preX, preY;
    // canvasへのペイント
    $('#my-canvas').mousedown(e => {
        preX = e.offsetX;
        preY = e.offsetY;
        writeFlag = true;
    });

    $('#my-canvas').mousemove(e => {
        if(!writeFlag) {
            return;
        }
        let curX = e.offsetX,
            curY = e.offsetY;
        
        const ctx = $('#my-canvas')[0].getContext('2d');
        ctx.save();

        ctx.strokeStyle = 'black';
        ctx.lineWidth = 10;
        ctx.lineCap = "round";
        ctx.beginPath();
        ctx.moveTo(preX, preY);
        ctx.lineTo(curX, curY);
        ctx.stroke();

        ctx.restore();

        preX = curX;
        preY = curY;
    });

    $('#my-canvas').mouseup(e => {
        writeFlag = false;
    });

    $('#my-canvas').mouseout(e => {
        writeFlag = false;
    });

    $('#recognize-button').click(e => {
        recognize();
    });

    $('#clear-button').click(e => {
        fillCanvas();
    });

    function fillCanvas() {
        const ctx = $('#my-canvas')[0].getContext('2d');
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    }

    function recognize(evt) {
        Tesseract
        .recognize($('#my-canvas')[0], { 
            lang: 'jpn', 
            tessedit_pageseg_mode: "RAW_LINE",
            //tessedit_char_whitelist: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
        })
        .progress(function (p) {
            // 進歩状況の表示
            $('#progress').text(p.status + " " + Math.round(p.progress * 100));
        })
        .then(function (result) {
            $('#progress').text('');
            // 結果の表示
            $('#ocrResult').val(result.text);
        });
    }

    fillCanvas();    
});

</script>
</head>
<body>
<div>
    <canvas id="my-canvas" width="400" height="200"></canvas>
    <br>
    <button id="recognize-button">recognize</button>
    <button id="clear-button">clear</button>
</div>
<br>
<div>
    進捗: <span id="progress">0</span>%
</div>
<div>
    <textarea id="ocrResult" style="resize:none; width: 400px; height: 100px;"></textarea>
</div>
</body>
</html>



0Like

Comments

  1. @frswataru

    Questioner

    tesseract-1.0.10.jsはどこでインストールしますか
  2. @frswataru

    Questioner

    ターミナルをつっかてインストールですか

    # For v1
    npm install tesseract.js@1
    yarn add tesseract.js@1

Your answer might help someone💌