使用 JavaScript 和 Transformers 实现图像对象检测的简易教程

引言

在本教程中,我们将使用 JavaScript 和 Transformers 库来实现图像对象检测的功能。图像对象检测是计算机视觉领域中的重要任务,它可以识别图像中的不同对象并标注它们的位置。我们将使用一个预训练的对象检测模型,将其集成到网页中,通过上传图片来进行对象检测,并在图片上绘制边界框以标识检测到的对象。

一. 准备工作

首先,我们需要引入 Transformers 库,这是一个用于自然语言处理和计算机视觉任务的强大工具。我们将使用其中的对象检测模块来完成我们的任务。在代码中,我们通过 import {pipeline, env} from "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0"; 引入了所需的模块,pipeline和env模块来自于@xenova/transformers软件包的版本2.6.0。(注意:在导入pipeline和env模块时需要确保网络成功连接上了魔法)

二. HTML 结构

我们的 HTML 结构非常简单,只有一个文件上传 input 元素和一个用于显示图片和边界框的容器。文件上传 input 元素用于选择要检测的图片,而图片和边界框则会显示在 imageContainer 容器中,p标签将会显示交互信息提示用户图片读取状态。代码如下:

javascript 复制代码
<main class="container">
        <label for="file-upload" class="custom-file-upload">
            上传图片
            <input type="file"  accept="image/*" id="file-upload">
        </label>
        <!-- #image-container div 标签不需要加前缀-->
        <div id="image-container"></div>
        <!-- p#status -->
        <p id="status"></p>    
    </main>

三. JavaScript 实现

我们通过 JavaScript 实现了以下功能:

  • 当用户选择了要检测的图片后,我们使用 FileReader 对象读取图片文件,将图片解析成base64编码的字符串形式,并将该字符串赋值给img元素的src属性,这样读取到的文件就能显示在页面上。
  • 然后,我们调用 detect 函数,这个函数会启动 AI 任务,使用预训练的对象检测模型来检测图片中的对象。
  • detect 函数中,我们使用 pipeline 函数初始化了一个对象检测器,并传入了我们选择的模型 xenova/detr-resnet-50。其中,threshold 参数设置了对象检测的置信度阈值,低于该阈值的检测结果将被忽略;percentage 参数设置为 true 表示输出的边界框的坐标将以百分比形式返回。
  • 检测完成后,我们会得到一个包含边界框和标签的输出,然后通过 renderBox 函数将边界框绘制在图片上,并显示对象的标签。首先,它从传入的参数中获取边界框的坐标信息,并创建相应的 <div><span> 元素来表示边界框和标签。然后,它动态计算并设置边界框元素的样式,包括边框颜色、宽度、位置和尺寸等属性。最后,它将标签元素作为子元素添加到边界框元素中,并将边界框元素添加到页面上用于显示。
  • 代码如下:
js 复制代码
 <script type="module">
        // transformers nlp 任务
        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);
            imageContainer.appendChild(boxElement);
        }

四. 总结

通过本教程,我们学习了如何使用 JavaScript 和 Transformers 库来实现图像对象检测的功能。我们使用了一个预训练的对象检测模型,并将其集成到网页中,通过简单的上传图片操作就能实现对象检测,并在图片上标注检测到的对象。这个示例展示了如何利用现有的工具和库来快速实现复杂的计算机视觉任务,为开发者提供了一种简单而有效的方法来处理图像数据。

五.运行效果

六.完整代码

xml 复制代码
<!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.container>label.custom-file-upload>input#file-upload -->
    <main class="container">
        <label for="file-upload" class="custom-file-upload">
            上传图片
            <input type="file"  accept="image/*" id="file-upload">
        </label>
        <!-- #image-container div 标签不需要加前缀-->
        <div id="image-container"></div>
        <!-- p#status -->
        <p id="status"></p>    
    </main>

    <script type="module">
        // transformers nlp 任务
        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);
            imageContainer.appendChild(boxElement);
        }

    </script>
</body>
</html>
相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax