開發與維運

阿里雲圖像搜索Quick Start

作者:俏巴

概述

圖像搜索服務(Image Search)是以深度學習和大規模機器學習技術為核心,通過圖像識別和搜索功能,實現以圖搜圖的智能圖像搜索產品。圖像搜索服務在基於圖像識別技術基礎上,結合不同行業應用和業務場景,幫助用戶實現相同或相似圖片搜索。因為導入到實例的圖片實例本身並不存儲原始圖片,所以在使用查詢功能的時候,並不能直接返回原始圖片或者可以直接訪問的圖片URL,需要使用者根據查詢反饋的picname等信息自行到自己的圖庫中反查原始圖片,這樣給使用帶來了很大的不便。

針對這種情況,提供一種解決辦法,利用添加圖片時候支持的屬性:CustomContent,直接設置該值為添加圖片可以公網訪問的URL,這樣在查詢的時候就直接可以通過Response Auctions對象的CustomContent屬性獲取圖片的URL,當然前提是本身加入的圖片提供公網訪問URL。

操作步驟

1、到圖像搜索控制檯創建實例

_

2、獲取測試需要的相關參數

_

3、pom.xml

  <dependencies>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.aliyun<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>aliyun-java-sdk-imagesearch<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span></span>
    &lt;dependency&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.aliyun<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span></span>
        &lt;artifactId&gt;aliyun-java-sdk-core&lt;<span class="hljs-regexp">/artifactId&gt;
        &lt;version&gt;[4.3.2,5.0.0)&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;</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&amp;quality=80&amp;size=b9999_10000&amp;sec=1577090672111&amp;di=ecb316794a7d0eeb8dc9dd76d4ca78d0&amp;imgtype=0&amp;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&amp;quality=80&amp;size=b9999_10000&amp;sec=1577090672122&amp;di=539afa0415b469da9bb57daf94eff8e7&amp;imgtype=0&amp;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支持的操作符有&gt;、&gt;=、&lt;、&lt;=、=,str_attr支持的操作符有=和!=,多個條件之支持AND和OR進行連接。</span>
    <span class="hljs-comment">// 示例:</span>
    <span class="hljs-comment">//  1. 根據IntAttr過濾結果,int_attr&gt;=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
測試結束


更多參考


Java SDK
新增圖片 API
查詢圖片 API

Leave a Reply

Your email address will not be published. Required fields are marked *