2016년 4월 27일 수요일

구글 비전 api 사용하기

비전 api는 구글에서 공개한 이미지 분석 api 이다.
라벨, 텍스트(ocr),랜드마크, 로고, 안면인식등의 기능을 제공한다.
가격은 다음과 같다.
각 조회 조건마다 개별적으로 계산되며 월 1000건까지는 무료다. 초과시에는 매 천건당 표기된 구간별 가격이 청구된다.


Feature1 - 1000 units/month1001- 1,000,000 units/month1,000,001 to 5,000,000 units/month5,000,001 - 20,000,000 units/month
Label DetectionFree$5.00$4.00$2.00
OCRFree$2.50$2.00$0.60
Explicit Content DetectionFree$2.50$2.00$0.60
Facial DetectionFree$2.50$2.00$0.60
Landmark DetectionFree$2.50$2.00$0.60
Logo DetectionFree$2.50$2.00$0.60
Image PropertiesFree$2.50$2.00$0.60
아! 혹시 월 2천만건 이상 조회하는 서비스를 만든다면 구글에 문의하라고 하네요 Cloud Vision API Quota Request.

코딩없이 간단하게 테스트하기
https://cloud.google.com/vision/docs/quickstart 로 접속한다.
해당페이지로 가면 간단한 구글클라우드설정 몇번으로 비전api를 사용해 볼 수 있게 해준다. 구글

프로젝트 설정

  1. 구글 클라우드 플랫폼을 사용하기 위해 프로젝트 설정 페이지로 이동해 새로운 프로젝트를 생성해 줍니다. 
  2. 결제 정보를 입력합니다. 유효한 결제 수단인지 테스트용으로 1$가 결제될수도 있지만 실제로 청구되지는 않습니다. 
  3. 클라우드 비전 api를 활성화 합니다.

클라우드 저장소 생성

  1. 저장소 브라우저로 이동합니다.
  2. 버킷을 생성해 줍니다. 실제로 저장할 위치를 얻습니다.
  3. 이름과 저장소 등급, 위치를 설정합니다. 설명이 잘 나와 있습니다.

클라우드 비전 api 호출하기

  1. 이미지를 준비합니다.
  2. 좀전에 생성한 클라우드스토리지의 버킷으로 이동합니다.  준비한 이미지를 업로드 합니다.
  3. 이지지가 업로드 되면 하단의 파일 목록 우측에 '공개링크' 체크박스가 있습니다. 이것을 체크해줘야 해당 이미지를 api 호출시 사용할 수 있습니다.
  4. 빠른실행 페이지에는 아래와 같이 리퀘스트바디를 생성해 주는 폼이 있는데 type과 파일주소를 입력해 주면 됩니다.  type은 api에서 지원하는 타입을  설정해 주시면 되고 파일주소는 좀전에 업로드한 버킷의 이미지를 입력해 주면 됩니다. 
    gs://bucket/demo-image.jpg 의 형식으로 되어 있는데 gs://{내버킷명}/{파일명}의 형식이므로 내 설정에 맞게 바꾸면 됩니다. OAuth인증을 사용해서 진행할 수도 있습니다.
  5. 저는 경복궁 경회루 사진을 이용해서 'LANDMARK_DETECTION'을 해봤습니다.
  6. 다음과 같은 응답이 왔습니다.
    vision.images.annotate executed moments ago time to execute: 2643 msRequest
  7. POST https://vision.googleapis.com/v1/images:annotate?key={YOUR_API_KEY}
    {
    "requests": [
    {
    "features": [
    {
    "type": "LANDMARK_DETECTION"
    }
    ],
    "image": {
    "source": {
    "gcsImageUri": "gs://seonsoo/1611732.jpg"
    }
    }
    }
    ]
    }

    Response

    200
    - Show headers -
    {
    "responses": [
    {
    "landmarkAnnotations": [
    {
    "mid": "/m/02v3t6",
    "description": "Gyeongbokgung",
    "score": 0.50221771,
    "boundingPoly": {
    "vertices": [
    {
    "x": 788,
    "y": 622
    },
    {
    "x": 2356,
    "y": 622
    },
    {
    "x": 2356,
    "y": 1057
    },
    {
    "x": 788,
    "y": 1057
    }
    ]
    },
    "locations": [
    {
    "latLng": {
    "latitude": 37.578256,
    "longitude": 126.977019
    }
    }
    ]
    },
    {
    "mid": "/m/05zp8",
    "description": "Palace",
    "score": 0.31039235,
    "boundingPoly": {
    "vertices": [
    {
    "x": 1185,
    "y": 586
    },
    {
    "x": 2032,
    "y": 586
    },
    {
    "x": 2032,
    "y": 1103
    },
    {
    "x": 1185,
    "y": 1103
    }
    ]
    },
    "locations": [
    {
    "latLng": {
    "latitude": 37.569344,
    "longitude": 126.977969
    }
    }
    ]
    },
    {
    "mid": "/m/048fz",
    "description": "Korea",
    "score": 0.20593485,
    "boundingPoly": {
    "vertices": [
    {
    "x": 729,
    "y": 832
    },
    {
    "x": 1193,
    "y": 832
    },
    {
    "x": 1193,
    "y": 1143
    },
    {
    "x": 729,
    "y": 1143
    }
    ]
    },
    "locations": [
    {
    "latLng": {
    "latitude": 37.529604,
    "longitude": 126.9828
    }
    }
    ]
    }
    ]
    }
    ]
    }
프로젝트 생성전에 구글 비전API가 어느정도의 인식률을 갖고 있는지 체크하는 용도로 사용해 보면 좋을 것 같습니다.

com.ibatis.common.beans.ProbeException: There is no READABLE property named

com.ibatis.common.beans.ProbeException: There is no READABLE property named XX ...

말 그대로  이름이 XX인 프로퍼티를 읽을 수가 없다는 말이다.
parameter 클래스나 맵에서 사용한 변수명과 쿼리문에 사용한 파라미터명이 같은지
확인한다.

2016년 4월 25일 월요일

xml 데이터로 html 뷰 만들기

1. 컨트롤러에서 json으로 변환 후 javascript로 html 구현
<server>
 URL url = new URL("http://www.ut.ac.kr/xmlout/Area.xml"); InputStream is = url.openStream(); String str = ""; StringBuilder sb = new StringBuilder();BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8")); try {
     while ((str = br.readLine())!= null) {
         sb.append(str);     }

 } catch (Exception e) {
     e.printStackTrace(); } finally {
     if (is != null) {
         is.close();         br.close();     }
 }
 JSONObject xmlJSONObj = XML.toJSONObject(sb.toString());

<client>
<script>
var json
function getDoc() {
    json = JSON.parse('${xml}');    var items = json.Info.items;    items.forEach(function (row) {        var cat = row.Category;        var name = row.Name;        var tel = row.Tel;        var lati = row.Latitude;        var longti = row.Longitude;
    });}

</script>

2.jstl로 파싱

<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<x:parse var="out" xml="${xmlData}"/>
<x:forEach select="$out/Info/items" var="item">
        <li class="map" title="<x:out select="Name"/>" lat="<x:out select="Latitude"/>" lng="<x:out select="Longitude"/>">
[<x:out select="Category"/> ]  상호 : <x:out select="Name"/></li>
</x:forEach>

ORA-01741: illegal zero-length identifier

ORA-01741: illegal zero-length identifier

한글자 이상 넣는다. 최소한 공백이라도

ORA-01741:illegal zero-length identifier
Cause:An attempt was made to use two double quotes ("") as an identifier. An identifier must be at least one character long.
Action:Insert at least one character between the double quotes in the identifier. If a blank identifier is required, specify a blank space between the double quotes (" ").

jstl 역순으로 정렬

먼저 해당 어트리뷰트를 페이지 컨텍스트의 scope변수로 저장하고 이를 역순으로 정렬하는
스크립틀릿을 추가한다.
<c:set var= "option" value =" ${ getDDLHakgiRegion}"/>
<% List<HashMap<String, String>> options = (List<HashMap<String, String>>)pageContext.getAttribute("option" );Collections.reverse(options);
pageContext.setAttribute("option,options);
%> <select id ="select-time-term" > <option >학기 </option > < c:forEach var= "row" items=" ${option}"> <option value=" ${row.MST_VAL}"> <c:out value =" ${row.MST_SMPL_NM}" /></option > </ c:forEach> </select >

kotlin programming language - 기초타입

코틀린에서는 모든것이 다 객체이며 numbers, characters, booleans and arrays.

Numbers
kotlin은 자바와 비슷하게 number를 취급하지만 정확하게 같지는  않다. 

TypeBit width
Double64
Float32
Long64
Int32
Short16
Byte
8

Literal Constants
-decimal:123
-long : 123L
-double : 123.5, 123.5e10
-float : 123.5f or 123.5F
-10진수 : 0x0F
-바이너리 :  0b00001011
#8진수는 지원하지 않습니다.

nullable 변수와 일반 변수 값 비교
값을 비교할 때 '=='과 '==='으로 비교할 수 있습니다.
'=='은 자바에서의 사용법과 다르게 equal()과 같습니다. 값만 비교합니다.
물론 equal()도 사용할 수 있습니다. 단 nullable로 선언된 변수는사용할 수 없습니다.
'==='은 자바의 '=='과 같습니다. 비교할 두 변수가 같은 값과 같은 오브젝트인지 체크합니다.
val a: Int = 10000print(a === a) // Prints 'true'val boxedA: Int? = a
val anotherBoxedA: Int? = a
print(boxedA === anotherBoxedA) // !!!Prints 'false'!!!print(boxedA == anotherBoxedA) // Prints 'true'

타입 캐스팅 
자바에서는 (변환할 타입)변환할 변수 이런 형식으로 다음과 같이 변환했다
Object obj = "hello";String str = (String) obj;//Object에서 String으로 타입 변환((String) obj).toCharArray();//String 타입의 메소드 사용 

kotlin에서는 'as' 키워드를 사용하여 변환한다 
val obj: Any = "hello"val str:String = obj as String //String 타입으로 변환(obj as String).toCharArray() //String 클래스의 메소드 사용

kotlin에는 wrapper 클래스가 없으므로 자바에서 처럼 boxing/unboxing/autoboxing 이 이루어지지 않습니다.
int a =1000;long b = a;
자바에서는 별다른 구현없이 자동으로 됐지만
val a: Int = 1val b: Long = a.toLong()
 이런식으로 명시해줘야 함 
아래와 같이 수학연산할 때만 묵시적으로 캐스팅없이 가능
val l = 1L // Long + Int => Long

Characters
캐릭터(Char)는 홅따옴표로 'a' 표시하고 특수기호의 이스케이프는 역슬레시'\'로  
fun decimalDigitValue(c: Char): Int {
    if (c !in 'a'..'z')
        throw IllegalArgumentException("Not a lowercase alphabet")
    return c.toInt() // 캐릭터 코드 리턴}

Boolean
true 및 false로 표현할 수 있고 논리합연산자 '||' 이나 논리곱연산자 '&&', 논리부정연산자  '!'으로 연산을 할 수 있다.
하지만 자바와 다르게 '|'와 '&'는 사용할 수 없습니다.

Array
kotlin에는 객체생성을 위해 new 키워드를 사용하지 않는다. 때문에 array 객체 생성이나 초기화에 불편함을 느낄 수도 있겠다.
array 객체 생성비교
[자바]
String[] strArr= null;String[] strArr1= {"a","b","c"};String[] strArr2= new String[]{};String[] strArr3= new String[]{"a","b","c"};
[kotlin]
val array nullval array2 arrayOf("a","b","c") // arrayOf()메소드를 통해 초기화 해야 한다

기본타입+arrayOf로 특정타입의 배열을 생성할 수 있다. 이 클래스들은 Array()클래스와 상속관계가 없는 독립적인 클래스이다. ex)intArrayOf(..),byteArrayOf(..)
또 Array클래스를 생성하며 람다식을 활용하여 배열을  생성할 수도 있다.
val limitedArray = Array(5,i->(i*i)}) //index를 이용하여 초기화한다
Array클래스의 생성자를 보면
public inline constructor(size: Intinit: (Int) -> T)
처럼 되어 있다. 사이즈와 초기화 메소드를 제공하면 배열을 생성해 준다.
생성한 후 출력해 보면 [0, 1, 4, 9, 16]의 결과를 확인할 수 있다.

String
Kotlin에서 String은 자바와 같이 불변성을 갖는다. 
String 리터럴: 이스케이프된 스트링과 줄바꿈기호가 포함된 raw 스트링 두가지종류가 있다.
이스케이프된 스트링은 자바와 매우 흡사하다. 
val s = "Hello, world!\n"
raw 스트링은 쌍따옴표 3개의 블럭으로 선언한다. (""" ...""")
기본 스트링("" "")은 줄바꿈시 +기호로 연결 안하면 오류 raw 타입 스트링은 """안에서 줄바꿈이 자유롭다. intellij에서는 엔터키 입력하면 자동으로 텍스트 블럭 닫고 + 기호로 연결해 준다.
val text = """|Tell me and I forget.|Teach me and I remember.|Involve me and I learn.|(Benjamin Franklin)"""
어쨌든 위의 텍스트를 출력해 보면 다음과 같이 처음과 마지막줄에 한줄씩 추가되어 있고 각 줄의 시작에 공백이 있는걸 볼수 있다.

(공백)
    |Tell me and I forget.
    |Teach me and I remember.
    |Involve me and I learn.
    |(Benjamin Franklin)
(공백)

이것은 String 클래스의  trimMargin()함수를 사용하면 해결된다. 파라미터로 마진 prefix를 입력할 수 있는데 기본값은 "|"이다. 무슨말인고 하니 각줄의 시작에 "|"을 추가하고 해당 함수를 호출하면 공백을 없애준다는 것이다.

Tell me and I forget.
Teach me and I remember.
Involve me and I learn.
(Benjamin Franklin)


문장 첫머리의 "|" 기호가 사라지고 공백도 함께 사라졌다. prefix값은 편의대로 입력하면 된다.ex) trimMargin(">")

2016년 4월 23일 토요일

kotlin programming langauage - 반복제어문

while loop
자바와 거의 동일하다
[while문]
    while (x > 0) {
        x--
    }
[do..while 문]
do{
    print(x)
}while(x>0)
}

자바의 iterator를 이용한 for문과 비슷하다.
for (item in collection)
    print(item)
물론 {}를 사용해도 되고 타입을 지정해도 된다.
for (item:String in collection){
    print(item)
}
인덱스 기반으로 사용할 경우 indices함수를 사용한다. 해당 함수는 컬렉션의 int range를 리턴해준다.
for (item in collection.indices)
    print(item)
그리고 이터레이터를 이용한 for문 사용시 문제가 되었던 인덱스 사용도 withIndex()함수를 사용한다면 별도의 구현이 필요 없다.
for((index,value) in x.withIndex()){
    println("index:$index,value:$value")
}
ranges and in

label and return
kotlin에도 반복문을 제어하기위해  label과 continue, break, return이 있다.기본은 자바와 같다. 
 return : 실행중인 함수가 종료된다.
continue :가장 가까운 반복문의 다음 단계로 이동
break:가장 가까운 반복문을 종료 시킨다.

먼저 라벨을 설명하기 위해 자바와 비교하자면
자바의 Label  반복문 앞에 라벨명:<반복문>의 형식으로 사용한다
public static void main (String[] args){
    firstLabel:for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            if(j%>0continue ;           
            if(j==4continue firstLabel;          
            System.out.println(i + "-"+j);
        }
    }
}
kotlin에서는 

fun main(args:Array<String>){
    val x =arrayOf("a","b","c")
    firstLabel@ for(i in 1..10) {
        for (j in 1..10) {
            if (j % 0continue
            if (j > 5continue@firstLabel 
           println("$i - $j")
        }
        println("after foreach")
    }
}

람다식 foreach에서의 라벨 사용
fun main(args:Array<String>){
    val x =arrayOf("a","b","c")
    x.forEach {
        if(it == "b"return
        println("$it")
    }
    println("after foreach")
}

if 조건에 맞아 return이 실행되면 함수가 종료되고 결과는 a만 출력된다.
fun main(args:Array<String>){
    val x =arrayOf("a","b","c")
    x.forEach loop@{
        if(it == "b"return@loop
        println("$it")
    } 
   println("after foreach")
}
라벨을 사용하면 함수전체가 종료되는 것이 아니라 해당 조건만 종료되고 계속진행된다.
결과는 a c after foreach가 출력된다.

람다식에서는 함수와 같은 이름의 라벨을 사용 한다면 라벨선언을 생략할 수 있다.
fun main(args:Array<String>){
    val x =arrayOf("a","b","c")
    x.forEach {
         if(it == "b"return@forEach
        print(it)
    }}

햇갈린다면 익명 함수를 람다 표현식 안에 선언하여 사용할 수 있다.
fun main(args:Array<String>){
    val x =arrayOf("a","b","c")
    x.forEach(fun(value:String){
        if(value == "b"return
        print(value)
    })

}


2016년 4월 21일 목요일

kotlin programming language - 조건 제어문

kotlin에는 if, when 두가지 조건 제어문이 있습니다.

if 조건문

//1.전통적인 사용법
var max = a 
if (a < b)
  max = b
 
// 2.if .. else
var max: Int
if (a > b) 
  max = a
else
  max = b
 
kotlin에서는 if문으로 3항연산자를 표현할 수 있습니다.
val max = if (a > b) a else b
오른쪽 조건문의 값이 왼쪽 변수에 대입될 수 있습니다. 만약 if문에 {}블록이 있다면 마지막 항목이 해당 블록의 리턴값이 됩니다.

val max = if (a > b) {
    print("Choose a")
    a
  }
  else {
    print("Choose b")
    b 
  }
a가 1 b가 2라고 한다면 max = 2가 됩니다.

when 
when은 기존의 switch문을 대신합니다. 
when (x) {
  1 -> print("x == 1") //x가 1일 때 
  2 -> print("x == 2") //x가 2일 때
  else -> { // 나머지 경우
    print("x is neither 1 nor 2")
  }}
변수가 다르지만 같은 결과를 출력 때는 ','로 구분하여 사용할 수 있습니다.
when (x) {
  0, 1 -> print("x == 0 or x == 1")
  else -> print("otherwise")}

또 in 을 range나 컬렉션과 함께 사용할 수 있습니다.
when (x) {
  in 1..10 -> print("x is in the range")
  in validNumbers -> print("x is valid")
  !in 10..20 -> print("x is outside the range")
  else -> print("none of the above")}

타입 체크시에는 'is'를 사용합니다.
val hasPrefix = when(x) {
  is String -> x.startsWith("prefix")
  else -> false}

kotlin programming language - 클래스 생성

클래스의 생성
코틀린에서는 new 선언자가 없다. 클래스명()으로 선언한다.
class Example(){} -> Example()

생성자
primary constructor와 한개 또는 그 이상의 secondary constructor를 갖는다.
primary constructor : 클래스 헤더에 선언
class constructor Example(title:String){}
단, 다른 annotation이나 visible modifier가 없다면 생략 가능

코클린의 모든 클래스는 공통 클래스 Any를 갖는다. 이것은 기본 선언없이 사용되며 java.lang.Object는 아니다.
클래스를 상속하기 위해서는 'open' annotaion을 붙여준다. 이는 final과 반대되는 성격의 지시자 이다. 다음과 같이 사용한다.

open class Base(p: Int){}
class Derived(p: Int) : Base(p){}

method overrinde
java와 동일하게 사용된다. super class에 동일한 메소드가 있다면 override annotation을 앞에 붙인다.
super class의 멤버에 open으로 선언되어 있어야 한다.
open class Base {
  open fun v() {}
  fun nv() {}}class Derived() : Base() {
  override fun v() {}}


gettter&setter

-작성중-

2016년 4월 19일 화요일

Kotlin Programming Language 시작하기 - 기초문법

1. 기초 문법
 - 패키지 선언 : 자바와 같이 최상단에서 선언한다.
package foo.bar

fun baz() {}

class Goo {}
자바와 다르게 클래스와 메소드가 한 파일에 같은 레벨로 존재할 수 있다.
따라서 import시 사용할 메소드와 클래스의 패키지명은 같다
메소드 baz()의 풀패키지명은 foo.bar.baz
클래스 Goo의 풀 패키지명은 foo.bar.goo

패키지명이 특정되지 않았다면 default 패키지에 속하고 아무런 이름이 없다.

Imports
import foo.Bar // Bar만 접근가능 
import foo.* // foo의 모든 컨텐츠(패키지,클래스, 오브젝트 등등)에 접근가능
패키지명이 충돌할 수도 있다. 이때에는 'as'키워드를 사용한다
import foo.Bar // Bar is accessible
import bar.Bar as bBar // bBar stands for 'bar.Bar'

자바와는 다른점 import static이 없다. 패키지명이 디렉토리 구조와 달라도 상관없다

 메소드 선언하기
 fun 지시자(?)를 통해 선언하며  자바와 리턴타입과 파라미터 표현 방식이 조금 다르다. 형식은 다음과 같다. 
  fun <function 명>(<파라미터명>:<파라미터타입>):리턴 타입 

 예제로 제시된건 4가지 방법 있다. 
가. 자바와 비슷하게 return 타입을 선언하고 body에 return문 기술
fun sum(a: Int, b: Int): Int {
    return a + b
}
나. return 타입을 생략하고 = 우측에 return 문 기술
fun sum(a: Int, b: Int) = a + b
다. void 타입(return 타입 Unit은 void와 같다.)
fun printSum(a: Int, b: Int): Unit {
    print(a + b)
}
라. 3의 unit은 생략될 수 있다
fun printSum(a: Int, b: Int) {
    print(a + b)
}

변수 선언
변수를 선언할 때에는 크게 val과 var 두가지 타입으로 선언할 수 있다. val은 자바의  final과 비슷하며 선언하고 값을 초기화한 뒤에는 더이상 수정되지 않는다. var는 계속 수정 가능하다. 아래와 같이 선언 할 수 있다.
val a: Int = 1 //int 타입으로 선언하고 정수 1로 초기화
val b = 1   // 초기화 값이 있다면 타입 생략 가능
 val c: Int  // 선언과 동시에 초기화 하지 않는다면 타입선언 필요
c = 1       // 초기화
c=2       //다시 값을 변경하려 한다면 Kotlin: Val cannot be reassigned 오류발생

var x = 5 // `Int` type is inferredx += 1

null타입 변수 선언
null타입의 변수를 선언하기 위해서는 변수선언시 타입뒤에 ?를 붙여준다.
val canNull:String? = null //null로 변수를 초기화할 수 있다. 다만 val타입 변수는 다시 값을 변경할 수 없다 
val notNull:String = null  //null은 non-null type 변수의 값이 될 수 없다.