SassidoとTeachable Machineを使っている果物品質発見ウェブアプリ


こんにちは!私は最近、果物(リンゴ、オレンジまたはバナナ)が新鮮か腐っているかどうかを識別できるWebアプリケーションを構築し、私はそれについて行った方法を共有したいと思います.私は、これは面白いアイデアでも、実際の生活のアプリケーションを持っている何かだと思いました.果物をスキャンして、腐敗したものを取り除くことができる自動化されたツールは、農業産業で本当に有益です.私はGoogleの教授マシンを使用して画像を格納するための機械学習モデルと刺身を訓練する.ユーザーは、画像をアップロードするか、予測結果を得るためにウェブカメラを使用することができます.
ウェブサイトがどのように働くかについて示している短いデモビデオは、ここにあります.

目次

  • Trainable Machine
  • SashiDo
  • Frontend
  • Webcam based prediction
  • Uploaded image based prediction
  • Conclusion
  • Github link
  • References
  • 訓練機械

    For classifying fruits the first step is to generate a ML model. Teachable machine 入力型、すなわち画像、オーディオ、ポーズに基づいてモデルの3種類を生成するために使用することができますWebベースのツールです.私はイメージプロジェクトを作成し、新鮮なだけでなく、リンゴやオレンジ、バナナのオレンジ色のサンプルから撮影された腐ったサンプルの画像をアップロードしました.私はOpencvを使って224 * 224にイメージを変えて、各々のクラスで100のイメージだけをとりました.

    エポック、学習率とバッチサイズのいくつかの高度な設定がありますが、私はデフォルトのものは十分にタスクのために良い感じた.トレーニング後、モデルをエクスポートしてアップロードしました.これは、クラウドに格納し、プロジェクトで使用できる共有のパブリックリンクを提供します.

    次のステップは、モデルを使用して分類を実行することです.入力を提供する2つの方法があります.

    さし道

    SashiDo is a beautiful backend as a service platform and has a lot of built in functions.In this project, I've used only the Files functionality to store images uploaded by users.I agree that this isn't totally necessary but it is a great way to obtain more samples from the public and build a better dataset.To connect the application with SashiDo copy the code in the getting started page in SashiDo's Dashboard to the javascript file and also add the following script.

    <script src=https://unpkg.com/parse/dist/parse.min.js></script>
    

    フロントエンド

    I've created two buttons to start/stop the webcam and to upload image, an input element for file upload and 3 empty divs to display the webcam input,image input and the output(prediction result).I have used Bootstrap, so in case you're not familiar with it, the class names basically correspond to various utilities in it.

    <label for="webcam" class="ps-3 pt-3 pb-3">USE WEBCAM:</label>
    <button id="webcam" type="button" class="btn btn-outline-primary ms-3" onclick="useWebcam()">Start webcam</button><br />
    <label class="p-3" for="fruitimg">UPLOAD IMAGE:</label>
    <div class="input-group px-3 pb-3" id="inputimg">
        <input type="file" class="form-control" accept="image/*" id="fruitimg">
        <button class="btn btn-outline-primary" id="loadBtn">Load</button>
    </div>
    <div id="webcam-container" class="px-3"></div>
    <div id="uploadedImage" class="px-3"></div>
    <div id="label-container" class="px-3 pt-3"></div>       
    

    ウェブカメラベース予測


    モデルは簡単に画像のためのTeachableマシンライブラリを使用して当社のJavaScriptプロジェクトで使用することができます.ライブラリを使用するには、次のスクリプトをHTMLファイルの下部に追加します.また、NPMからライブラリをインストールすることもできます.
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
    <script
        src="https://cdn.jsdelivr.net/npm/@teachablemachine/[email protected]/dist/teachablemachine-image.min.js">
    </script>
    
    次のコードは、Webカメラボタンを切り替えるといくつかの変数を宣言するのに役立ちます.URL定数はモデルリンクに設定されます.
    const URL = "https://teachablemachine.withgoogle.com/models/N58PlX_GN/";
    
    let model, webcam, newlabel, canvas, labelContainer, maxPredictions, camera_on = false, image_upload = false;
    
    function useWebcam() {
        camera_on = !camera_on;
    
        if (camera_on) {
            init();
            document.getElementById("webcam").innerHTML = "Close Webcam";
        }
        else {
            stopWebcam();
            document.getElementById("webcam").innerHTML = "Start Webcam";
        }
    }
    
    async function stopWebcam() {
        await webcam.stop();
        document.getElementById("webcam-container").removeChild(webcam.canvas);
        labelContainer.removeChild(newlabel);
    }
    
    現在、我々はモデルをロードすることができて、予測を実行して、最高確率を持っているクラスを表示することができます.
    // Load the image model and setup the webcam
    async function init() {
    
        const modelURL = URL + "model.json";
        const metadataURL = URL + "metadata.json";
    
        // load the model and metadata
        model = await tmImage.load(modelURL, metadataURL);
        maxPredictions = model.getTotalClasses();
    
        // Convenience function to setup a webcam
        const flip = true; // whether to flip the webcam
        webcam = new tmImage.Webcam(200, 200, flip); // width, height, flip
        await webcam.setup(); // request access to the webcam
        await webcam.play();
        window.requestAnimationFrame(loop);
    
        // append element to the DOM
        document.getElementById("webcam-container").appendChild(webcam.canvas);
    
        newlabel = document.createElement("div");
        labelContainer = document.getElementById("label-container");
        labelContainer.appendChild(newlabel);
    }
    
    async function loop() {
        webcam.update(); // update the webcam frame
        await predict(webcam.canvas);
        window.requestAnimationFrame(loop);
    }
    
    async function predict(input) {
        // predict can take in an image, video or canvas html element
        const prediction = await model.predict(input);
    
        var highestVal = 0.00;
        var bestClass = "";
        result = document.getElementById("label-container");
        for (let i = 0; i < maxPredictions; i++) {
            var classPrediction = prediction[i].probability.toFixed(2);
            if (classPrediction > highestVal) {
                highestVal = classPrediction;
                bestClass = prediction[i].className;
            }
        }
    
        if (bestClass == "Fresh Banana" || bestClass == "Fresh Apple" || bestClass == "Fresh Orange") {
            newlabel.className = "alert alert-success";
        }
        else {
            newlabel.className = "alert alert-danger";
        }
    
        newlabel.innerHTML = bestClass;
    }
    

    アップロード画像ベース予測


    入力を提供する第2の方法は、画像をアップロードすることです.私はjQueryコードのビットを使用してこれを行う.本質的に、ユーザーが一度クライアント側の入力要素を使用しているイメージファイルを選んで、ロードをクリックすると、ファイルへの参照はクリックハンドラを使用して得られる.そして、新規なparseファイルはつくられる.パースファイルは、オブジェクトに保存するには大きすぎるクラウド内のアプリケーションファイルを保存します.次に、保存されたイメージを表示するキャンバス要素を作成し、アップロードされた画像のクラスを予測するために使用します.
    $(document).ready(function () {
        $("#loadBtn").on("click", async function () {
    
            labelContainer = document.getElementById("label-container");
    
            image_upload = !image_upload;
    
            if (!image_upload) {
                labelContainer.removeChild(newlabel);
                document.getElementById("uploadedImage").removeChild(canvas);
            }
    
            const fileUploadControl = $("#fruitimg")[0];
            if (fileUploadControl.files.length > 0) {
    
                const modelURL = URL + "model.json";
                const metadataURL = URL + "metadata.json";
    
                // load the model and metadata
                model = await tmImage.load(modelURL, metadataURL);
                maxPredictions = model.getTotalClasses();
    
                const file = fileUploadControl.files[0];
    
                const name = "photo.jpg";
                const parseFile = new Parse.File(name, file);
    
                parseFile.save().then(async function () {
                    //The file has been saved to the Parse server
    
                    img = new Image(224, 224);
                    img.crossOrigin = "Anonymous";
                    img.addEventListener("load", getPredictions, false);
                    img.src = parseFile.url();
    
                }, function (error) {
                    // The file either could not be read, or could not be saved to Parse.
                    result.innerHTML = "Uploading your image failed!";
                });
            }
            else {
                result.innerHTML = "Try Again!";
            }
        });
    });
    
    以下のコードでは、キャンバスはイメージを表示するためにつくられます、そして、予測はウェブカメラのために使われた同じ予測機能を使用してされます.
    async function getPredictions() {
    
        canvas = document.createElement("canvas");
        var context = canvas.getContext("2d");
        canvas.width = "224";
        canvas.height = "224";
        context.drawImage(img, 0, 0);
        document.getElementById("uploadedImage").appendChild(canvas);
    
        newlabel = document.createElement("div");
        labelContainer = document.getElementById("label-container");
        labelContainer.appendChild(newlabel);
    
        await predict(canvas);
    }
    
    それだ!どんな果物も、現在欠陥のためにテストされることができます.

    結論

    I had a lot of fun making this project and learnt a lot doing it.I hadn't used SashiDo nor Teachable machine before so this was a nice opportunity for me to learn about them.I hope you enjoyed reading this.I think this is a pretty simple project, so if you have some time and are interested, go ahead and try building it yourself!

    ギタブリンク

    Github repo
    Check out the project here

    参考文献

    SashiDo - https://www.sashido.io/en/
    ティーチングマシンhttps://teachablemachine.withgoogle.com/
    教育用機械ライブラリhttps://github.com/googlecreativelab/teachablemachine-community/tree/master/libraries/image
    データセットhttps://www.kaggle.com/sriramr/fruits-fresh-and-rotten-for-classification
    SDKのパースhttps://github.com/parse-community/Parse-SDK-JS
    パースファイルhttps://docs.parseplatform.org/js/guide/#creating-a-parsefile