最近我在学习如何在前端实现图片识别功能,这可真是个超有意思的领域!现在 AI 发展得太快了,很多前沿的 AI 模型都提供了强大的图片识别能力,通过在前端调用这些模型的 API,我们就能轻松实现原本复杂的图片识别任务。今天就来跟大家分享一下,我是如何使用 React 框架调用暗之月面模型来识别图片的,过程中还能学到不少前端开发的实用知识,就算是前端新手也能轻松跟上。
构建基础应用
我们都知道,React 是当下超火的前端 JavaScript 库,它采用组件化的开发模式,能让我们高效地构建用户界面。在这个图片识别项目里,我们第一步就是要搭建一个 React 应用的基础框架。
在开始之前,确保你已经安装好了 Node.js 和 npm(Node Package Manager),它们可是我们开发的好帮手。打开命令行工具,输入以下命令创建一个新的 React 项目:
npm init vite
输入项目名:moonshot-img,依次选择React和JavsScript
这个命令会自动帮我们创建一个名为moonshot-img的 React 项目,并且安装好所有必要的依赖包。等安装完成后,进入项目目录:
cd moonshot-img
然后启动项目:
npm i
npm run dev
这时,你的浏览器会自动打开,展示一个默认的 React 应用页面。接下来,我们就可以对这个应用进行改造,让它实现图片识别的功能啦。
编写React Hook
在 React 中,Hook 是一项非常强大的特性,它能让我们在函数组件中使用状态(state)和其他 React 特性。在我们的图片识别应用里,就用到了useState这个 Hook。
useState主要用来创建一个状态,也就是响应式的数据状态。简单来说,它能让我们在组件中定义一个可变的数据,并且当这个数据发生变化时,React 会自动帮我们更新相关的 UI。
图片识别应用需要处理三个关键数据:识别结果文本、图片的 Base64 数据、以及图片有效性标记。因此在App.js文件中,我们可以这样使用useState:
import { useState } from 'react';
function App() {
const [content, setContent] = useState('');
const [imgBase64Data, setImgBase64Data] = useState('');
const [isValid, setIsValid] = useState(false);
}
这里我们创建了三个状态变量:
content用来存储图片识别后的结果内容,初始值为空字符串。imgBase64Data用于存储上传图片的 Base64 编码数据,一开始也是空字符串。isValid表示当前上传的图片是否有效,初始为false。
useState返回一个数组,数组的第一个元素是当前状态的值,第二个元素是一个函数,通过这个函数我们可以更新状态。比如,要更新content的值,我们就可以调用setContent函数。
获取并预览图片
接下来,我们要实现从本地选择图片并在页面上预览的功能。这涉及到 HTML5 的一些特性以及 JavaScript 与操作系统本地文件的交互。为什么要这么做?因为识别图片可能是一个时间很长的过程,最好提前预览一下,让用户知道正在识别的是哪张图片。
在App.js的return部分,添加以下代码:
return (
<div className='container'>
<div>
<label htmlFor="fileInput">文件</label>
<input type="file" id='fileInput' className='input' accept='.jpeg,.jpg,.png,.gif' onChange={updateBase64Data} />
</div>
<div className="output">
<div className="preview">
{
imgBase64Data && <img src={imgBase64Data} alt='' />
}
</div>
</div>
<div>
{content}
</div>
</div>
);
这里我们添加了一个文件输入框,type="file"表示这是一个文件选择器。accept='.jpeg,.jpg,.png,.gif'限定了只能选择这几种格式的图片文件。当用户选择文件后,会触发onChange事件,对应的处理函数是updateBase64Data。
然后在组件内部定义updateBase64Data函数:
const updateBase64Data = (e) => {
const file = e.target.files[0];
if (!file) {
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
setImgBase64Data(reader.result);
setIsValid(true);
};
};
在这个函数里,首先通过e.target.files[0]获取用户选择的文件。如果没有选择文件(!file),就直接返回。接着,创建一个FileReader对象,它专门用来读取文件内容。调用reader.readAsDataURL(file)方法,这个方法会将文件读取为 Base64 编码的数据。当读取完成后,会触发reader.onload事件,在这个事件处理函数中,我们将读取到的 Base64 数据通过setImgBase64Data更新到状态中,同时将isValid设为true,表示图片有效。这样,页面上就能根据imgBase64Data的值展示出图片预览了。
调用暗之月面 API
图片上传预览完成后,最重要的就是调用暗之月面的 API 来进行图片识别啦。这里我们会用到async/await进行异步编程。
在App.js中继续添加一个update函数:
const update = async () => {
if (!imgBase64Data) {
return;
}
const endpoint = 'https://api.moonshot.cn/v1/chat/completions';
const headers = {
'Content - Type': 'application/json',
'Authorization': `Bearer ${import.meta.env.VITE_API_KEY}`
};
setContent('正在生成中...');
const response = await fetch(endpoint, {
method: 'POST',
headers,
body: JSON.stringify({
model:'moonshot - v1 - 8k - vision - preview',
messages: [
{
role: 'user',
content: [
{
type: 'image_url',
image_url: {
"url": imgBase64Data
}
},
{
type: 'text',
text: '请描述图片的内容'
}
]
}
]
})
});
const data = await response.json();
setContent(data.choices[0].message.content);
};
这个函数一开始会检查imgBase64Data是否有值,如果没有,说明用户还没有上传有效的图片,就直接返回。然后定义了 API 的端点endpoint,以及请求头headers。这里的Authorization字段需要填入你的暗之月面 API 密钥,我们通过import.meta.env.VITE_API_KEY从环境变量中获取密钥。在实际项目中,你需要在.env文件中设置这个环境变量,比如VITE_API_KEY = your_api_key_here。
接着,我们通过setContent('正在生成中...')先给用户一个反馈,告诉他们图片识别正在进行中。然后使用fetch函数发起一个 POST 请求到暗之月面的 API。fetch是 JavaScript 中用于发起 HTTP 请求的原生方法,非常强大。在请求体中,我们指定了要使用的模型moonshot - v1 - 8k - vision - preview,并且构造了messages数组,其中包含了图片的 Base64 数据(通过image_url类型)以及要让模型执行的任务描述(请描述图片的内容)。
因为fetch返回的是一个 Promise 对象,所以我们使用await等待请求完成,获取到响应response。然后再使用await response.json()将响应内容解析为 JSON 格式的数据。最后,从解析后的数据中取出图片识别的结果,通过setContent更新到页面上展示给用户。
完整代码展示
最后,给大家展示一下完整的App.js代码:
import { useState } from'react';
import './App.css';
function App() {
const [content, setContent] = useState('');
const [imgBase64Data, setImgBase64Data] = useState('');
const [isValid, setIsValid] = useState(false);
const updateBase64Data = (e) => {
const file = e.target.files[0];
if (!file) {
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
setImgBase64Data(reader.result);
setIsValid(true);
};
};
const update = async () => {
if (!imgBase64Data) {
return;
}
const endpoint = 'https://api.moonshot.cn/v1/chat/completions';
const headers = {
'Content - Type': 'application/json',
'Authorization': `Bearer ${import.meta.env.VITE_API_KEY}`
};
setContent('正在生成中...');
const response = await fetch(endpoint, {
method: 'POST',
headers,
body: JSON.stringify({
model:'moonshot - v1 - 8k - vision - preview',
messages: [
{
role: 'user',
content: [
{
type: 'image_url',
image_url: {
"url": imgBase64Data
}
},
{
type: 'text',
text: '请描述图片的内容'
}
]
}
]
})
});
const data = await response.json();
setContent(data.choices[0].message.content);
};
return (
<div className='container'>
<div>
<label htmlFor="fileInput">文件</label>
<input type="file" id='fileInput' className='input' accept='.jpeg,.jpg,.png,.gif' onChange={updateBase64Data} />
</div>
<button onClick={update} disabled={!isValid}>提交</button>
<div className="output">
<div className="preview">
{
imgBase64Data && <img src={imgBase64Data} alt='' />
}
</div>
</div>
<div>
{content}
</div>
</div>
);
}
export default App;
在这段代码中,我们还添加了一个提交按钮,onClick事件绑定了update函数,并且通过disabled={!isValid}来控制按钮的禁用状态。当isValid为false(即用户还未上传有效图片)时,按钮是禁用的,避免用户误操作。
通过以上步骤,我们就成功地使用 React 实现了一个调用暗之月面模型进行图片识别的应用。在这个过程中,我们学习了 React 的 Hook(特别是useState)、HTML5 与本地文件交互、async/await异步编程以及如何调用第三方 API 等重要的前端知识。
希望这篇文章能帮助大家快速上手前端图片识别开发,也鼓励大家在这个基础上继续探索,比如优化界面设计、增加更多的图片处理功能等。让我们一起在前端开发的世界里不断进步,创造出更多有趣又实用的应用吧!