作者:俏巴
概述
图像搜索服务(Image Search)是以深度学习和大规模机器学习技术为核心,通过图像识别和搜索功能,实现以图搜图的智能图像搜索产品。图像搜索服务在基于图像识别技术基础上,结合不同行业应用和业务场景,帮助用户实现相同或相似图片搜索。因为导入到实例的图片实例本身并不存储原始图片,所以在使用查询功能的时候,并不能直接返回原始图片或者可以直接访问的图片URL,需要使用者根据查询反馈的picname等信息自行到自己的图库中反查原始图片,这样给使用带来了很大的不便。
针对这种情况,提供一种解决办法,利用添加图片时候支持的属性:CustomContent,直接设置该值为添加图片可以公网访问的URL,这样在查询的时候就直接可以通过Response Auctions对象的CustomContent属性获取图片的URL,当然前提是本身加入的图片提供公网访问URL。
操作步骤
1、到图像搜索控制台创建实例
2、获取测试需要的相关参数
3、pom.xml
<dependencies>
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>com.aliyun<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>aliyun-java-sdk-imagesearch<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">version</span>></span>2.0.0<span class="hljs-tag"></<span class="hljs-name">version</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span></span>
<dependency>
<span class="xml"><span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>com.aliyun<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span></span>
<artifactId>aliyun-java-sdk-core<<span class="hljs-regexp">/artifactId>
<version>[4.3.2,5.0.0)</version>
</dependency>
</dependencies></span></code></pre>
4、Code Sample
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.imagesearch.model.v20190325.AddImageRequest;
import com.aliyuncs.imagesearch.model.v20190325.AddImageResponse;
import com.aliyuncs.imagesearch.model.v20190325.SearchImageRequest;
import com.aliyuncs.imagesearch.model.v20190325.SearchImageResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.apache.commons.codec.binary.Base64;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class AddAndSearchDemo {
public <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> main(<span class="hljs-built_in">String</span>[] args) throws IOException, InterruptedException {
<span class="hljs-built_in">String</span> accessKeyId = <span class="hljs-string">"LTAIOZZgYX******"</span>;
<span class="hljs-built_in">String</span> accessSecret = <span class="hljs-string">"v7CjUJCMk7j9aKduMAQLjyCm******"</span>;
<span class="hljs-built_in">String</span> regionId = <span class="hljs-string">"cn-shanghai"</span>;
<span class="hljs-built_in">String</span> instanceName = <span class="hljs-string">"demop******"</span>;
<span class="hljs-built_in">String</span> productId = <span class="hljs-string">"shirt"</span>;
<span class="hljs-built_in">String</span> picName1 = <span class="hljs-string">"shirt_1"</span>;
<span class="hljs-built_in">String</span> picName2 = <span class="hljs-string">"shirt_2"</span>;
<span class="hljs-built_in">String</span> picURL1 = <span class="hljs-string">"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1577090672111&di=ecb316794a7d0eeb8dc9dd76d4ca78d0&imgtype=0&src=http%3A%2F%2Fimg12.360buyimg.com%2Fn0%2Fjfs%2Ft208%2F202%2F990939258%2F101503%2Fe8b76d70%2F53a13d75N1456d2d6.jpg"</span>;
<span class="hljs-built_in">String</span> picURL2 = <span class="hljs-string">"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1577090672122&di=539afa0415b469da9bb57daf94eff8e7&imgtype=0&src=http%3A%2F%2Fimg12.360buyimg.com%2Fn1%2Fjfs%2Ft877%2F18%2F399371448%2F100857%2Fd906afbb%2F551d5285Nd29ae9aa.jpg"</span>;
<span class="hljs-built_in">String</span> picPath = <span class="hljs-string">"C:\\******\\main\\resources\\test.jpg"</span>; <span class="hljs-comment">// 待查询图片的路径</span>
DefaultProfile.addEndpoint( regionId, <span class="hljs-string">"ImageSearch"</span>, <span class="hljs-string">"imagesearch.cn-shanghai.aliyuncs.com"</span>);
IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessSecret);
IAcsClient client = <span class="hljs-keyword">new</span> DefaultAcsClient(profile);
<span class="hljs-comment">// 添加图片到实例</span>
addPic(client,instanceName,productId,picName1,picURL1);
Thread.sleep(<span class="hljs-number">1000</span>);<span class="hljs-comment">// 防止出现flow control</span>
addPic(client,instanceName,productId,picName2,picURL2);
<span class="hljs-comment">// 查询图片</span>
searchPic(client, instanceName, picPath);
System.out.println(<span class="hljs-string">"测试结束"</span>);
}
<span class="hljs-comment">/**
* 添加图片到实例
* @param client 实例对象
* @param instanceName 实例名称
* @param productId 商品Id
* @param picName 图片名称
* @param picURL 图片URL
* @throws IOException
*/</span>
public <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> addPic(IAcsClient client, <span class="hljs-built_in">String</span> instanceName, <span class="hljs-built_in">String</span> productId, <span class="hljs-built_in">String</span> picName, <span class="hljs-built_in">String</span> picURL) throws IOException {
<span class="hljs-comment">// 增加图片</span>
AddImageRequest addImageRequest = <span class="hljs-keyword">new</span> AddImageRequest();
<span class="hljs-comment">// 必填,图像搜索实例名称。</span>
addImageRequest.setInstanceName(instanceName);
<span class="hljs-comment">// 必填,商品id,最多支持 512个字符。</span>
<span class="hljs-comment">// 一个商品可有多张图片。</span>
addImageRequest.setProductId(productId);
<span class="hljs-comment">// 必填,图片名称,最多支持 512个字符。</span>
<span class="hljs-comment">// 1. ProductId + PicName唯一确定一张图片。</span>
<span class="hljs-comment">// 2. 如果多次添加图片具有相同的ProductId + PicName,以最后一次添加为准,前面添加的的图片将被覆盖。</span>
addImageRequest.setPicName(picName);
<span class="hljs-comment">// request.setStrAttr("");// 测试</span>
<span class="hljs-comment">// 选填,图片类目。</span>
<span class="hljs-comment">// 1. 对于商品搜索:若设置类目,则以设置的为准;若不设置类目,将由系统进行类目预测,预测的类目结果可在Response中获取 。</span>
<span class="hljs-comment">// 2. 对于布料、商标、通用搜索:不论是否设置类目,系统会将类目设置为88888888。</span>
addImageRequest.setCategoryId(<span class="hljs-number">1</span>);
Base64 base64 = <span class="hljs-keyword">new</span> Base64();
<span class="hljs-built_in">String</span> encodePicContent = base64.encodeToString(getFileFromUrl(picURL));
<span class="hljs-comment">// 必填,图片内容,Base64编码。</span>
<span class="hljs-comment">// 最多支持 2MB大小图片以及5s的传输等待时间。当前仅支持jpg和png格式图片;</span>
<span class="hljs-comment">// 对于商品、商标、通用图片搜索,图片长和宽的像素必须都大于等于200,并且小于等于1024;</span>
<span class="hljs-comment">// 对于布料搜索,图片长和宽的像素必须都大于等于448,并且小于等于1024;</span>
<span class="hljs-comment">// 图像中不能带有旋转信息。</span>
addImageRequest.setPicContent(encodePicContent);
<span class="hljs-comment">// 选填,是否需要进行主体识别,默认为true。</span>
<span class="hljs-comment">// 1.为true时,由系统进行主体识别,以识别的主体进行搜索,主体识别结果可在Response中获取。</span>
<span class="hljs-comment">// 2. 为false时,则不进行主体识别,以整张图进行搜索。</span>
<span class="hljs-comment">// 3.对于布料图片搜索,此参数会被忽略,系统会以整张图进行搜索。</span>
addImageRequest.setCrop(<span class="hljs-literal">true</span>);
<span class="hljs-comment">// 选填,图片的主体区域,格式为 x1,x2,y1,y2, 其中 x1,y1 是左上角的点,x2,y2是右下角的点。</span>
<span class="hljs-comment">// 若用户设置了Region,则不论Crop参数为何值,都将以用户输入Region进行搜索。</span>
<span class="hljs-comment">// 对于布料图片搜索,此参数会被忽略,系统会以整张图进行搜索。</span>
// request.setRegion("280,486,232,351");
<span class="hljs-comment">// 选填,整数类型属性,可用于查询时过滤,查询时会返回该字段。</span>
<span class="hljs-comment">// 例如不同的站点的图片/不同用户的图片,可以设置不同的IntAttr,查询时通过过滤来达到隔离的目的</span>
addImageRequest.setIntAttr(<span class="hljs-number">0</span>);
<span class="hljs-comment">// 选填,字符串类型属性,最多支持 128个字符。可用于查询时过滤,查询时会返回该字段。</span>
addImageRequest.setStrAttr(<span class="hljs-string">"demo"</span>);
<span class="hljs-comment">// 选填,用户自定义的内容,最多支持 4096个字符。</span>
<span class="hljs-comment">// 查询时会返回该字段。例如可添加图片的描述等文本。</span>
<span class="hljs-comment">// 这里设置为图片的公网地址URL,方便从查询结果中直接获取数据</span>
addImageRequest.setCustomContent(picURL);
<span class="hljs-keyword">try</span> {
AddImageResponse addImageResponse = client.getAcsResponse(addImageRequest);
System.out.println(<span class="hljs-string">"Add Picture Result: "</span> + addImageResponse.getSuccess());
} <span class="hljs-keyword">catch</span> (ClientException e) {
<span class="hljs-comment">// 抛出异常,例如参数无效,或者实例不可用等情况</span>
e.printStackTrace();
}
}
<span class="hljs-comment">/**
* 使用本地图片到图片库中查询
* @param client 实例对象
* @param instanceName 实例名称
* @param picPath 本地图片的路径
*/</span>
public <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> searchPic(IAcsClient client, <span class="hljs-built_in">String</span> instanceName, <span class="hljs-built_in">String</span> picPath)
{
SearchImageRequest searchImageRequest = <span class="hljs-keyword">new</span> SearchImageRequest();
<span class="hljs-comment">// 必填,图像搜索实例名称。</span>
searchImageRequest.setInstanceName(instanceName);
<span class="hljs-comment">// 选填,搜索类型,取值范围:</span>
<span class="hljs-comment">// 1. SearchByPic(默认):根据图片搜索相似图片。</span>
<span class="hljs-comment">// 2. SearchByName,根据已添加的图片搜索相似图片。</span>
<span class="hljs-comment">// request.setType("SearchByPic");</span>
byte[] bytes2_search = getBytesFromPath(picPath);
Base64 base64 = <span class="hljs-keyword">new</span> Base64();
<span class="hljs-built_in">String</span> encodePicContent_seacrch = base64.encodeToString(bytes2_search);
<span class="hljs-comment">// 图片内容,Base64编码。最多支持 2MB大小图片以及5s的传输等待时间。当前仅支持jpg和png格式图片;</span>
<span class="hljs-comment">// 对于商品、商标、通用图片搜索,图片长和宽的像素必须都大于等于200,并且小于等于1024;</span>
<span class="hljs-comment">// 对于布料搜索,图片长和宽的像素必须都大于等于448,并且小于等于1024;</span>
<span class="hljs-comment">// 图像中不能带有旋转信息。</span>
<span class="hljs-comment">// 1. Type=SearchByPic时,必填</span>
<span class="hljs-comment">// 2. Type=SearchByName时,无需填写。</span>
searchImageRequest.setPicContent(encodePicContent_seacrch);
<span class="hljs-comment">// 选填,商品类目。</span>
<span class="hljs-comment">// 1. 对于商品搜索:若设置类目,则以设置的为准;若不设置类目,将由系统进行类目预测,预测的类目结果可在Response中获取 。</span>
<span class="hljs-comment">// 2. 对于布料、商标、通用搜索:不论是否设置类目,系统会将类目设置为88888888。</span>
searchImageRequest.setCategoryId(<span class="hljs-number">1</span>);
<span class="hljs-comment">// 选填,是否需要进行主体识别,默认为true。</span>
<span class="hljs-comment">// 1.为true时,由系统进行主体识别,以识别的主体进行搜索,主体识别结果可在Response中获取。</span>
<span class="hljs-comment">// 2. 为false时,则不进行主体识别,以整张图进行搜索。</span>
<span class="hljs-comment">// 3.对于布料图片搜索,此参数会被忽略,系统会以整张图进行搜索。</span>
searchImageRequest.setCrop(<span class="hljs-literal">false</span>);
<span class="hljs-comment">// 选填,图片的主体区域,格式为 x1,x2,y1,y2, 其中 x1,y1 是左上角的点,x2,y2是右下角的点。</span>
<span class="hljs-comment">// 若用户设置了Region,则不论Crop参数为何值,都将以用户输入Region进行搜索。</span>
<span class="hljs-comment">// 3.对于布料图片搜索,此参数会被忽略,系统会以整张图进行搜索。</span>
<span class="hljs-comment">// searchImageRequest.setRegion("280,486,232,351");</span>
<span class="hljs-comment">// 选填,返回结果的数目。取值范围:1-100。默认值:10。</span>
searchImageRequest.setNum(<span class="hljs-number">2</span>);
<span class="hljs-comment">// 选填,返回结果的起始位置。取值范围:0-499。默认值:0。</span>
<span class="hljs-comment">// searchImageRequest.setStart(1);</span>
<span class="hljs-comment">// 选填,过滤条件</span>
<span class="hljs-comment">// int_attr支持的操作符有>、>=、<、<=、=,str_attr支持的操作符有=和!=,多个条件之支持AND和OR进行连接。</span>
<span class="hljs-comment">// 示例:</span>
<span class="hljs-comment">// 1. 根据IntAttr过滤结果,int_attr>=100</span>
<span class="hljs-comment">// 2. 根据StrAttr过滤结果,str_attr!="value1"</span>
<span class="hljs-comment">// 3. 根据IntAttr和StrAttr联合过滤结果,int_attr=1000 AND str_attr="value1"</span>
<span class="hljs-comment">// searchImageRequest.setFilter("int_attr=1");</span>
<span class="hljs-keyword">try</span> {
SearchImageResponse searchImageResponse = client.getAcsResponse(searchImageRequest);
System.out.println(<span class="hljs-string">"getCustomContent: "</span> + searchImageResponse.getAuctions().get(<span class="hljs-number">0</span>).getCustomContent());
System.out.println(<span class="hljs-string">"getCustomContent: "</span> + searchImageResponse.getAuctions().get(<span class="hljs-number">1</span>).getCustomContent());
} <span class="hljs-keyword">catch</span> (ClientException e) {
e.printStackTrace();
}
}
<span class="hljs-comment">/**
* 通过oss 中的URL的读取图片到Byte[]
* @param url 公网可以访问的图片URL
* @return byte[]
* @throws IOException
*/</span>
private <span class="hljs-keyword">static</span> byte[] getFileFromUrl(<span class="hljs-built_in">String</span> url) throws IOException{
URL urlConet = <span class="hljs-keyword">new</span> URL(url);
HttpURLConnection con = (HttpURLConnection)urlConet.openConnection();
con.setRequestMethod(<span class="hljs-string">"GET"</span>);
con.setConnectTimeout(<span class="hljs-number">4</span> * <span class="hljs-number">1000</span>);
InputStream inStream = con .getInputStream();<span class="hljs-comment">//通过输入流获取图片数据</span>
ByteArrayOutputStream outStream = <span class="hljs-keyword">new</span> ByteArrayOutputStream();
byte[] buffer = <span class="hljs-keyword">new</span> byte[<span class="hljs-number">2048</span>];
int len = <span class="hljs-number">0</span>;
<span class="hljs-keyword">while</span>( (len=inStream.read(buffer)) != <span class="hljs-number">-1</span> ){
outStream.write(buffer, <span class="hljs-number">0</span>, len);
}
inStream.close();
byte[] data = outStream.toByteArray();
<span class="hljs-keyword">return</span> data;
}
<span class="hljs-comment">/**
* 从本地读取图片到byte[]
* @param filePath 本地图片的路径
* @return byte[]
*/</span>
private <span class="hljs-keyword">static</span> byte[] getBytesFromPath(<span class="hljs-built_in">String</span> filePath) {
byte[] buffer = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">try</span> {
File file = <span class="hljs-keyword">new</span> File(filePath);
FileInputStream fis = <span class="hljs-keyword">new</span> FileInputStream(file);
<span class="hljs-comment">// picture max size is 2MB</span>
ByteArrayOutputStream bos = <span class="hljs-keyword">new</span> ByteArrayOutputStream(<span class="hljs-number">2000</span> * <span class="hljs-number">1024</span>);
byte[] b = <span class="hljs-keyword">new</span> byte[<span class="hljs-number">1000</span>];
int n;
<span class="hljs-keyword">while</span> ((n = fis.read(b)) != <span class="hljs-number">-1</span>) {
bos.write(b, <span class="hljs-number">0</span>, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
} <span class="hljs-keyword">catch</span> (FileNotFoundException e) {
e.printStackTrace();
} <span class="hljs-keyword">catch</span> (IOException e) {
e.printStackTrace();
}
<span class="hljs-keyword">return</span> buffer;
}
}
备注:待查询图片下载地址。
5、测试结果
Add Picture Result: true
Add Picture Result: true
getCustomContent: https: class="hljs-comment">//timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1577090672111&di=ecb316794a7d0eeb8dc9dd76d4ca78d0&imgtype=0&src=http%3A%2F%2Fimg12.360buyimg.com%2Fn0%2Fjfs%2Ft208%2F202%2F990939258%2F101503%2Fe8b76d70%2F53a13d75N1456d2d6.jpg
getCustomContent: https: class="hljs-comment">//timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1577090672122&di=539afa0415b469da9bb57daf94eff8e7&imgtype=0&src=http%3A%2F%2Fimg12.360buyimg.com%2Fn1%2Fjfs%2Ft877%2F18%2F399371448%2F100857%2Fd906afbb%2F551d5285Nd29ae9aa.jpg
测试结束
更多参考