前端与ai碰撞会摩擦出什么样的火花?

176 阅读5分钟

近些年来人工智能ai又火起来了,这一下点燃了整个互联网,我们知道写ai的计算机语言一般是python,而对于一些使用其他语言想写ai的人是望而却步,现如今,使用colab google 提供的在线nlp实验室(免费),js也可以写ai,这无疑对于前端来说是一个好消息,如果你想了解前端和ai是怎么结合的,请仔细阅读本文,一窥其中的奥妙,话不多说,跟上我的思路。

  • 在开始前,我们可以先了解一下colab的部分功能,适应感受一下
  • 打开网站,点击新建笔记本

image.png

  • 输入代码安装transforms,点击运行
# 安装transformers 机器学习库 进行情感分析
!pip install transformers

image.png

  • 输入代码,运行
from transformers import pipeline # 派发一个工作,模块
classifier = pipeline('sentiment-analysis') # 派发了nlp任务中的情感分析任务
output = classifier('I like you')
print(output)

image.png 运行结果:

image.png 由结果可以知道,“I like you”这句话的积极程度为0.999,可以说,这句话非常nice。

  • 输入另一句话,运行
result = classifier('I hate you')
print(result)

image.png 结果显示,“I hate you”这句话的消极程度为0.999,可以说,这句话非常的不满。

  • 以上情感分析的任务,我们可以很轻松的完成,不需要你从头开始安装软件,配置环境,也不需要你懂“情感分析”里面的判断逻辑,只需输入几串代码就可以完成,ai会自动帮你配置,这就是ai的魅力,使小白能够轻松入手。

  • 既然使用ai如此简单,我们不妨可以将前端和ai结合起来,进行人工智能才会做的图片识别任务,下面难度将会升级,但相对以前的图片分析过程来说会简单很多。

  • 先上传图片,制作一个上传图片的功能,不做详细解释

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>nlp之图片识别,两种语言</title>
    <style>
    .container {
        margin: 40px auto;
        width: max(50vw, 400px);
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .custom-file-upload {
        display: flex;
        align-items: center;
        cursor: pointer;
        gap:10px;
        border: 2px solid black;
        padding: 8px 16px;
        border-radius: 6px;
    }
    #file-upload {
        display: none;
    }
    #image-container {
        width: 100%;
        margin-top:20px;
        position: relative;
    }
    #image-container>img {
        width: 100%;
    }
    .bounding-box {
        position: absolute;
        box-sizing: border-box;
    }
    .bounding-box-label {
        position: absolute;
        color: white;
        font-size: 12px;
    }

    </style>
</head>
<body>
    <!-- 语义化 main就比div 更好 页面中的主体内容 -->
    <!-- css 选择器 -->
    <main class="container">
        <label for="file-upload" class="custom-file-upload">
            <!-- <input type="file" id="file-upload" accept="image/*"> -->
            <input type="file" accept="image/*" id="file-upload">
            上传图片
        </label>
        <div id="image-container">

        </div>
        <p id="status"></p >
    </main>
    
</body>
</html>

效果图: image.png

  • 图片识别的功能放在js中,这段代码我会详细注释,代码如下:
<script type="module">
    // transformers npl 任务 ,引入所需模块transformers
    import { pipeline, env } from "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0"
    env.allowLocalModels = false;
    
    //获取文件上传输入框和图像容器的引用
    const fileUpload = document.getElementById('file-upload');
    const imageContainer = document.getElementById('image-container')
    //当文件上传输入框内容改变时触发的事件监听器
    fileUpload.addEventListener('change', function(e) {
        // console.log(e.target.files[0]);
        //获取用户上传的文件
        const file = e.target.files[0];
        // 新建一个FileReader 对象, 01 序列 
        // 图片比较大 
        const reader = new FileReader();

        //当文件读取完成时触发的事件处理函数
        reader.onload = function(e2) {
            // 读完了, 加载完成
            const image = document.createElement('img'); // 图片对象
            console.log(e2.target.result);
            image.src = e2.target.result;
            imageContainer.appendChild(image)
            detect(image) // 启动ai任务  功能模块化,封装出去
        }
        reader.readAsDataURL(file)
    })
    const status = document.getElementById('status');
    // 检测图片的AI任务
    const detect = async (image) => {
        status.textContent = "分析中..." 
        const detector = await pipeline("object-detection", 
        "Xenova/detr-resnet-50") // model 实例化了detector对象
        const output = await detector(image.src, {
            threshold: 0.1,
            percentage: true
        })
        // console.log(output);
        output.forEach(renderBox)
    } 

    // 绘制边界框的函数
    function renderBox({box, label}) {
        
        console.log(box, label);
        // 解构出边界框的坐标信息
        const { xmax, xmin, ymax, ymin} = box
        //创建一个div元素作为边界框
        const boxElement = document.createElement("div");
        //添加类名
        boxElement.className = "bounding-box"
        //设置边框样式和位置
        Object.assign(boxElement.style, {
            borderColor: '#123123',
            borderWidth: '1px',
            borderStyle: 'solid',
            left: 100*xmin + '%',
            top: 100 *ymin + '%',
            width: 100*(xmax-xmin) + "%",
            height: 100*(ymax-ymin) + "%"
        })
        // 创建一个span元素作为标签,用于显示物体类别
        const labelElement = document.createElement('span');
        labelElement.textContent = label;
        labelElement.className = "bounding-box-label"
        labelElement.style.backgroundColor = '#000000'

        //将标签添加到边界框中
        boxElement.appendChild(labelElement);
        boxElement.appendChild(labelElement);
        // 将边界框添加到图像容器中
        imageContainer.appendChild(boxElement);
    }

    
    </script>

整体代码(运行需科学上网):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>nlp之图片识别,两种语言</title>
    <style>
    .container {
        margin: 40px auto;
        width: max(50vw, 400px);
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .custom-file-upload {
        display: flex;
        align-items: center;
        cursor: pointer;
        gap:10px;
        border: 2px solid black;
        padding: 8px 16px;
        border-radius: 6px;
    }
    #file-upload {
        display: none;
    }
    #image-container {
        width: 100%;
        margin-top:20px;
        position: relative;
    }
    #image-container>img {
        width: 100%;
    }
    .bounding-box {
        position: absolute;
        box-sizing: border-box;
    }
    .bounding-box-label {
        position: absolute;
        color: white;
        font-size: 12px;
    }

    </style>
</head>
<body>
    <!-- 语义化 main就比div 更好 页面中的主体内容 -->
    <!-- css 选择器 -->
    <main class="container">
        <label for="file-upload" class="custom-file-upload">
            <!-- <input type="file" id="file-upload" accept="image/*"> -->
            <input type="file" accept="image/*" id="file-upload">
            上传图片
        </label>
        <div id="image-container">

        </div>
        <p id="status"></p >
    </main>
    <script type="module">
    // transformers npl 任务 
    import { pipeline, env } from "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0"
    env.allowLocalModels = false;

    const fileUpload = document.getElementById('file-upload');
    const imageContainer = document.getElementById('image-container')
    fileUpload.addEventListener('change', function(e) {
        // console.log(e.target.files[0]);

        const file = e.target.files[0];
        // 新建一个FileReader 对象, 01 序列 
        // 图片比较大 
        const reader = new FileReader();
        reader.onload = function(e2) {
            // 读完了, 加载完成
            const image = document.createElement('img'); // 图片对象
            console.log(e2.target.result);
            image.src = e2.target.result;
            imageContainer.appendChild(image)
            detect(image) // 启动ai任务  功能模块化,封装出去
        }
        reader.readAsDataURL(file)
    })
    const status = document.getElementById('status');
    // 检测图片的AI任务
    const detect = async (image) => {
        status.textContent = "分析中..." 
        const detector = await pipeline("object-detection", 
        "Xenova/detr-resnet-50") // model 实例化了detector对象
        const output = await detector(image.src, {
            threshold: 0.1,
            percentage: true
        })
        // console.log(output);
        output.forEach(renderBox)
    } 

    function renderBox({box, label}) {
        console.log(box, label);
        const { xmax, xmin, ymax, ymin} = box
        const boxElement = document.createElement("div");
        boxElement.className = "bounding-box"
        Object.assign(boxElement.style, {
            borderColor: '#123123',
            borderWidth: '1px',
            borderStyle: 'solid',
            left: 100*xmin + '%',
            top: 100 *ymin + '%',
            width: 100*(xmax-xmin) + "%",
            height: 100*(ymax-ymin) + "%"
        })
        const labelElement = document.createElement('span');
    labelElement.textContent = label;
    labelElement.className = "bounding-box-label"
    labelElement.style.backgroundColor = '#000000'

    boxElement.appendChild(labelElement);
    boxElement.appendChild(labelElement);
    imageContainer.appendChild(boxElement);
    }

    
    </script>
</body>
</html>

效果图:

image.png

  • 最后

    看到这里,我想你大概已经感受到了前端和ai碰撞之后的美妙,以后的生活和ai息息相关,希望掘友们能够能够在ai的世界中畅游!