前端与 AI 融合:图片识别技术的创新之旅
前言
在信息技术飞速发展的时代,前端开发和 AI 技术正以令人惊叹的速度融合在一起。而图片识别作为两者结合的一个重要应用领域,正逐渐改变着我们的生活和工作方式。 一个小白如何结合ai与前端技术紧跟时代潮流呢?
下面的代码会让很多同学难以接受、看不懂各种api。因此在这里我想让各位同学一定要转变思维,api是可以慢慢积累的,我们不妨先用起来,知道这是干什么的,勇于去接受它,这样我们才能以最快的速度进步。
接下来以做一个图片识别应用为引子,欢迎大家相互探讨。
想做的事情
图片检测,这里先附上最终的效果,然后再来谈如何实现。
点击上传图片,我们选中任意一张图片,通过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);
}
- 详细说明都在注释
效果
完整代码
<!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