使用 Clarifai API for Node.js 创建并部署您自己的图像分类引擎





5.00/5 (4投票s)
本文的读者将了解到如何使用 Clarifai API for Node.js 来创建和部署一个轻量级的车辆图像分类 Web 应用程序。
注意:您可以通过访问以下链接来评估本文讨论的现成 Web 应用程序:http://ec2-18-225-37-56.us-east-2.compute.amazonaws.com/。
引言
本文的读者将了解到如何使用 Clarifai API for Node.js 来快速轻松地创建和部署一个简单的图像分类器,该分类器可以识别和分类来自多个类别的各种图像。作为 Clarifai API 的一个使用示例,我们将实现一个进行车辆图像分类的轻量级 Web 应用程序。具体来说,本文讨论的 Web 应用程序可用于对逻辑上分为“卡车”或“豪华轿车”两大类别的车辆进行分类。总而言之,本文的主要目的是提供具体的指导和操作流程,以帮助您开始构建自己的图像识别引擎,包括创建包含“有用”概念和图像语料库的一个或多个模型。这些模型可以用来训练 Clarifai 基于云的服务 AI,以识别我们的自定义视觉内容,并根据训练的模型进行预测和分类。具体来说,我们将通过高端 API 网关与 Clarifai 图像识别服务进行交互,以编程方式了解如何使用所有这些 Clarifai 基于云的解决方案功能。在本文中,我们还将介绍一种算法,该算法允许我们使用特定的 Clarifai 图像识别服务来实现图像分类引擎,从而提供高质量的预测和分类体验。
第一步:准备工作…
在创建和开发图像识别 Web 应用程序之前,至少需要完成两件事:要么创建 Clarifai 帐户,要么通过安装 Node.js 和 MySQL Server 开发工具来设置开发环境。
创建 Clarifai API 帐户
我们需要做的第一件事是注册 Clarifai API 图像和视频识别即服务,创建一个简单的应用程序,并获取正确的 Clarifai API 密钥值,以便在正在创建的 Node.js Web 应用程序中使用 https://api.clarifai.com/v2/ API 网关的端点。为此,我们必须访问 http://www.clarifai.com/ 网站,并使用用户名和电子邮件凭据创建一个常规的免费帐户。注册完成后,Clarifai 工作空间下会自动创建一个带有特定 API 密钥的第一个 Clarifai 应用程序。此时,我们可以自定义现有应用程序或创建具有新 API 密钥值的另一个应用程序。
为此,我们必须切换到工作区页面顶部的“创建应用程序”按钮,如下图所示。
之后,屏幕上将出现“创建应用程序”对话框。
在这里,我们必须输入应用程序的名称,然后单击“创建”按钮来创建一个新应用程序。
新 Clarifai 应用程序成功创建后,我们必须通过查看“应用程序详细信息”(如下图所示)来获取此应用程序的 API 密钥。
在应用程序的详细信息页面中,我们必须将应用程序的 Clarifai API 密钥值复制到剪贴板,并在我们正在创建的 Web 应用程序中使用它。
最后,完成上述步骤后,我们就可以自由使用我们刚刚创建的 Clarifai API 应用程序了。
安装 Node.js 和 MySQL Server
创建 Clarifai 帐户和特定的图像和视频处理应用程序后,我们必须通过安装 Node.js 和 MySQL Server 来正确设置开发环境。我们基本上需要 Node.js 来创建我们的图像分类 Web 应用程序。我们还需要安装 MySQL Server 来部署一个包含“有用”概念的图像语料库的数据库。请使用以下链接下载和安装 Node.js 和 MySQL Server。
- https://node.org.cn/dist/v10.16.0/node-v10.16.0-x64.msi
- https://dev.mysqlserver.cn/downloads/windows/installer/8.0.html
安装 Node.js 后,我们还必须安装 Clarifai 模块,以便能够在我们正在创建的 Web 应用程序中使用 Clarifai API。为此,我们必须使用 Node.js 包管理器 (NPM),在 Node.js 命令提示符中运行以下命令:
npm install --save clarifai
最后,要创建我们的第一个 Node.js Web 应用程序,我们必须全部安装 express.js 模块,并使用 express-generator 创建一个初始 Web 应用程序。
npm install --save express
npm install -g express-generator
要创建 Web 应用程序,我们必须创建一个空目录并进入该目录,然后运行以下命令:
express --ejs --view=ejs --force .
最后,既然我们已经设置了开发环境,我们现在就可以开始创建我们的图像分类 Web 应用程序了。
第二步:图像分类
图像分类是一个复杂的问题,其解决方案基本上依赖于执行图像识别。在这一段中,我们将讨论允许我们通过涉及 Clarifai AI 图像识别引擎来执行简单图像分类的算法。可以在 https://github.com/arthurratz/clarifai_api-demo 下载一个现成的 Web 应用程序,该应用程序执行车辆图像分类。该项目还包括可用于训练特定模型和根据用户提交的输入图像进行预测的图像数据集。
图像分类本身是一个过程,在此过程中,我们根据图像识别来确定输入图像属于特定类别的概率,然后执行简单的搜索来查找具有最高概率的类别,假设输入图像属于该特定类别。为了执行高质量的图像分类,我们通常需要实现图像识别过程,该过程基本上依赖于为每个特定类别创建和训练多个模型。具体来说,我们将分别为“卡车”和“豪华轿车”车辆类别创建单独的模型。每个类别都与车辆图像的语料库相关联。对于这些类别中的每一个,我们将执行完全相同的操作。我们将上传每个类别的图像,并创建和训练用于图像识别的特定模型。创建和训练好这些模型后,我们将遍历每个类别并执行预测,确定输入图像属于特定类别的概率。最后,我们将执行线性搜索来查找输入图像最有可能所属类别的概率。执行图像分类的结果主要是类别的名称以及输入图像属于该类别的特定概率值。
第三步:创建和训练模型
创建和训练模型是本文讨论的图像分类过程中非常重要的一步。具体到图像分类问题,在这种情况下,我们基本上处理的是创建和使用多个模型,每个模型代表一个正在分类的特定车辆类别。为此,我们将使用下一段中讨论的特定 Clarifai API 功能。
上传带有概念的图像
在创建和训练特定模型并使用它们进行图像分类之前,我们需要将带有“有用”概念的图像语料库上传到我们的 Clarifai 应用程序。通常,我们上传一组图像,并为每个特定车辆类别创建一个模型。这通常通过实现以下代码来完成:
router.post('/train', function(req, res, next) {
var params = JSON.parse(
require('fs').readFileSync('mysql.json'));
var con_sql = mysql.createConnection(params);
con_sql.connect((err) => {
if (err) throw err;
let query_classes = "SELECT class_id, class_name \
FROM clrfai_imagebase.classes";
con_sql.query(query_classes, (err, classes) => {
if (err) throw err;
classes.forEach(async (class_row, index) => {
let class_id = class_row["class_id"],
class_name = class_row["class_name"];
let query_images = "SELECT * FROM clrfai_imagebase.images \
WHERE class_id = \'" + class_id + "\'";
await con_sql.query(query_images, async (err, images) => {
if (err) throw err;
var image_urls = images.map((image) => { return { url: image["image_url"],
concepts: [ { id: class_name, value: true } ] }; });
app.inputs.create(image_urls);
await app.models.create(
"vehicles_class" + (index + 1),
[
{ "id": class_name }
]
);
app.models.train("vehicles_class" + (index + 1));
});
});
});
});
});
在这段代码中,我们基本上是创建与图像数据库的连接,并执行一个查询来检索结果集中的类别。然后,对于每个特定类别,我们检索一个图像数组,并将数组中的每个“图像”与一个完全对应于特定“类别”的“概念”相关联。属于整个类别的数组中的每个图像都将具有相同的正面概念参数值。要上传从数据库检索的图像批次,我们必须调用 app.inputs.create(image_urls)
方法,该方法接受一个图像 URL 数组作为单个参数。以下数组是一个对象数组,其中每个对象包含一个图像 URL 和一个概念 ID。概念对象有两个参数:概念 ID 和一个指示该概念是正面还是负面的值。
创建模型
成功上传完属于当前类别的所有图像后,我们需要调用 app.models.create(...)
方法来创建一个特定模型。在此代码执行期间,将为每个特定类别及其关联的图像数组创建一个模型。要创建模型,我们需要将以下参数值传递给上述方法。此方法的第一个参数是要创建的模型名称。至于这个基于 string
的参数的值,下面的代码会生成一个唯一的模型名称,即 vehicles_class1, vehicles_class2, ...
。此方法的另一个参数是整个图像类别的概念 ID。在这种情况下,概念 ID 的值是实际类别名称的 string
值。
训练模型
最后,在我们创建了模型之后,我们还必须通过调用 app.models.train(...)
方法来启动模型训练过程,该方法接受之前生成的模型名称作为单个参数。正如我们已经讨论过的,我们通常需要对每个特定类别和一组图像执行以下过程。
第四步:预测
在我们创建和训练了特定模型之后,现在就可以使用它们来进行图像分类了。根据本文介绍的图像分类算法,我们将使用我们之前创建的每个模型来预测输入图像的概念。我们将实际上使用一个训练好的特定模型来确定输入图像属于特定类别的概率值。这通常通过实现以下代码来完成:
router.post('/predict', async function(req, res, next) {
var params = JSON.parse(
require('fs').readFileSync('mysql.json'));
var con_sql = mysql.createConnection(params);
await con_sql.connect((err) => {
if (err) throw err;
let query_classes = "SELECT * \
FROM clrfai_imagebase.classes";
Jimp.read(req.body["url"])
.then(async (image_buf) => {
await image_buf.grayscale().getBuffer(Jimp.AUTO, (err, data) => {
if (err) throw err;
con_sql.query(query_classes, async (err, classes) => {
if (err) throw err;
var predict_results = [];
for (let index = 0; index < classes.length; index++) {
var buf = Buffer.from(data).toString('base64');
await app.models.predict({ id: "vehicles_class" + (index + 1),
version: '' }, {'base64': buf}).then(
(response) => {
predict_results.push(response["outputs"][0]["data"]);
},
(err) => { console.log(err); }
);
}
var prob_max = Math.max.apply(Math,
predict_results.map((obj) => { return obj["concepts"][0]["value"]; }));
predict_results = predict_results.filter((result) =>
{ return result["concepts"][0]["value"] == prob_max; });
res.send(JSON.stringify({ "class": predict_results[0]["concepts"][0]["name"],
"prob": predict_results[0]["concepts"][0]["value"]}));
});
})
});
});
});
在我们确定了每个特定类别的概率后,然后我们必须找到输入图像所属概率值最高的类别。结果是找到的类别,即输入图像最有可能所属的类别。要为每个特定类别执行预测,我们必须调用以下方法 app.models.predict(...)
,该方法接受三个主要参数:一个基于 string
的模型标识符或 Clarifai 应用版本 ID,以及一个包含输入图像的 base64
缓冲区。执行上述方法后,我们将以 JSON 格式收到预测结果。然后,我们将需要提取包含当前输入图像的概念和概率值的 data 对象。由于我们基本上处理的是多个类别和模型,因此我们将获取每个特定类别的概念 ID 和概率值,并将它们附加到结果数组中。
在为数组中的每个特定类别预测了输入图像的概念后,我们必须执行以下代码来确定最高概率以及输入图像所属的实际类别,通过执行以下代码:
var prob_max = Math.max.apply(Math,
predict_results.map((obj) => { return obj["concepts"][0]["value"]; }));
predict_results = predict_results.filter((result) => \
{ return result["concepts"][0]["value"] == prob_max; });
上面的代码首先找到每个对象具有的最高概率值,然后从数组中过滤出具有最高概率值的对象。
结论
在探索和使用 Clarifai API 的过程中,我完全被它的能力所折服,图像和视频识别问题竟然可以如此简单地解决。整个图像识别和分类任务,包括 AI 图像识别引擎的训练,都可以通过执行几个 API 方法来完成。这正是我认为 Clarifai API 可以积极用于更复杂的任务,而不仅仅是图像分类的原因。
历史
- 2019 年 6 月 1 日:初始版本