(Amazon Rekognition 이미지(nodejs)에서 텍스트 감지) https://sssbin./185
이번에는 Android에서 Rekognition API를 사용해 봅니다.
(사실 1년전에 했던 프로젝트인데…)
사용자가 카메라로 사진을 찍으면 S3 버킷에 업로드하고 Rekognition 수행 결과를 반환합니다.
AWS 설정
– IAM 계정, 새로운 S3 버킷(위 링크 참조)
– Amazon Cognito 자격 증명 풀 생성
– 로그인 기능 X -> 인증되지 않은 자격 증명에 대한 액세스 활성화(Unauth)
– 인지 역량 강화
– IAM > 역할 > Cognito 자격 증명 풀 생성 시 생성된 역할 선택(비인증) > 권한 추가
– IAMFullAccess, AmazonS3FullAccess, AmazonRekognitionFullAccess, AdministratorAccess
프로젝트 설정
build.gradle(app) -> 의존성 추가
implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.13.5'
implementation 'com.amazonaws:aws-android-sdk-cognito:2.13.5'
implementation 'com.amazonaws:aws-android-sdk-s3:2.13.5'
매니페스트 -> 권한 부여, 서비스 추가
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
...
<service android:name="com.amazonaws.mobileconnectors.s3.transferutility.TransferService" android:enabled="true"/>
...
</application>
코드
– Amazon Cognito 인증 공급자, S3 객체 설정
– 카메라 -> 이미지 파일 생성 -> URI 생성 -> S3 버킷에 업로드
-> Rekognition 클라이언트 객체 생성 -> DetectText 요청
package kr.co.company.canfindcan;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import com.amazonaws.auth.CognitoCachingCredentialsProvider;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferListener;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferObserver;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferState;
import com.amazonaws.mobileconnectors.s3.transferutility.TransferUtility;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.rekognition.AmazonRekognition;
import com.amazonaws.services.rekognition.AmazonRekognitionClient;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.services.rekognition.model.DetectTextRequest;
import com.amazonaws.services.rekognition.model.DetectTextResult;
import com.amazonaws.services.rekognition.model.Image;
import com.amazonaws.services.rekognition.model.S3Object;
import com.amazonaws.services.rekognition.model.TextDetection;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class RekogActivity extends AppCompatActivity {
private final static String TAG = "CANFINDCAN";
public final static String PREFS_NAME = "MyPrefsFile";
static final int REQUEST_IMAGE_CAPTURE = 1;
static final int REQUEST_TAKE_PHOTO = 1;
String mCurrentPhotoPath;
private FrameLayout capture;
File img;
AmazonS3 s3;
TransferUtility transferUtility;
CognitoCachingCredentialsProvider credentialsProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rekog);
capture = (FrameLayout) findViewById(R.id.capture);
// Amazon Cognito 인증 공급자 설정
credentialsProvider = new CognitoCachingCredentialsProvider(
getApplicationContext(),
"------", // 자격 증명 풀 ID
Regions.AP_NORTHEAST_2 // 리전
);
// s3 클라이언트 설정
s3 = new AmazonS3Client(credentialsProvider);
transferUtility = new TransferUtility(s3, getApplicationContext());
s3.setRegion(Region.getRegion(Regions.AP_NORTHEAST_2));
s3.setEndpoint("s3.ap-northeast-2.amazonaws.com");
// 카메라 버튼
capture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dispatchTakePictureIntent();
}
});
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) !
= null) {
File photoFile = null;
try {
// 이미지 파일 생성
photoFile = createImageFile();
} catch (IOException ex) {
Log.e("ERROR", ex.getMessage(), ex);
// 사진 촬영 실패
}
if (photoFile !
= null) {
// URI 생성
img = photoFile;
Uri photoURI = FileProvider.getUriForFile(this,
"kr.co.company.canfindcan.fileprovider", // "패키지명.fileproivder"
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
} else {
// 사진 촬영 실패
}
}
}
private File createImageFile() throws IOException {
Log.i(TAG, "Creating image file");
String imageFileName = "can_images";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
Log.i(TAG, "Image created and returned");
return image;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
// 이미지 파일 & URI 생성 -> request 성공적이면 -> S3 버킷에 업로드
upload();
}
}
public void upload() {
String imgName = "uploadImg";
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("curImg", imgName);
editor.commit();
if (img == null) {
Log.i("ERROR", "The file is empty");
} else {
TransferObserver observer = transferUtility.upload(
"------", // The bucket to upload to
"upload_test.jpg", // The key for the uploaded object
img, // 위에서 생성한 이미지 파일 객체
CannedAccessControlList.PublicRead
);
observer.setTransferListener(new TransferListener() {
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
Log.i(TAG, "progress changed");
}
public void onStateChanged(int id, TransferState state) {
if (state == TransferState.COMPLETED) {
Log.i(TAG, "state changed");
DetectText(); // 텍스트 감지 (Rekognition)
}
}
public void onError(int id, Exception ex) {
Log.e("ERROR", ex.getMessage(), ex);
// 오류 발생
}
});
}
}
public void DetectText() {
String photo = "upload_test.jpg"; // The key for the uploaded object
String bucket = "------"; // The bucket to upload to
AWSCredentials cre = new AWSCredentials() {
// IAM 계정 생성할 때 받은 키 넣어주기
@Override
public String getAWSAccessKeyId() {
return "------";
}
@Override
public String getAWSSecretKey() {
return "------";
}
};
// RekognitionClient 객체 생성
AmazonRekognition rekognitionClient = new AmazonRekognitionClient(cre);
rekognitionClient.setRegion(Region.getRegion(Regions.AP_NORTHEAST_2));
// 요청 객체(?)
DetectTextRequest request = new DetectTextRequest()
.withImage(new Image()
.withS3Object(new S3Object()
.withName(photo)
.withBucket(bucket)));
String res =""; // 텍스트 결과값
// DetectText 요청
try {
AsyncTask<DetectTextRequest,Void,String> asyncTask = new AsyncTask<DetectTextRequest, Void, String>() {
@Override
protected String doInBackground(DetectTextRequest... detectTextRequests) {
DetectTextResult result = rekognitionClient.detectText(request);
List<TextDetection> textDetections = result.getTextDetections();
System.out.println("Detected lines and words for " + photo);
String res="";
for (TextDetection text: textDetections) {
if (text.getId() == 0) { // 원하는 값만 얻으려면 첫번째 줄만 필요함.
res = text.getDetectedText();
break;
}
}
return res;
}
};
// 텍스트 감지 결과값 !
!
!
!
res = asyncTask.execute(request).get();
}catch (Exception e){
System.out.println(e);
// 텍스트 감지 실패 !
!
!
!
}
}
}
그게 다야..
공식 문서에 제공된 코드는… 지원되지 않아서 당황스럽네요
텍스트 감지 결과는 res에 저장되므로 이제 원하는 대로 사용할 수 있습니다.