[Translation API] Extract, Analyze, and Translate Text from Images with the Cloud ML APIs

yejinยท2026๋…„ 4์›” 13์ผ

Google Skills

๋ชฉ๋ก ๋ณด๊ธฐ
2/46

Course

Analyze Images with the Cloud Vision API

Lab

๋ชฉ๋ก

  • APIs Explorer: Qwik Start
  • Extract, Analyze, and Translate Text from Images with the Cloud ML APIs โฌ…๏ธ ์˜ค๋Š˜ ํ•™์Šตํ•  Lab!
  • Detect Labels, Faces, and Landmarks in images with the Cloud Vision API
  • Analyze Images with the Cloud Vision API: Challenge Lab
  • Claim credential (๋ชจ๋“  ๊ฐ•์˜๋ฅผ ์ˆ˜๋ฃŒํ•ด์•ผ Skill badge ์ทจ๋“ ๊ฐ€๋Šฅ!โœจ)

๐ŸŒ Extract, Analyze, and Translate Text from Images with the Cloud ML APIs

๊ฐœ์š”

Cloud Vision API์˜ ํ…์ŠคํŠธ ๊ฐ์ง€ ๋ฉ”์„œ๋“œ๋กœ ๊ด‘ํ•™ ๋ฌธ์ž ์ธ์‹(OCR)์„ ํ™œ์šฉํ•ด ์ด๋ฏธ์ง€์—์„œ ํ…์ŠคํŠธ๋ฅผ ์ถ”์ถœํ•˜๋Š” ๊ฒƒ์—์„œ ์ถœ๋ฐœํ•˜์—ฌ ์ด ํ…์ŠคํŠธ๋ฅผ Translation API๋กœ ๋ฒˆ์—ญํ•˜๊ณ  Natural Language API๋กœ ๋ถ„์„ํ•˜๊ธฐ

์‹ค์Šต๊ณผ์ •

(1) Cloud Shell ํ™œ์„ฑํ™”: ์šฐ์ธก ์ƒ๋‹จ์— Shell ๋ฒ„ํŠผ ํด๋ฆญ ํ›„ ํ™œ์„ฑํ™” ์ง„ํ–‰


Your Cloud Platform project in the session is set to "PROJECT_ID" ๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€ ๋ณด์ด๋ฉด ์„ฑ๊ณต!
โžก๏ธ PROJECT_ID: ์ž๋™์œผ๋กœ ์„ค์ •๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž๋งˆ๋‹ค ์ƒ์ด

(2) ํ™œ์„ฑ ๊ณ„์ • ์ด๋ฆ„ ๋ชฉ๋ก๊ณผ ํ”„๋กœ์ ํŠธ ID ๋ชฉ๋ก ํ™•์ธ (์„ ํƒ์‚ฌํ•ญ)


(3) API ํ‚ค ๋งŒ๋“ค๊ธฐ

(3-1) ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฉ”๋‰ด > APIs & Servies > Credentials > + Create credenntials > API key

(3-2) API (Cloud Translation API, Cloud Vision API, Natural Language API) ์„ ํƒ ํ›„ API key ๋ณต์‚ฌ

(3-3) ํ™˜๊ฒฝ๋ณ€์ˆ˜์— API key ๊ฐ’ ์ €์žฅ

export API_KEY=<YOUR_API_KEY>

โžก๏ธ echo API_KEY ๋ฅผ ํ†ตํ•ด์„œ ์ œ๋Œ€๋กœ ์„ธํŒ… ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ ๊ฐ€๋Šฅ


(4) Cloud Storage Bucket์— ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ

โžก๏ธ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฐ” > Cloud Storage > Create Bucket > Bucket ์ƒ์„ฑ ํ›„ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ (์ƒ์„ธ ๋ฐฉ๋ฒ•์€ ์ด์ „ ํฌ์ŠคํŠธ ์ฐธ๊ณ )

์ฐธ๊ณ  ์ด๋ฏธ์ง€

(5) ์ด๋ฏธ์ง€ ์ ‘๊ทผ ๊ถŒํ•œ ์„ค์ •

โžก๏ธ ์ด๋ฏธ์ง€ ์„ค์ • > Add Entry > Public / allUsers / Reader ๊ถŒํ•œ ๋ถ€์—ฌ
(์ƒ์„ธ ๋ฐฉ๋ฒ•์€ ์ด์ „ ํฌ์ŠคํŠธ ์ฐธ๊ณ )


(6) Cloud Vision API Reqest ์ƒ์„ฑ

โžก๏ธ ocr-request.json ํŒŒ์ผ ์ƒ์„ฑ

{
  "requests": [
      {
        "image": {
          "source": {
              "gcsImageUri": "gs://my-bucket-name/sign.jpg"
          }
        },
        "features": [
          {
            "type": "TEXT_DETECTION",
            "maxResults": 10
          }
        ]
      }
  ]
}

์ฐธ๊ณ 

ํŒŒ์ผ ์ƒ์„ฑ ๋ฐฉ๋ฒ•์€ nano, vim, emacs ๋“ฑ ์„ ํ˜ธํ•˜๋Š” Command line editor๋ฅผ ์‚ฌ์šฉํ•ด๋„ ๋ฌด๋ฐฉํ•˜๋‹ค.


(7) ํ…์ŠคํŠธ ๊ฐ์ง€ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

1) Cloud Shell ์—์„œ curl์„ ์‚ฌ์šฉํ•˜์—ฌ Cloud Vision API๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

curl -s -X POST -H "Content-Type: application/json" --data-binary @ocr-request.json  https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}

Response ๊ฐ’ ๋ถ„์„

textAnnotations์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ์ฒซ ๋ฒˆ์งธ ๋ฐ์ดํ„ฐ๋Š” API๊ฐ€ ์ด๋ฏธ์ง€์—์„œ ์ฐพ์€ ์ „์ฒด ํ…์ŠคํŠธ ๋ธ”๋ก์ด๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ’๋“ค์ด ํฌํ•จ๋œ๋‹ค.

  • ์–ธ์–ด์ฝ”๋“œ(the language code)
  • ํ…์ŠคํŠธ ๋ฌธ์ž์—ด(a string of the text)
  • ์ด๋ฏธ์ง€์—์„œ ํ…์ŠคํŠธ๊ฐ€ ๋ฐœ๊ฒฌ๋œ ์œ„์น˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒฝ๊ณ„ ์ƒ์ž(a bounding box indicating where the text was found in the image)

2) ์ถ”ํ›„์— ์ฐธ์กฐํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ํŒŒ์ผ์— ์‘๋‹ต ๊ฒฐ๊ณผ ์ €์žฅํ•œ๋‹ค.

โžก๏ธ ocr-request.json ํŒŒ์ผ์— ์ €์žฅ๋œ๋‹ค.

curl -s -X POST -H "Content-Type: application/json" --data-binary @ocr-request.json  https://vision.googleapis.com/v1/images:annotate?key=${API_KEY} -o ocr-response.json

(8) ์ด๋ฏธ์ง€์˜ ํ…์ŠคํŠธ๋ฅผ Translation API๋กœ ์ „์†กํ•˜๊ธฐ

1) ํ…์ŠคํŠธ์™€ ๋Œ€์ƒ ์–ธ์–ด์˜ ๋‚ด์šฉ์„ ๋‹ด์€ translation-request.json ํŒŒ์ผ ์ƒ์„ฑ

{
  "q": "your_text_here",	//์ถ”ํ›„ ๋ฒˆ์—ญํ•  ๋ฌธ์ž์—ด์ด ์ €์žฅ๋จ
  "target": "en"			//๋ฒˆ์—ญํ•  ์–ธ์–ด ์ฝ”๋“œ
}

์ฐธ๊ณ 

์–ธ์–ด ์ง€์›์„ ํ†ตํ•ด Translation API๋กœ ๋ฒˆ์—ญ ๊ฐ€๋Šฅํ•œ ์–ธ์–ด๋“ค๊ณผ ํ•ด๋‹นํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

2) (7-2)์—์„œ ๋งŒ๋“  ocr-response.json ํŒŒ์ผ์—์„œ ํ…์ŠคํŠธ๋ฅผ ์ถ”์ถœํ•ด ๊ฐ€๊ณตํ•œ ๋’ค, ๊ทธ ๋‚ด์šฉ์„ translation-request.json ํŒŒ์ผ์˜ ํŠน์ • ์œ„์น˜(=q์˜ value)์— ์ž๋™์œผ๋กœ ์‚ฝ์ž…ํ•œ๋‹ค.

STR=$(jq .responses[0].textAnnotations[0].description ocr-response.json) && STR="${STR//\"}" && sed -i "s|your_text_here|$STR|g" translation-request.json

์ฃผ์˜๐Ÿ’ฅ


์œ„์ฒ˜๋Ÿผ error๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ์ฒ˜์Œ์— ์ƒ์„ฑํ•œ API๊ฐ€ Cloud Vision API๋‚˜ Cloud Translation API, Natural Language API์— ๋Œ€ํ•œ ๊ถŒํ•œ์ด ์—†๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฉ”๋‰ด > APIs & Servies ์—์„œ ๋‚ด๊ฐ€ ์ฒ˜์Œ์— ์ƒ์„ฑํ•œ API Key๋ฅผ ์„ ํƒ ํ›„, API ๊ถŒํ•œ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

3) Translation API๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๊ทธ ์‘๋‹ต์„ translation-response.json ํŒŒ์ผ์— ์ €์žฅํ•œ๋‹ค.

curl -s -X POST -H "Content-Type: application/json" --data-binary @translation-request.json https://translation.googleapis.com/language/translate/v2?key=${API_KEY} -o translation-response.json

(9) Natural Language API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€์˜ ํ…์ŠคํŠธ ๋ถ„์„ํ•˜๊ธฐ

์ฐธ๊ณ 

Google Cloud Natural Language API๋Š” ์ปดํ“จํ„ฐ๊ฐ€ ์ธ๊ฐ„์˜ ์–ธ์–ด(์ž์—ฐ์–ด)๋ฅผ ์ดํ•ดํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋„๊ตฌ์ด๋‹ค. ๋‹จ์ˆœํžˆ ํ…์ŠคํŠธ๋ฅผ ์ฝ๋Š” ๊ฒƒ์„ ๋„˜์–ด, ๊ทธ ์•ˆ์— ๋‹ด๊ธด ์˜๋„, ๊ฐ์ •, ๊ตฌ์กฐ๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ํŠนํ™”๋˜์–ด ์žˆ๋‹ค.

1) API ์š”์ฒญ์„ ์œ„ํ•ด nl-request.json ํŒŒ์ผ ์ƒ์„ฑ

{
  "document":{
    "type":"PLAIN_TEXT",
    "content":"your_text_here"
  },
  "encodingType":"UTF8"
}

ํ•ญ๋ชฉ ๋ถ„์„

  • type: ์ง€์›๋˜๋Š” ์œ ํ˜•(PLAIN_TEXT, HTML)
  • content: Natural Language API์— ์ „์†กํ•˜์—ฌ ๋ถ„์„ํ•˜๋ ค๋Š” ํ…์ŠคํŠธ๋ฅผ ์ „๋‹ฌ
    • Cloud Storage์—์„œ ํŒŒ์ผ์„ ์ „์†กํ•˜๋ ค๋ฉด, content๋ฅผ gcsContentUri๋กœ ๋Œ€์ฒดํ•˜๊ณ  Cloud Storage์˜ ํ…์ŠคํŠธ ํŒŒ์ผ์˜ URI ๊ฐ’์„ ์‚ฌ์šฉํ•ด์•ผ ํ•จ
  • encodingType: API์— ํ…์ŠคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•  ํ…์ŠคํŠธ ์ธ์ฝ”๋”ฉ ์œ ํ˜•

2) ๋ฒˆ์—ญ๋œ ํ…์ŠคํŠธ๋ฅผ nl-request.json์˜ content ๋ถ€๋ถ„์— ๋ณต์‚ฌํ•ด ๋„ฃ๊ธฐ

STR=$(jq .data.translations[0].translatedText  translation-response.json) && STR="${STR//\"}" && sed -i "s|your_text_here|$STR|g" nl-request.json

3) Natural Language API์˜ analyzeEntities ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ˜ธ์ถœ

โžก๏ธ ์ด์ œ nl-request.json ํŒŒ์ผ์— ์›๋ณธ ์ด๋ฏธ์ง€์—์„œ ์ถ”์ถœํ•˜์—ฌ ์˜์–ด๋กœ ๋ฒˆ์—ญ๋œ ํ…์ŠคํŠธ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ถ„์„ ๊ฐ€๋Šฅ!

curl "https://language.googleapis.com/v1/documents:analyzeEntities?key=${API_KEY}" \
  -s -X POST -H "Content-Type: application/json" --data-binary @nl-request.json

Response ๋ถ„์„

student_02_bd8583cb7b9e@cloudshell:~ (qwiklabs-gcp-02-6bd633451e8b)$ curl "https://language.googleapis.com/v1/documents:analyzeEntities?key=${API_KEY}" \
  -s -X POST -H "Content-Type: application/json" --data-binary @nl-request.json
{
  "entities": [
    {
      "name": "news reports",
      "type": "WORK_OF_ART",
      "metadata": {},
      "salience": 0.34937522,
      "mentions": [
        {
          "text": {
            "content": "news reports",
            "beginOffset": 16
          },
          "type": "COMMON"
        }
      ]
    },
    {
      "name": "PUBLIC GOOD",
      "type": "ORGANIZATION",
      "metadata": {
        "wikipedia_url": "https://en.wikipedia.org/wiki/Public_good",
        "mid": "/m/017bkk"
      },
      "salience": 0.26161328,
      "mentions": [
        {
          "text": {
            "content": "PUBLIC GOOD",
            "beginOffset": 4
          },
          "type": "PROPER"
        }
      ]
    },
    {
      "name": "Obama",
      "type": "PERSON",
      "metadata": {
        "wikipedia_url": "https://en.wikipedia.org/wiki/Barack_Obama",
        "mid": "/m/02mjmr"
      },
      "salience": 0.18295486,
      "mentions": [
        {
          "text": {
            "content": "Obama",
            "beginOffset": 33
          },
          "type": "PROPER"
        }
      ]
    },
    {
      "name": "mustard",
      "type": "OTHER",
      "metadata": {},
      "salience": 0.115125984,
      "mentions": [
        {
          "text": {
            "content": "mustard",
            "beginOffset": 44
          },
          "type": "COMMON"
        }
      ]
    },
    {
      "name": "Dijon",
      "type": "LOCATION",
      "metadata": {
        "wikipedia_url": "https://en.wikipedia.org/wiki/Dijon",
        "mid": "/m/0pbhz"
      },
      "salience": 0.09093063,
      "mentions": [
        {
          "text": {
            "content": "Dijon",
            "beginOffset": 60
          },
          "type": "PROPER"
        }
      ]
    }
  ],
  "language": "en"
}
์—”ํ‹ฐํ‹ฐ(์ด๋ฆ„)์œ ํ˜•์ค‘์š”๋„์„ค๋ช…
new reportsWORK_OF_ART0.349์ด ๋ฌธ์žฅ์—์„œ ๊ฐ€์žฅ ํ•ต์‹ฌ์ ์ธ ์†Œ์žฌ(์˜ˆ์ˆ /์ €์ž‘๋ฌผ)๋กœ ์ธ์‹
PUBLIC GOODORGANIZATION0.261๊ณต๊ณต์žฌ๋ฅผ '๋‹จ์ฒด/์กฐ์ง'์œผ๋กœ ๋ถ„๋ฅ˜
ObamaPERSON0.182'๋ฒ„๋ฝ ์˜ค๋ฐ”๋งˆ'๋ผ๋Š” ์ธ๋ฌผ๋กœ ์ •ํ™•ํžˆ ์ธ์‹
mustardOTHER0.115์ผ๋ฐ˜์ ์ธ ์‚ฌ๋ฌผ(๋จธ์Šคํ„ฐ๋“œ ์†Œ์Šค ๋“ฑ)๋กœ ๋ถ„๋ฅ˜
DijonLOCATION0.091ํ”„๋ž‘์Šค์˜ ๋„์‹œ '๋””์ข…'์ด๋ผ๋Š” ์žฅ์†Œ๋กœ ์ธ์‹
  • type: ํ•ด๋‹น ๋‹จ์–ด๊ฐ€ ์ธ๋ฌผ(PERSON), ์žฅ์†Œ(LOCATION), ์กฐ์ง(ORGANIZATION) ์ค‘ ์–ด๋””์— ์†ํ•˜๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋ƒ„
  • metadata: ์ง€์‹ ๊ทธ๋ž˜ํ”„์™€ ์—ฐ๊ฒฐ๋œ ์ •๋ณด -> ํŠนํžˆ wikipedia_url์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์€ API๊ฐ€ ์ด ๋‹จ์–ด๊ฐ€ ๊ตฌ์ฒด์ ์œผ๋กœ ๋ฌด์—‡์ธ์ง€(์˜ˆ: ์ˆ˜๋งŽ์€ ์˜ค๋ฐ”๋งˆ ์ค‘ ์ „ ๋ฏธ๊ตญ ๋Œ€ํ†ต๋ น ์˜ค๋ฐ”๋งˆ) ํ™•์‹คํžˆ ์•Œ๊ณ  ์žˆ๋‹ค๋Š” ๋œป!
  • salience (์ค‘์š”๋„): 0์—์„œ 1 ์‚ฌ์ด์˜ ์ˆซ์ž๋กœ, ๋ฌธ์žฅ์—์„œ ์ด ๋‹จ์–ด๊ฐ€ ์–ผ๋งˆ๋‚˜ ์ค‘์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•˜๋Š”์ง€ ๋ณด์—ฌ์คŒ
  • mentions: ๋ฌธ์žฅ ๋‚ด์—์„œ ์ด ๋‹จ์–ด๊ฐ€ ๋‚˜ํƒ€๋‚œ ์œ„์น˜์™€ ๊ณ ์œ  ๋ช…์‚ฌ์ธ์ง€ ์ผ๋ฐ˜ ๋ช…์‚ฌ์ธ์ง€ ๋“ฑ์„ ๋‚˜ํƒ€๋ƒ„

๋ฒˆ์™ธโ‰๏ธ

์‹ค์Šต ๊ฐ•์˜์—๋Š” ์˜์–ด๋กœ ๋ฒˆ์—ญ์„ ํ•˜๋„๋ก ๋˜์–ด ์žˆ์ง€๋งŒ, ๋‚˜๋Š” ํ•œ๊ตญ์–ด๋กœ ๋ฒˆ์—ญ์„ ์‹œ๋„ํ•ด๋ณด์•˜๋‹ค. -> translation-request.json ํŒŒ์ผ์˜ target์„ ko๋กœ ๋ณ€๊ฒฝ ํ›„ ๋‚˜๋จธ์ง€๋Š” ๋™์ผํ•œ ์ˆœ์„œ์™€ curl์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง„ํ–‰ํ•˜์˜€๋‹ค.

profile
์ƒˆ์‹น ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€