[Firebase + Android + Tensorflow] tflite모델을 이용해 Camera로 찍은 사진을 분류, Firebase Cloud Storage에 Upload하기(JAVA)
- Firebase 이용하기
- Firebase Android에서 이용해보기
- Manifest 추가 Code
<uses-permission android:name="android.permission.CAMERA" />
- MainActivity 일부 Code
static final int REQUEST_IMAGE_CAPTURE = 1;
private void openCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
}
- 실행결과
→ App 실행시 후, 사진 촬영 Button Click 시 Camera가 작동됨 (Button 눌러 동작 Code 따로 구현 했음.)
- Manifest 추가 Code
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--찍은 사진 저장할려면 필요 - 추가하기-->
<meta-data
android:name="com.google.android.actions"
android:resource="@xml/file_paths" />
<!--찍은 사진 저장할려면 필요 - 추가하기-->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.android.######.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
→ ######에는 자신의 package 주소를 쓰면 된다.
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
→ resource = "@xml/file_paths" --> xml파일 안에 file_paths라고 지정된 folder에 사진 저장됨.
- res/ xml folder 생성하기
1. 위와 같은 방법으로 Directory 추가 Click
2. xml type으로 설정 후 OK
3. xml에 folder에 새로운 file_paths.xml file 생성하기
- file_paths.xml code
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="image_capture" path="Pictures/" />
</paths>
→ 이렇게 설정한 후, 밑에처럼 opencamera 코드를 수정해 주면 찍은 사진이 핸드폰에 저장되게 된다.
- MainActivity 일부 추가 Code
static final int REQUEST_IMAGE_CAPTURE = 1;
private String mPhotoFileName = null;
private File mPhotoFile = null;
private Uri imageUri;
private void openCamera() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
//1. 카메라 앱으로 찍은 이미지를 저장할 파일 객체 생성
mPhotoFileName = "IMG" + currentDateFormat() + ".jpg";
mPhotoFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), mPhotoFileName);
if (mPhotoFile != null) {
//2. 생성된 파일 객체에 대한 Uri 객체를 얻기
imageUri = FileProvider.getUriForFile(this, "com.android.######.fileprovider", mPhotoFile);
//3. Uri 객체를 Extras를 통해 카메라 앱으로 전달
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
} else
Toast.makeText(getApplicationContext(), "file null", Toast.LENGTH_SHORT).show();
}
}
→ ######에는 자신의 package 주소를 쓰면 된다.
→ 이미지 Uri를 통해서 사진을 저장하고 넘겨준다.
- 실행 결과
↑ 위의 게시물 코드 이용 예정
- Code
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// camera 사용 code 이고 result_ok일시 작동
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
// image_w /h (?,224,224,3) shape 3 -> rgb
// tflite 모델 image가 width/height 각각 224, 224 size
float[][][][] input = new float[1][224][224][3];
int batchNum = 0;
// 저장된 사진 mPhotoFile을 bitmap으로 decodeFile
Bitmap bitmap = BitmapFactory.decodeFile(mPhotoFile.getAbsolutePath());
// imageview 사진 뜨게함
image.setImageBitmap(bitmap);
for (int x = 0; x < 224; x++) {
for (int y = 0; y < 224; y++) {
int pixel = bitmap.getPixel(x, y);
input[batchNum][x][y][0] = Color.red(pixel) / 1.0f;
input[batchNum][x][y][1] = Color.green(pixel) / 1.0f;
input[batchNum][x][y][2] = Color.blue(pixel) / 1.0f;
}
}
// pass this bitmap to classifier to make prediction
List<ImageClassifier.Recognition> predicitons = imageClassifier.recognizeImage(
bitmap, 0);
// creating a list of string to display in list view
final List<String> predicitonsList = new ArrayList<>();
for (ImageClassifier.Recognition recog : predicitons) {
// 일치 확률 50% 일시 listview 작성
if (recog.getConfidence() * 100 >= 50) {
predicitonsList.add(recog.getName() + "와(과) " + recog.getConfidence() * 100 + "% 일치");
if (imageUri != null) {
/*
* firebase기반으로 한 cloud storage -> 사용자가 찍은 image를 cloud storage로 넘김
*/
// image를 cloud로 넘길때 이름
String filename = recog.getName() + recog.getConfidence() * 100 + "__" + currentDateFormat()+ ".jpg";
// image를 넘길 폴더
String foldername = recog.getName() + "/";
// reference 생성
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageRef = storage.getReferenceFromUrl("gs://#######.appspot.com").child(foldername + filename);
storageRef.putFile(imageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
// coloud storage에 image 업로드 성공시
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(getApplicationContext(), "업로드 완료!", Toast.LENGTH_SHORT).show();
Log.e("Firebase cloud storage","Upload Success!");
}
})
//실패시
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(getApplicationContext(), "업로드 실패!", Toast.LENGTH_SHORT).show();
Log.e("Firebase cloud storage","Upload Fail!");
}
})
//진행중
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
@Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
Log.e("Firebase cloud storage","Loading!");
}
});
} else {
Toast.makeText(getApplicationContext(), "파일을 먼저 선택하세요.", Toast.LENGTH_SHORT).show();
}
}
else if(recog.getConfidence() * 100 < 50){
mush_output.setText("일치하는 버섯이 존재하지 않습니다.");
}
}
// creating an array adapter to display the classification result in list view
ArrayAdapter<String> predictionsAdapter = new ArrayAdapter<>(
this, R.layout.support_simple_spinner_dropdown_item, predicitonsList);
listView.setAdapter(predictionsAdapter);
}
}
- 참조
- 실행 결과
→ 모델 잘 작동 후, folder에 사진 저장 작동
→ Cloud에 잘 저장됨.
ⓐ 사진찍은거 gallery 저장
[Tensorflow & keras] .h5 -> .pb -> .tflite 변환 오류(python) (0) | 2020.08.28 |
---|---|
[Android] imageView 사진 회전 현상 해결하기 & 사진의 절대경로명 찾기(JAVA) (4) | 2020.08.22 |
[Firebase + Android] Android App으로 Firebase Cloud Storage 이용하기(JAVA) (0) | 2020.08.09 |
[SplashActivity] How to Create a Splash Screen(Java) (0) | 2020.07.31 |
[Image] Image resize & convert(python) (0) | 2020.07.30 |