Swift 언어를 사용하여
네이버 Clova OCR 엔진을 사용하는 예제를 포스팅한다!
네이버 Clovar OCR Api 사용 방법부터 진행해야 하는 분은
이전 글부터 읽어야 한다
네이버 Clova OCR 사용 예제
2022.12.07 - [프로그래밍/기타] - [OCR] 네이버 Naver Clova OCR 사용
api 사용 완료 했다면,
이제부터 예제를 스탭별로 따라 하면 된다!
Chap1. 번역할 이미지를 넣는다
저는 김수영 시인의 '사랑' 이라는 시를 번역해 보겠습니다
번역할 이미지를 Asset에 넣어줍니다.
이미지를 변수에 저장합니다!
var image = UIImage(named: "love")
여기까지 하면 이미지 준비는 '완'
Chap2. 네이버 Clova Platform에서 생성한 Secret Key와 Api URL 을 저장한다
Secret Key 와 Api URL 은 변하지 않음으로 let 변수에 저장하여 반복적으로 사용합니다
let secretKey = "scretkey"
let apiURL = "https://3f1iycdv15.apigw.ntruss.com/custom/v1/19260/general"
Chap3. Request , Response 모델을 Codable 형식으로 제작합니다
Request, Response를 할 때 Json 데이터가 필요하다
Swift에서는 쉽게 Json <-> Model 할 수 있는 함수를 제공한다!
Encode - 모델을 Json 데이터로 변환
Decode - Json 데이터를 모델로 변환
Encode, Decode 하기 위해서는 Codable 모델이 필요한데,
Json 데이터를 Codable 모델로 바꾸는 과정을 진행하겠습니다~
위 사이트에 json 데이터를 입력하면 자동으로 Codable 데이터로 변환해 줍니다
Request 데이터
[ Request Json ]
{
"images": [
{
"format": "png",
"name": "medium",
"data": "image64",
}
],
"lang": "ko",
"requestId": "string",
"resultType": "string",
"timestamp": {{$timestamp}},
"version": "V2"
}
[ Request Codable ]
import Foundation
struct Naver: Codable {
let images: [images]
let lang: String
let requestId: String
let timestamp: String
let version: String
}
struct images: Codable {
let format: String
let name: String
let data: String
}
Response 데이터
[ Response Json ]
{
"version": "V2",
"requestId": "string",
"timestamp": 1670386441771,
"images": [
{
"uid": "d3c3f8cc84e84e878f07474b573d0fd2",
"name": "medium",
"inferResult": "SUCCESS",
"message": "SUCCESS",
"validationResult": {
"result": "NO_REQUESTED"
},
"convertedImageInfo": {
"width": 700,
"height": 400,
"pageIndex": 0,
"longImage": false
},
"fields": [
{
"valueType": "ALL",
"boundingPoly": {
"vertices": [
{
"x": 345.0,
"y": 201.0
},
{
"x": 434.0,
"y": 120.0
},
{
"x": 463.0,
"y": 152.0
},
{
"x": 375.0,
"y": 233.0
}
]
},
"inferText": "사랑",
"inferConfidence": 0.9995,
"type": "NORMAL",
"lineBreak": true
}
}
]
}
]
}
[ Response Codable ]
import Foundation
struct Response: Codable {
let version, requestID: String
let timestamp: Int
let images: [Image]
enum CodingKeys: String, CodingKey {
case version
case requestID = "requestId"
case timestamp, images
}
}
struct Image: Codable {
let uid, name, inferResult, message: String
let validationResult: ValidationResult
let convertedImageInfo: ConvertedImageInfo
let fields: [Field]
}
struct ConvertedImageInfo: Codable {
let width, height, pageIndex: Int
let longImage: Bool
}
struct Field: Codable {
let valueType: String
let boundingPoly: BoundingPoly
let inferText: String
let inferConfidence: Double
let type: String
let lineBreak: Bool
}
struct BoundingPoly: Codable {
let vertices: [Vertex]
}
struct Vertex: Codable {
let x, y: Int
}
struct ValidationResult: Codable {
let result: String
}
Chap4. Model 을 Encode 한다
Model 을 encode 하기 전 사진 파일을 String 형식으로 바꿔야 한다
UIImage에 base64EncodedString 를 적용하면 쉽게 바꿀 수 있다!
fileprivate func changePngToString() {
if let data = image?.pngData() { // image = UIImage
let base64 = data.base64EncodedString()
image64 = base64
}
}
모든 준비가 완료되었으니 Model을 Json 형식으로 Encode 한다
fileprivate func encodeJson(){
//객체 생성
let naver = Naver(images: [images(format: "png", name: "love", data: image64)]
, lang: "ko", requestId: "string", timestamp: "0", version: "V2")
let encoder = JSONEncoder()
let jsonData = try? encoder.encode(naver)
let jsonString = String(bytes: jsonData!, encoding: .utf8)
requestBody = jsonString!
print("Encode Finish")
}
Chap5. Model을 Request 한 후 Response 데이터를 Decode 한다
네이버 url로 encode 한 json을 보내고
미리 정의 한 Response Model로 json을 파싱 한다
fileprivate func requestPost(){
encodeJson()
//URL
let url = URL(string : apiURL);
//URLRequest 생성
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue(secretKey, forHTTPHeaderField: "X-OCR-SECRET")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = requestBody.data(using: .utf8)
//POST전송
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
//에러처리
if let e = error {
NSLog("An error has occurred: \(e.localizedDescription)")
return;
}
// response status code 검증
guard let httpResponse = response as? HTTPURLResponse,
(200..<300).contains(httpResponse.statusCode) else {
print("Response error")
return
}
// data 검증 및 사용
if let data = data {
DispatchQueue.main.async {
do {
let decoder = JSONDecoder()
var result = ""
if let json = try? decoder.decode(Response.self, from: data) {
print(json.timestamp)
// field 갯수만큼 for 문 돌려서 추출
for i in 0...json.images[0].fields.count - 1{
result += json.images[0].fields[i].inferText
print(json.images[0].fields[i].inferText)
}
print("전체 결과 : ", result)
}
} catch let e as NSError {
NSLog("An error has occurred: \(e.localizedDescription)")
}
}
}
}
task.resume();
}
전체 코드
import UIKit
class NaverViewController: UIViewController{
let secretKey = "R1lLZUxIZkNtalVaU05rSkFlcHNScXF3SG1ialNyclI="
let apiURL = "https://3f1iycdv15.apigw.ntruss.com/custom/v1/19260/d965e0173ed48371cfca72258ce8dc822ede325e69df2196b5a9f3187a375ea0/general"
var image = UIImage(named: "love")
var image64: String = ""
var stringResult: String = ""
private lazy var topSafeAreaView: UIView = {
var view = UIView()
view.backgroundColor = UIColor(named: "#f8f8fa")
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let labelTitle: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.textAlignment = .center
label.text = "네이버 결과"
return label
}()
private let imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.image = UIImage(named: "love")
imageView.contentMode = .scaleAspectFit
return imageView
}()
private let lbResult: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.textAlignment = .center
label.text = ""
return label
}()
private lazy var button: UIButton = {
var button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("변환", for: .normal)
button.setTitleColor(.blue, for: .normal)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(topSafeAreaView)
topSafeAreaView.addSubview(labelTitle)
topSafeAreaView.addSubview(imageView)
topSafeAreaView.addSubview(lbResult)
topSafeAreaView.addSubview(button)
applyConstraints()
setupAction()
changePngToString()
}
// MARK: - Contstraints
fileprivate func applyConstraints() {
let topSafeAreaViewConstraints = [
topSafeAreaView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
topSafeAreaView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
topSafeAreaView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
topSafeAreaView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
]
let labelTitleConstraints = [
labelTitle.topAnchor.constraint(equalTo: topSafeAreaView.topAnchor, constant: 20),
labelTitle.leadingAnchor.constraint(equalTo: topSafeAreaView.leadingAnchor, constant: 20),
labelTitle.trailingAnchor.constraint(equalTo: topSafeAreaView.trailingAnchor, constant: -20)
]
let imageViewConstraints = [
imageView.topAnchor.constraint(equalTo: labelTitle.bottomAnchor, constant: 20),
imageView.leadingAnchor.constraint(equalTo: topSafeAreaView.leadingAnchor, constant: 20),
imageView.trailingAnchor.constraint(equalTo: topSafeAreaView.trailingAnchor, constant: -20),
imageView.heightAnchor.constraint(equalToConstant: 300)
]
let buttonConstraints = [
button.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 20),
button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
button.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)
]
let lbResultConstraints = [
lbResult.topAnchor.constraint(equalTo: button.bottomAnchor, constant: 20),
lbResult.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
lbResult.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)
]
NSLayoutConstraint.activate(topSafeAreaViewConstraints)
NSLayoutConstraint.activate(labelTitleConstraints)
NSLayoutConstraint.activate(imageViewConstraints)
NSLayoutConstraint.activate(lbResultConstraints)
NSLayoutConstraint.activate(buttonConstraints)
}
fileprivate func setupAction() {
button.isUserInteractionEnabled = true
button.addTarget(self, action: #selector(changeImageToText), for: .touchUpInside)
}
@objc func changeImageToText() {
requestPost()
}
fileprivate func requestPost(){
let naver = Naver(images: [images(format: "png", name: "1", data: image64)], lang: "ko", requestId: "string", timestamp: "0", version: "V2")
let encoder = JSONEncoder()
let jsonData = try? encoder.encode(naver)
let jsonString = String(bytes: jsonData!, encoding: .utf8)
var requestBody = jsonString!
//URL
let url = URL(string : apiURL);
//URLRequest 생성
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue(secretKey, forHTTPHeaderField: "X-OCR-SECRET")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = requestBody.data(using: .utf8)
//POST전송
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
//에러처리
if let e = error {
NSLog("An error has occurred: \(e.localizedDescription)")
return;
}
// response status code 검증
guard let httpResponse = response as? HTTPURLResponse,
(200..<300).contains(httpResponse.statusCode) else {
print("Response error")
return
}
// data 검증 및 사용
if let data = data {
DispatchQueue.main.async {
do {
let decoder = JSONDecoder()
if let json = try? decoder.decode(Response.self, from: data) {
// field 갯수만큼 for 문 돌려서 추출
for i in 0...json.images[0].fields.count - 1{
self.stringResult += json.images[0].fields[i].inferText
print(json.images[0].fields[i].inferText)
}
self.lbResult.text = self.stringResult
}
} catch let e as NSError {
NSLog("An error has occurred: \(e.localizedDescription)")
}
}
}
}
task.resume();
}
fileprivate func changePngToString(){
if let data = image?.pngData() {
let image64 = data.base64EncodedString()
}
}
}
'iOS Swift > Library, Framework 연동' 카테고리의 다른 글
[iOS/Swift] 파이어베이스 프로필 생성 Profile Firebase Auth (4) (0) | 2023.07.11 |
---|---|
[iOS/Swift] 로그인 비밀번호 재설정 로그아웃 회원탈퇴 Firebase Auth (3) (0) | 2023.07.04 |
[iOS/Swift] ios 파이어베이스 회원가입 Firebase Auth (2) (0) | 2023.06.28 |
[iOS/Swift] ios 파이어베이스 연동 Firebase Auth (1) (4) | 2023.06.20 |