likes
comments
collection
share

前端与 AI 融合:图片识别技术的创新之旅

作者站长头像
站长
· 阅读数 20

前言

在信息技术飞速发展的时代,前端开发和 AI 技术正以令人惊叹的速度融合在一起。而图片识别作为两者结合的一个重要应用领域,正逐渐改变着我们的生活和工作方式。 一个小白如何结合ai与前端技术紧跟时代潮流呢?

下面的代码会让很多同学难以接受、看不懂各种api。因此在这里我想让各位同学一定要转变思维,api是可以慢慢积累的,我们不妨先用起来,知道这是干什么的,勇于去接受它,这样我们才能以最快的速度进步。

接下来以做一个图片识别应用为引子,欢迎大家相互探讨。

想做的事情

图片检测,这里先附上最终的效果,然后再来谈如何实现。

前端与 AI 融合:图片识别技术的创新之旅 点击上传图片,我们选中任意一张图片,通过ai帮助我们完成对图片的识别功能,并且识别的同时还能获取位置,将图片进行渲染

前端与 AI 融合:图片识别技术的创新之旅

实现过程:主体页面部分

  • 有一个主要的容器 main,其中包含了图片上传的控件和图片显示区域。
  • input type="file" id="file - upload":创建一个文件上传输入框,用于用户选择要上传的图片。
  • #image - {insert_element_2_Y29udGFpbmVy} 是图片显示的div容器,用于获取用户上传的图片并展示在页面
  • p#status 用p标签显示状态信息,比如分析中。
<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>

实现过程:脚本部分

  • 引入transformers库导入pipeline,env模块,用于执行nlp任务。
    • 这里我们需要了解一下transformers库是用来做什么的。Transformers 库是一个开源库,提供的所有预训练模型都是基于 Transformer 模型结构。可以使用 Transformers 库提供的 API 轻松下载和训练最先进的预训练模型。
    • 在 transformers 库中,pipeline()函数是最基本的对象。通过向 pipeline 对象提供任务名称,然后从 Hugging Face 模型存储库中自动下载合适的模型,就可以使用了。例如我们想做情感分析,我们便可以传入entiment-analysis:情感分析;模型,轻松完成ai任务
  • cdn.jsdelivr.net 是一个内容分发网络(CDN),通过从 CDN 导入模块,可以提高模块的加载速度,特别是在网络延迟较高的情况下。
  • from后边接的那一串是一个远程地址,从该地址导入pipeline 和 env 两个模块。
// transformers库导入pipeline模块 npl 任务 
import { pipeline, env } from "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0"
  • 设置当前环境对象,禁止加载本地模型,使用远程加载。
       // 设置当前的环境对象 不要加载本地模型,使用远程加载 transformers库
       env.allowLocalModels = false;
  • 为文件上传输入框添加 change 事件监听器。当用户选择文件时:
    • 获取上传的文件。
    • 创建一个 FileReader 对象。用于读取图片文件
    • 在 reader.onload 回调函数中,创建一个图片元素,并设置其 src 属性为读取到的图片数据。
    • 将图片添加到图片显示容器中。
    • 详细在注释中
        // 获取上传图片的input元素
        const fileUpload = document.getElementById('file-upload');
        // 获取一会儿显示加载出来图片的div容器
        const imageContainer = document.getElementById('image-container')
        // 文件输入框元素添加监听器 事件名称change 指定触发事件执行的函数
        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);
                //加载完毕后通过e2.target.result获取图片src赋予图片对象
                image.src = e2.target.result;
                //添加图片src获取图片展示到div中
                imageContainer.appendChild(image)
                // 拿到图片后可以正式启动ai任务detect(图片检测)  功能模块化,封装出去
                detect(image)
            }
            reader.readAsDataURL(file)
        })

  • 封装思想将detect函数封装到外面,将功能模块化
  • detect 函数用于启动图片检测的 AI 任务。它在获取到上传的图片后,更新状态信息,并使用 pipeline 和指定的模型进行检测。
  • renderBox 函数用于处理检测结果,根据边界框信息和标签创建相应的边界框元素和标签元素,并添加到图片显示容器中。
  • 通过pipeline指定特定模型用于物体检测,并将其实例化
  • 使用 await 等待 detector 对象,确保模型完全加载后再继续。
  • output返回检测对象结果
  • renderBox函数用于渲染边界框
// 获取主体中我们创建的p标签 用于展示状态
const status = document.getElementById('status');
        // 通过pipeline启动一个检测图片的AI任务并选择合适的模型
        //ai任务封装
        const detect = async (image) => {
            //加载时在p标签中显示内容:分析中
            status.textContent = "分析中...";
            //选择合适任务和模型,做物体检测选用object-detection,模型选用"Xenova/detr-resnet-50"
            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) + "%"
            })
            
            // 创建一个span元素
            const labelElement = document.createElement('span');
            labelElement.textContent = label;
            labelElement.className = "bounding-box-label"
            labelElement.style.backgroundColor = '#000000'

            boxElement.appendChild(labelElement);
            imageContainer.appendChild(boxElement);
        }
  • 详细说明都在注释

效果

前端与 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>


    <script type="module">
        // transformers库导入pipeline模块 npl 任务 
        import { pipeline, env } from "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0"
        // 设置当前的环境对象 不要加载本地模型,使用远程加载 transformers库
        env.allowLocalModels = false;
        // 通过id获取input元素
        const fileUpload = document.getElementById('file-upload');
        const imageContainer = document.getElementById('image-container')
        // 文件输入框元素添加监听器 事件名称change 指定触发事件执行的函数
        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;
                //添加图片src获取图片展示到div中
                imageContainer.appendChild(image)
                // 启动ai任务  功能模块化,封装出去
                detect(image)
            }
            reader.readAsDataURL(file)
        })

        const status = document.getElementById('status');
        // 通过pipeline启动一个检测图片的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);
            imageContainer.appendChild(boxElement);
        }
    </script>
</body>

</html>

结语

AI与前端可以完美融合,让我们积极拥抱创新,迎接未来的无限可能!

转载自:https://juejin.cn/post/7358813120841990154
评论
请登录