elevne's Study Note
GCP Vision, Knowledge Graph Search API 본문
Google Cloud Platform의 Vision API를 이용하여 이미지검색 서비스를 구현하려 하였다.

index.html
<form method="post" action="fileupload.jsp" enctype="multipart/form-data">
<input type="file" name="photo" />
<input type="submit" value="upload" />
</form>
위와 같이 이미지 데이터를 Input으로 받고 fileupload.jsp로 넘겨서 이미지검색을 시작한다.
fileupload.jsp 파일로 넘어가기 전 필요한 기능들을 java 파일로 구현해둬야 함.
그 기능들을 사용하기 위해 필요한 jar 파일들을 준비하는 과정도 필요함.
DetectWebDetections.java
List<AnnotateImageRequest> requests = new ArrayList<>();
AnnotateImageRequest는 유저가 첨부한 이미지, 유저가 요청한 리퀘스트 그리고 Context Information을 활용하여 GCP Vision API를 실행시키는 것.
ByteString imgBytes = ByteString.readFrom(new FileInputStream(filePath));
ByteString은 Immutable한 byte의 시퀀스임. filePath라는 변수(파일경로)부터 이미지를 읽어오고 저장하는데 사용. 그 이후 이 이미지를 다시
Image img = Image.newBuilder().setContent(imgBytes).build();
Image.newBuilder().setContent().build()에 imgBytes를 넣어 Image형으로 만들어주기.
Feature feat = Feature.newBuilder().setType(Type.WEB\_DETECTION).build();
로 Feature도 세팅을 해준다고 한다.
AnnotateImageRequest request = AnnotateImageRequest.newBuilder().addFeatures(feat).setImage(img).build();
requests.add(request);
requests는 위의 AnnotateImageRequest를 담은 List임. 그 안에 위에서 만든 Image, Feature을 사용하여 만든 AnnotateImageRequest를 담아주는 것.
try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
BatchAnnotateImagesResponse response = client.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = response.getResponsesList();
for (AnnotateImageResponse res : responses) {
if (res.hasError()) {
return null;
}
client를 만들어주고 client.batchAnnotateImages() 안에 위에서 만든 request를 넣어주면 BatchAnnotateImagesResponse 형태로 결과를 반환받을 수 있음. 이를 다시 getResponseList() 함수를 사용하여 AnnotateImageResponse가 담긴 List로 변환해주기.
WebDetection annotation = res.getWebDetection();
WebEntity entity = annotation.getWebEntities(0);
entity.getDescription();
entity.getScore();
getDescription => 이미지를 무엇으로 예측하였는지 반환
getScore => 예측에 대한 점수
그 외에도 여러가지 확인 가능...
for (WebDetection.WebLabel label : annotation.getBestGuessLabelsList()) {
System.out.println(label.getLabel());
}
System.out.println("%nPages with matching images: Score%n==");
for (WebDetection.WebPage page : annotation.getPagesWithMatchingImagesList()) {
System.out.println(page.getUrl() + " : " + page.getScore());
}
System.out.println("%nPages with partially matching images: Score%n==");
for (WebDetection.WebImage image : annotation.getPartialMatchingImagesList()) {
System.out.println(image.getUrl() + " : " + image.getScore());
}
System.out.println("%nPages with fully matching images: Score%n==");
for (WebDetection.WebImage image : annotation.getFullMatchingImagesList()) {
System.out.println(image.getUrl() + " : " + image.getScore());
}
System.out.println("%nPages with visually similar images: Score%n==");
for (WebDetection.WebImage image : annotation.getVisuallySimilarImagesList()) {
System.out.println(image.getUrl() + " : " + image.getScore());
}
Best Guessed Label, Matching Pages, Partially Matching Image List, Fully Matching Image List, Visually Similar Image List 등 받기 가능.
이 파일에서는 return 값으로 response를 넣어주고 후에 필요한 값을 꺼내서 쓰면 될 것 같다.
fileupload.jsp
MultipartRequest multipartRequest = new MultipartRequest(request, path, sizeLimit, "utf-8", new DefaultFileRenamePolicy());
클라이언트의 상태정보를 유지하기 위해 MultipartRequest 사용.
(this.getServletContext().getRealPath(“/”) => ServletContext까지의 실제경로 => path변수에 넣어주기 / this.getServletContext().getContextPath() => Tomcat webapps에서 ServletContext까지의 경로)
index.html에서 업로드 한 파일의 value를 "upload"로 받았기에 getRealPath("upload"); 로 적기.
이 path 변수를 사용하여
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
자바에서 파일/폴더에 대한 제어를 하는데 File class를 사용 가능
File.mkdir() => 만들고자 하는 디렉토리의 상위 디렉토리가 존재하지 않을 경우 생성불가
File.mkdirs() => 만들고자 하는 디렉토리의 상위 디렉토리가 존재하지 않을 경우 상위 디렉토리까지 생성
String filename = multipartRequest.getFilesystemName();
String filepath = path + "\\" + filename;
WebEntity result = DetectWebDetections.Detect(filepath);
String description = result.getDescription();
아까 만들었던 함수로 WebEntity를 가져와주고 getDescription() 함수를 사용하여 Knowledge Graph Search를 위해 필요한 준비물을 마련하기.
Knowledge Graph Search는 Google에서 제공하는 또다른 API로 한국어로는 지식 정보 검색 API임. 구글에서 설명하는 바로는
- 특정 기준과 일치하는 가장 주목할만한 엔티티의 순위 목록을 가져옵니다.
- 검색 상자에서 엔터티를 예측 완료합니다.
- 지식 정보 항목을 사용하여 콘텐츠에 주석 달기/구성
Vision API를 통해 얻은 결과에 대해 다른 정보를 추출해낼 수 있는 것임.
아래는 구글에서 제공하는 예시 코드임.
SearchExample.java
/** Example of Java client calling Knowledge Graph Search API */
public class SearchExample {
public static Properties properties = new Properties();
public static void main(String[] args) {
try {
properties.load(new FileInputStream("kgsearch.properties"));
HttpTransport httpTransport = new NetHttpTransport();
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
JSONParser parser = new JSONParser();
GenericUrl url = new GenericUrl("https://kgsearch.googleapis.com/v1/entities:search");
url.put("query", "Taylor Swift");
url.put("limit", "10");
url.put("indent", "true");
url.put("key", properties.get("API_KEY"));
HttpRequest request = requestFactory.buildGetRequest(url);
HttpResponse httpResponse = request.execute();
JSONObject response = (JSONObject) parser.parse(httpResponse.parseAsString());
JSONArray elements = (JSONArray) response.get("itemListElement");
for (Object element : elements) {
System.out.println(JsonPath.read(element, "$.result.name").toString());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Result
{
"@context": {
"@vocab": "http://schema.org/",
"goog": "http://schema.googleapis.com/",
"resultScore": "goog:resultScore",
"detailedDescription": "goog:detailedDescription",
"EntitySearchResult": "goog:EntitySearchResult",
"kg": "http://g.co/kg"
},
"@type": "ItemList",
"itemListElement": [
{
"@type": "EntitySearchResult",
"result": {
"@id": "kg:/m/0dl567",
"name": "Taylor Swift",
"@type": [
"Thing",
"Person"
],
"description": "Singer-songwriter",
"image": {
"contentUrl": "https://t1.gstatic.com/images?q=tbn:ANd9GcQmVDAhjhWnN2OWys2ZMO3PGAhupp5tN2LwF_BJmiHgi19hf8Ku",
"url": "https://en.wikipedia.org/wiki/Taylor_Swift",
"license": "http://creativecommons.org/licenses/by-sa/2.0"
},
"detailedDescription": {
"articleBody": "Taylor Alison Swift is an American singer-songwriter and actress. Raised in Wyomissing, Pennsylvania, she moved to Nashville, Tennessee, at the age of 14 to pursue a career in country music. ",
"url": "http://en.wikipedia.org/wiki/Taylor_Swift",
"license": "https://en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License"
},
"url": "http://taylorswift.com/"
},
"resultScore": 4850
}
]
}
그래서 나는 이를 활용하여 VisionAPI에서 getDescription을 통해 얻은 결과를 Knowledge Graph Search API에 한 번 더 전송하여 추가 정보를 가져올 수 있게끔 함.
JSONArray result = SearchExample.search("en", description);
String resultDescription = JsonPath.read(result.get(0), "$.result.description").toString();
이런 식으로 사용하면 위의 예시에서는 Singer-songwriter이 반환되게 될 것임.