如何用Javascript和Nyckel进行机器学习图像分类

294 阅读4分钟

用Javascript和Nyckel进行机器学习图像分类

人工智能已经成为技术的未来,每个人都在努力将其应用于各个领域。人工智能应用为人工智能技术做出了贡献,有交易机器人和其他应用程序。网络开发人员,也希望将这些模型整合到他们的应用程序中。

这篇文章将展示如何在网络应用中实现机器学习模型,对图像进行分类。在这里,我们将对戴和不戴面具的人的图像进行分类和识别。

要求

为了继续学习本教程,读者将需要以下条件。

  • 一个合适的编辑器,如visual studio,sublime,或其他。
  • 对Nyckel、JavaScript的预先了解。
  • HTML和CSS的基本知识。

什么是Nyckel?

Nyckel是一个机器学习API,为模型提供自动训练,而不是手动编写代码。它还允许这些模型以最佳的简单性集成到应用程序中。按照下面的每个步骤来开发你自己的支持机器学习的网络应用。

JavaScript CSS和HTML网站构建

我们将建立一个简单的网络应用程序,将一张照片从桌面上上传到应用程序中。布局中只需要一个放置照片的部分和一个按钮来对文件资源管理器进行系统调用。

建立HTML

首先,创建一个扩展名为.html 的文件,用来存放HTML代码。然后将脚本标签放在<head> 标签下,以创建与JavaScript文件的连接,该文件将在稍后阶段创建。

<html>
<head>
  <script src="https://code.jquery.com/jquery-latest.min.js"></script>
</head>

在body标签下是上传部分的位置。这段代码创建了一个可点击的上传部分,用于上传照片。

<body>

  <div id="main" class="container">

    <h1 id="title">Mask or no mask?</h1>

    <!-- Drag and Drop container-->
    <div class="upload-area" id="uploadfile">
      <h2>Drop Your photo here</h2>
    </div>
    <input type="file" name="file" id="file">
    <a id="nyckel" href="https://www.nyckel.com">Machine Learning application created by Victor</a>
  </div>
</body>

上面的代码中的分部类upload-area ,创建了一个容器,用于容纳正在上传的照片。当你运行上面的代码组合时,你应该有一个只有一个按钮和一个上传部分的网页,如下面的截图所示。

htmlResult

由于本教程没有深入涉及网站的样式设计,你可以使用你的样式,并学习如何将它们与应用程序联系起来。

当你使用上述链接中的代码时,可以得到与下面照片中类似的结果。

styled

JavaScript功能

JavaScript有助于客户端的脚本编写。然而,它主要使用函数来启用网页中的一些活动。在这个页面中,这些函数鼓励的此类行动的例子包括;通过拖动上传,向Nyckel发送AJAX请求以针对机器学习模型运行,确保图片被上传,调整大型图片的大小,以及更多。

下面的代码包含这样的功能。首先,创建一个JavaScript文件(.js)并复制&粘贴以下代码。

$(function ()
{
    // preventing the page from redirecting
    
    $("html").on("dragover", function (d)
    {
        d.preventDefault();
        d.stopPropagation();
        $("h2").text("Drag here");
    });

    $("html").on("drop", function (d) 
      { 
        d.preventDefault();
        d.stopPropagation();
        });

    // Dragging entry as 'dragenter'
    
    $('.upload-area').on('dragenter', 
    function (d)
       {
        d.stopPropagation();
        d.preventDefault();
        $("h2").text("Drop");
    });

    // Dragging over as 'dragover.'
    
    $('.upload-area').on('dragover', function (d)
    {
        d.stopPropagation();
        d.preventDefault();
        $("h2").text("Drop");
    });

    // This allows the image being dragged to be droppable
    $('.upload-area').on('drop', 
    function (d)
      {
      // after dropping the image(propagation), this prevents the page from going back to default but instead let the image stick

        d.stopPropagation();
        d.preventDefault();
        $("h2").text("Checking...");

        var file = d.originalEvent.dataTransfer.files;

        showImage(file[0]);

        resizeAndUploadImage(file[0]);
    });

    // Open file selector on div click
    // When you click on the upload area, this opens your local files location (file explorer if it is a computer)
    $("#uploadfile").click(function ()
    {
        $("#file").click();
    });

    // file selected
    $("#file").change(function ()
    {
        var file = $('#file')[0].files[0];
        showImage(file);
        resizeAndUploadImage(file);
    });
});
// This function reads the uploaded file into your application.
function showImage(file)
{
    var reader = new FileReader();
    reader.onload = function (d)
    {
        $('.upload-area').css("background-image", "url(" + d.target.result + ")");
    }
    reader.readAsDataURL(file);
}

function resizeAndUploadImage(file)
{
    // Ensure it's an image (the file must be a photo)
    if (file.type.match(/image.*/))
    {
        // Load the image
        var reader = new FileReader();
        reader.onload = function (readerEvent)
        {
            var image = new Image();
            image.onload = function (imageEvent)
            {
                // this gives the specifications to the canvas about the measurements of the uploaded image
                // It checks the image size and if it does not match the required dimensions, it is resized to fit the canvas
                var canvas = document.createElement('canvas'),
                    max_size = 600, //maximum size of any uploaded file
                    width = image.width,
                    height = image.height;
                if (width > height)
                {
                    if (width > max_size)
                    {
                        height *= max_size / width;
                        width = max_size;
                    }
                } else
                {
                    if (height > max_size)
                    {
                        width *= max_size / height;
                        height = max_size;
                    }
                    //New dimensions are given to the image if it exceeds the defined maximum
                }
                canvas.width = width;
                canvas.height = height;
                canvas.getContext('2d').drawImage(image, 0, 0, width, height);
                var dataUrl = canvas.toDataURL('image/jpeg');
                var resizedImage = dataURLToBlob(dataUrl); //the resized image is then interpreted as raw data
                
                checkImageWithNyckel(resizedImage);
            }
            image.src = readerEvent.target.result;
        }
        //this ensures that Nyckel reads the image as raw data
        reader.readAsDataURL(file);
    }
    else
    {
    // If the file is not an image, upload is rejected with an alert, and the page is reset to default
        alert("You must choose an image");
        resetPage();
    }
}

上述代码脚本的第一部分实现了不同的功能,如照片拖放、图像大小调整和文件类型,如注释中所示。用于存放上传图片的矩形区域在HTML中被称为画布。另一方面,blob代表原始数据形式的对象。

将canvas转换为blob可以将上传到你的应用程序中的图像翻译成模型,以便模型能够理解。下面的代码是一个扩展JavaScript文件的实用函数,用于将canvas转换为blob。

/* Utility function to convert a canvas to a BLOB */
var dataURLToBlob = function (dataURL)
{
    var BASE64_MARKER = ';base64,';
    if (dataURL.indexOf(BASE64_MARKER) == -1)
    {
    // The file is converted to url data which is the raaw data and split into two parts
        var parts = dataURL.split(',');
        var contentType = parts[0].split(':')[1];
        var raw = parts[1];

        return new Blob([raw], { type: contentType });
        // Once the image is uploaded, this function returns it as raw url data
    }

    var parts = dataURL.split(BASE64_MARKER);
    var contentType = parts[0].split(':')[1];
    var raw = window.atob(parts[1]);
    var rawLength = raw.length;

    var uInt8Array = new Uint8Array(rawLength);
// the blob url data parts are stored in form of an array that adjust with the data size 
    for (var i = 0; i < rawLength; ++i)
    {
        uInt8Array[i] = raw.charCodeAt(i);
    }

    return new Blob([uInt8Array], { type: contentType });
}

一旦转换完成,就需要重置页面以接受另一次上传。这可以通过紧随转换函数之后添加的以下函数来完成。

/* End Utility function to convert a canvas to a BLOB*/
function displayResult(response)
{
    resetPage();
    $("#title").text(response.labelName);
}
// After a result is obtained, this function resets the page to be ready to receive another file.
function resetPage()
{
    $("#thinking").hide();
    $(".upload-area").show();
    $("h2").text("Drop JPG here");
}

脚本的最后一节引入了AJAX(异步JavaScript和XML),调用了机器学习模型。通过向Nyckel发送一个请求,使用url对你保存的模型进行运行。复制Nyckel在训练完你的模型后提供的url,并替换此代码中给出的url。

// Sending AJAX request to Nyckel to run against ML model
function checkImageWithNyckel(image)
{
    var formdata = new FormData();
    formdata.append('file', image);
// this get your model to function as if it is in your application
    $.ajax({
        url: 'https://www.nyckel.com/v1/functions/j3l3xdfs0fv4tec7/invoke',
        type: 'post',
        data: formdata,
        contentType: false,
        processData: false,
        dataType: 'json',
        success: function (response) // the image is checked against the model for classification
        {
        // Once checked, the right classification response is displayed as "with mask" or "without mask."
            displayResult(response);

            //Show the JSON response in the console
            console.log(response);
        },
        error: function (response)
        {
        //In case the model cannot classify the image, the page is reset to indicate a classification error.
            alert("Error checking image", response);
            $("#title").show();
            resetPage();
        }
    });
}

为了将这个文件链接到HTML文件中,你将在HTML文件中的CSS链接下面创建一个JavaScript参考链接,如下图所示。

<script type="text/Javascript" src="../mlApp/js/main.js"></script>

现在刷新你的页面,试着点击上传区域。它会打开windows explorer,让你上传照片。

使用Nyckel建立机器学习模型

本节将使用Nyckel训练一个模型,对戴面具和不戴面具的人的图像进行分类。你将需要一个访问 "Nyckel网站 "的网络协会来准备模型。下面的步骤将为我们的网络应用产生一个成功的训练模型。

创建一个尼科尔账户

创建一个账户将使你能够为你的模型使用尼科尔训练网站。要注册,请到nyckel.com的注册页面来设置你与该API的连接。

  • 注册后,选择输入类型(本例为图像),添加输出类别为with maskwithout mask ,然后点击create function 按钮。
  • 在提供的区域内,上传你的照片,两张带面具的,两张不带面具的,然后用这两个标签正确标注。
  • 上传更多的照片并导入,同时检查它们的分类准确性。

用于训练的照片越多,模型的准确性就越高。

归类后,你会得到一个通知,说你的模型已经训练好了。导航到调用部分,通过上传一张与用于检查输出功能的照片不同的照片,对模型进行满意度测试。

做完这一切后,你的模型已经训练完毕,可以使用了。

机器学习模型与网络应用的整合

要将训练好的模型集成到网络应用程序中,请导航到API部分,复制给定的网址并粘贴到$ajax 下的JavaScript代码中。这个网址看起来和下图中的网址差不多,以invoke 结尾。

https://www.nyckel.com/v1/functions/j3l3xdfs0fv4tec7/invoke

一旦完成,你的应用程序就可以用训练时未包括的照片进行测试了。

应用程序实时测试

在将模型与网络应用程序整合后,你现在可以上传照片,看看这个应用程序的效果如何。下面的照片显示了一个成功的分类是如何显示的。

带有面具的照片的结果

with mask

没有面具的照片的结果

without mask

结语

在本教程中,你学到了如何训练一个模型,一个与机器学习模型兼容的网络应用程序,并将模型集成到网络应用程序中。在学习了这些之后,开发者可以建立任何支持机器学习的网络应用。

此外,Nyckel的灵活性和易用性将大大有助于人工智能技术的发展。我希望你觉得这个教程对你有帮助。