前言
在当今科技飞速发展的时代,JavaScript(JS)作为广泛应用的编程语言,展现出了强大的活力与无限的可能性。与此同时,自然语言处理(NLP)领域也正在经历着深刻的变革与进步。
当这两者碰撞在一起时,一个全新的领域就此打开——图片分析。
实现
效果展示
通过点击上传图片按钮上传图片后,通过AI帮助我们对图像进行识别
实现过程
页面
<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>
<main class="container">
: 这是一个<main>
元素,表示页面的主要内容区域<label for="file-upload" class="custom-file-upload">
: 这是一个<label>
元素,它与file-upload
输入框关联<input type="file" accept="image/*" id="file-upload">
: 这是一个<input>
元素,类型为file
。accept="image/*"
属性表示只允许上传图片文件。id="file-upload"
属性用于与<label>
元素关联<div id="image-container"></div>
: 这是一个空的<div>
元素,其id
为image-container
。用于显示上传的图片预览
js代码
// transformers库导入pipeline模块 npl 任务
import { pipeline, env } from "https://cdn.jsdelivr.net/npm/@xenova/transformers@2.6.0"
首先从导入transformers库导入pipeline模块和env
- transformers 是一个由 Hugging Face 开发的开源 Python 库,用于快速开发和部署最先进的自然语言处理(NLP)模型,为 NLP 开发者提供了一个强大、灵活和易用的工具集。无论是进行基础的文本分类还是构建复杂的对话系统,transformers 都可以成为开发者的首选。
// 设置当前的环境对象 不要加载本地模型,使用远程加载 transformers库
env.allowLocalModels = false;
设置当前的环境对象 不要加载本地模型,使用远程加载 transformers库
// 通过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)
})
-
获取 HTML 元素:
const fileUpload = document.getElementById('file-upload');
: 通过 ID 获取文件上传的 input 元素。const imageContainer = document.getElementById('image-container');
: 通过 ID 获取用于显示图片的容器 div。
-
添加事件监听器:
fileUpload.addEventListener('change', function (e) { ... });
: 给文件上传 input 添加 ‘change’ 事件监听器,当用户选择文件时触发。
-
处理上传文件:
const file = e.target.files[0];
:获取用户选择的第一个文件。const reader = new FileReader();
: 创建一个 FileReader 对象,用于读取文件内容。reader.onload = function (e2) { ... };
: 当文件读取完成时,触发 ‘onload’ 回调函数。const image = document.createElement('img');
: 创建一个新的 img 元素用于显示图片。image.src = e2.target.result;
: 将读取到的文件内容设置为 img 元素的 src 属性,显示图片。imageContainer.appendChild(image);
: 将 img 元素添加到图片容器 div 中,完成图片预览。
-
触发 AI 检测:
detect(image);
: 在图片加载完成后,调用一个名为detect
的函数来执行 AI 检测任务。这个函数没有在代码中定义,需要在其他地方实现。
其中将detect单独模块化,体现了封装的思想
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(rendesrBox)
}
上述代码
const detector = await pipeline("object-detection", "Xenova/detr-resnet-50");
: 使用 Hugging Face 的pipeline
函数加载预训练的对象检测模型。这里选择了 “Xenova/detr-resnet-50” 模型,它适用于对象检测任务。const output = await detector(image.src, { threshold: 0.1, percentage: true });
: 使用加载的对象检测模型对图像进行分析,返回检测结果。这里设置了置信度阈值为 0.1,并将结果以百分比的形式返回。output.forEach(renderBox);
: 遍历检测结果,对每个检测到的对象调用一个名为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);
}
对于每个检测到的对象,都会在图像容器中渲染一个带有标签的边界框,以可视化地显示检测结果
完整js代码
<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(rendesrBox)
}
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>
总结
AI 技术的发展带来了很多新的可能性,前端技术结合AI将有更广阔的未来