Clarifai是一个提供图像和视频识别的API,它非常易于使用,并且实现起来非常有趣。 在本文中,我们将探索将图像从网上拖放到简单的Web应用程序中的过程,该应用程序将读取它们并告诉我们它认为它们是什么。
在本演示中,我们将使用Node.js作为服务器,以及一个相对基本的前端,该前端使用jQuery进行AJAX请求。 如果您不擅长使用Node.js,只要您可以轻松地运行npm install
以在命令行中引入模块和node app.js
来使Web应用程序正常运行,那应该没问题。 您不需要在其中进行太多自定义,并且可以通过运行现有代码来最终学到一两个东西!
编码
入门
首先,我们进入Clarifai主页,然后单击右上角的“立即注册”按钮:
使用您的电子邮件和详细信息进行注册:
我们要创建一个新的应用程序,因此我们通过单击左侧的“应用程序”菜单项转到应用程序屏幕。
Clarifai尚不允许我们创建应用程序,因为我们需要选择一个计划:
让我们选择一个计划,这样我们才能顺利进行。 对于我们的演示,免费计划应该绰绰有余。 如果需要,我们可以稍后升级:
现在,我们可以创建一个应用程序,为此,我们可以单击左侧的“应用程序”菜单项或“创建应用程序”链接:
点击“创建新应用”按钮:
我们给我们的新应用程序起一个名字(例如“ Image Recognizer”),保持默认模型不变并设置我们的语言(我们将其保留为英语,您可能希望使用其他语言!)。 要完成,请单击“创建应用程序”:
现在将出现我们的新应用程序详细信息。 我们要复制到安全位置的两个最重要的位是“客户端ID”和“客户端机密”,我们将需要它们来访问服务器上的Clarifai,接下来我们将对其进行设置。
设置我们的Node.js服务器
Clarifai有一个Node.js客户端,我们可以使用它与GitHub上的服务接口。 将存储库下载到您的计算机。 特别是,我们需要clarifai_node.js文件。
为您的Node服务器创建目录,然后将`clarifai_node.js` JavaScript文件添加到根目录中。
我们的Node.js服务器功能将位于一个名为app.js
的JavaScript文件中。 在这里,我们将管理Clarifai支持的图像识别请求。 app.js
具有以下JavaScript:
var Clarifai = require("./clarifai_node.js"),
express = require("express"),
app = express(),
server = require("http").Server(app),
bodyParser = require("body-parser"),
port = process.env.PORT || 5000;
app.use(bodyParser.json());
Clarifai.initAPI("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");
function identifyClarifaiError(err) {
// Default error function from Clarifai we won't go into but you can find it in the GitHub download of this code!
}
app.post("/examineImage", function(req, resp) {
var imageURL = req.body.imageRequested;
console.log("Response was ", imageURL);
Clarifai.tagURL(imageURL, "Image from browser", commonResultHandler);
function commonResultHandler(err, res) {
if (err != null) {
identifyClarifaiError(err);
}
else {
if (typeof res["status_code"] === "string" &&
(res["status_code"] === "OK" || res["status_code"] === "PARTIAL_ERROR")) {
if (res["results"][0]["status_code"] === "OK") {
var tags = res["results"][0].result["tag"]["classes"];
console.log("Tags found were: ", tags);
resp.send(tags);
}
else {
console.log("We had an error... Details: " +
" docid=" + res.results[0].docid +
" local_id=" + res.results[0].local_id +
" status_code="+res.results[0].status_code +
" error = " + res.results[0]["result"]["error"]);
resp.send("Error: " + res.results[0]["result"]["error"]);
}
}
}
}
});
app.get("/", function(request, response) {
response.sendFile(__dirname + "/public/index.html");
});
app.get(/^(.+)$/, function(req, res) {
res.sendFile(__dirname + "/public/" + req.params[0]);
});
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send("Something broke!");
});
server.listen(port, function() {
console.log("Listening on " + port);
});
大部分代码是基本的Node express服务器功能,我们将在本文中介绍,如果您不太确定这些部分是否意味着您可以保留它们,而只是享受运行中的Node服务器。
与Clarifai特别相关的位从包含clarifai_node.js
文件的代码行开始:
var Clarifai = require("./clarifai_node.js"),
使用Clarifai的下一行开始API的初始化。 它使我们能够使用客户端ID和客户端机密访问API,这些客户端ID和客户端机密是我们先前在安全位置复制的。 将它们粘贴到适当的位置:
Clarifai.initAPI("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET");
然后,我们有一个POST请求,Node服务器将寻找并响应该请求。 通过/examineImage
访问时,此请求期望在我们的POST正文中收到一个名为imageRequested
的图像的Web URL。 它将找到的URL记录到控制台中:
app.post("/examineImage", function(req, resp) {
var imageURL = req.body.imageRequested;
console.log("Response was ", imageURL);
然后,我们从Clarifai Node API Client运行一个名为tagURL()
的函数。 此函数采用三个参数-我们希望Clarifai检查的图像URL,我们为图像指定的名称(如果需要,您可以更改此名称并从URL改编它,但为了简单起见,我们将其保留为通用名称的名称)和运行后的回调函数:
Clarifai.tagURL(imageURL, "Image from browser", commonResultHandler);
在commonResultHandler()
,我们对Clarifai返回给我们的内容做出反应。 如果返回错误,则将其传递给identifyClarifaiError()
函数, identifyClarifaiError()
函数可以保留原样(您可以在上面的GitHub下载中找到该函数)。 它包含一系列检查来自Clarifai的状态代码的方法。 就我们在此基本演示中的目的而言,我们不会涵盖它的所有功能,因为您不需要调整它。
function commonResultHandler(err, res) {
if (err != null) {
identifyClarifaiError(err);
}
// Continues further
如果没有返回明确的错误,请再次检查Clarifai的返回数据在res["status_code"]
是否也没有错误状态:
else {
if (typeof res["status_code"] === "string" &&
(res["status_code"] === "OK" || res["status_code"] === "PARTIAL_ERROR")) {
Clarifai在res["results"]
返回一个结果数组-每个给定的图像都返回一个。 因为我们只提供一个图像,所以我们只需要检索该数组中的第一项。 每个项目将具有该图像具有的JSON数据对象。 返回的JSON如下所示:
{
"docid": 6770681588539017000,
"url": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQSoU65AMIOpJ2rwtvdJyuSExIjcwQfuIup8sm6tesdWwtCEajzVw",
"status_code": "OK",
"status_msg": "OK",
"local_id": "Image from browser",
"result": {
"tag": {
"concept_ids": [
"ai_l8TKp2h5",
"ai_VPmHr5bm"
],
"classes": [
"people",
"adult"
],
"probs": [
0.9833399057388306,
0.9695020318031311
]
}
},
"docid_str": "c009c46cf0c7b68b5df64b083c2547b4"
}
我们要使用的最重要的位在result
对象内。 它包含三个数组,一个列出了已找到元素的Clarifai概念ID,一个列出了它们的“类”(每个概念的人类可读名称),一个列出了每个元素正确的可能性。 这些命令的顺序与每个对象的标签匹配,因此在上面的示例中, "ai_l8TKp2h5"
的概念ID被称为"people"
,Clarifai大约有0.9833399057388306
可以确定此图中有人。
使用这些数据,我们可以列出这些类以显示Clarifai发现的内容。 在下面的代码中,我们检查结果中的状态代码是否为"OK"
,然后发送标签数组作为对前端AJAX请求的响应。
if (res["results"][0]["status_code"] === "OK") {
var tags = res["results"][0].result["tag"]["classes"];
console.log("Tags found were: ", tags);
resp.send(tags);
}
否则,如果状态代码不是"OK"
,我们将记录错误的详细信息,然后将其发送回我们的Web应用程序:
else {
console.log("We had an error... Details: " +
" docid=" + res.results[0].docid +
" local_id=" + res.results[0].local_id +
" status_code="+res.results[0].status_code +
" error = " + res.results[0]["result"]["error"]);
resp.send("Error: " + res.results[0]["result"]["error"]);
}
我们的前端JavaScript
您可以根据自己的喜好来制作许多前端。 在我们的示例中,前端将是一个相对简单的前端,它允许将图像从网络上的其他位置拖到应用程序上。 我们读取它的URL,将其发送到上方的Node服务器,然后等待要显示的标签列表。
我们完整的前端JavaScript文件如下所示:
var baseUrl = window.location.origin,
dropArea = document.getElementById("dropArea");
dropArea.addEventListener("drop", imageDropped, false);
function imageDropped(evt) {
evt.stopPropagation();
evt.preventDefault();
var imageHTML = evt.dataTransfer.getData("text/html"),
dataParent = $("<div>").append(imageHTML),
imageRequested = $(dataParent).find("img").attr("src"),
$imageFound = $("#imageFound");
console.log(imageRequested);
$imageFound.attr("src", imageRequested);
$.ajax({
type: "POST",
url: baseUrl + "/examineImage",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({"imageRequested": imageRequested}),
success: function(data) {
console.log(data);
var tags = "";
for (var i = 0; i The initial line of code reads in the URL we've got in the browser bar, as this is also the URL for our server:
[code language="js"]
var baseUrl = window.location.origin,
然后,我们告诉JavaScript密切#dropArea
元素,并添加一个事件侦听器,如果我们将某些东西放到它上,它将运行imageDropped()
:
dropArea = document.getElementById("dropArea");
dropArea.addEventListener("drop", imageDropped, false);
imageDropped()
首先防止了将文件拖到浏览器时会发生的常见行为(通常会将文件加载到您拖入的浏览器窗口中):
function imageDropped(evt) {
evt.stopPropagation();
evt.preventDefault();
一旦确定避免使用浏览器拖放的常规功能,就可以从事件的拖放数据中获取HTML。 数据通常应包含<img>
标记,但有时还带有其他标记,例如<meta>
标记和其他<div>
标记。 为了确保始终有一个父元素可以在其中查找,我们将获取的所有数据附加到<div>
。 然后我们在其中找到<img>
,读取其src
属性并将此值放入一个名为imageRequested
的变量中:
var imageHTML = evt.dataTransfer.getData("text/html"),
dataParent = $("<div>").append(imageHTML),
imageRequested = $(dataParent).find("img").attr("src")
HTML中有一个ID为#imageFound
的<img>
标记,然后我们将拖动的图像放入其中,以便我们可以直观地看到结果下方的图像。 我们还记录了图像的URL进行调试(如果您愿意,可以删除console.log
):
$imageFound = $("#imageFound");
console.log(imageRequested);
$imageFound.attr("src", imageRequested);
使用我们新获取的图像URL,我们已检索并存储到imageRequested
,将其以{"imageRequested": "http://www.somewebsite.com/yourimage.jpg"}
的格式发送到JSON对象内节点服务器的/examineImage
地址{"imageRequested": "http://www.somewebsite.com/yourimage.jpg"}
。 成功获取标签后(Clarifai将其称为类),我们将其更改为逗号分隔的字符串,并将该字符串放入HTML的#dropArea
元素中。 如果有错误,我们记录发生了错误。
$.ajax({
type: "POST",
url: baseUrl + "/examineImage",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({"imageRequested": imageRequested}),
success: function(data) {
console.log(data);
var tags = "";
for (var i = 0; i I won't cover the HTML in detail as it isn't too exciting and could definitely be optimized! It looks like so:
[code language="html"]
<!doctype html>
<html>
<head>
<title>Image recognition tester</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Lora" rel="stylesheet" type="text/css"/>
<style type="text/css">
#dropArea {
border: 1px solid #fff;
bottom: 10%;
color: #fff;
display: flex;
justify-content: center;
flex-direction: column;
font-family: "Lora", Arial, sans-serif;
font-size: 30px;
left: 10%;
position: absolute;
right: 10%;
text-align: center;
text-shadow: 0 0 10px rgba(0,0,0,0.5);
top: 10%;
}
#imageFound {
background-size: 100% cover;
background: none 0 0 no-repeat #000;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
</style>
</head>
<body>
<img src="" id="imageFound" />
<div id="dropArea" ondragover="return false;">Drop your image from the web into here!</div>
<script src="./main.js"></script>
</body>
</html>
行动中
如果我们在本地运行Node服务器,则可以通过localhost:5000
访问它,因此请使用node app.js
运行服务器并在Web浏览器中访问该页面。
在另一个窗口中访问另一个网站,然后将图像从该窗口拖到该窗口中:
当识别并识别出图像后,它会按照其认为图像包含的可能性从最大到最小的顺序告诉我们标签列表:
结论
Clarifai具有图像识别功能的巨大潜力。 可以将该服务的API添加到一系列AI应用程序中,以使我们的AI对周围的世界有很好的视觉理解。 例如,我们可以将此功能添加到Siri风格的个人助理中,就像我们在如何使用Api.ai构建您自己的AI Assistant和使用Intent和Context定制Api.ai Assistant文章中构建的 那样 。 您可以将其添加到Nodebot或任何其他启用Web的应用程序。 Clarifai的服务还可以进行视频识别,带来全新的潜力!
您打算在哪里计划使用Clarifai的图像识别功能? 我很想知道这个API在哪里使用! 在下面的评论中让我知道,或者在Twitter上通过@thatpatrickguy与我联系 。
From: https://www.sitepoint.com/how-to-make-your-web-app-smarter-with-image-recognition/