From 39af97da1ed6c54d815e6bc4fef2e57c656500b3 Mon Sep 17 00:00:00 2001 From: Alexey Date: Sun, 22 Mar 2020 17:36:43 +0400 Subject: [PATCH] design and some code clean-up --- .../CapturePhotoFragment.kt | 51 ++++++++---------- .../ImageClassification.kt | 11 ++-- .../androidProjectOnTFLite/ItemViewHolder.kt | 26 +++++++++ .../ListOfClassifiedImagesFragment.kt | 16 ++++-- .../androidProjectOnTFLite/MainActivity.kt | 5 +- .../androidProjectOnTFLite/MenuFragment.kt | 8 --- .../RecyclerViewAdapter.kt | 45 ++++++++++++++++ .../RoomDB/AppDatabase.kt | 2 - .../androidProjectOnTFLite/RoomDB/Picture.kt | 1 + .../androidProjectOnTFLite/Utils/Utils.kt | 10 +++- app/src/main/res/drawable/del.xml | 18 +++++++ app/src/main/res/drawable/pytorch_logo.png | Bin 0 -> 22916 bytes .../res/layout/fragment_capture_photo.xml | 37 +++++++------ app/src/main/res/layout/fragment_menu.xml | 47 ++++++++++------ app/src/main/res/layout/item.xml | 50 +++++++---------- app/src/main/res/values/colors.xml | 6 +-- app/src/main/res/values/strings.xml | 2 +- 17 files changed, 211 insertions(+), 124 deletions(-) create mode 100644 app/src/main/java/com/example/androidProjectOnTFLite/ItemViewHolder.kt create mode 100644 app/src/main/java/com/example/androidProjectOnTFLite/RecyclerViewAdapter.kt create mode 100644 app/src/main/res/drawable/del.xml create mode 100644 app/src/main/res/drawable/pytorch_logo.png diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/CapturePhotoFragment.kt b/app/src/main/java/com/example/androidProjectOnTFLite/CapturePhotoFragment.kt index c60e0f4..d9fb803 100644 --- a/app/src/main/java/com/example/androidProjectOnTFLite/CapturePhotoFragment.kt +++ b/app/src/main/java/com/example/androidProjectOnTFLite/CapturePhotoFragment.kt @@ -4,6 +4,7 @@ import android.app.Activity import android.content.Intent import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.graphics.drawable.BitmapDrawable import android.os.Bundle import android.provider.MediaStore import android.util.Log @@ -21,38 +22,28 @@ import java.io.ByteArrayOutputStream class CapturePhotoFragment : Fragment() { - private lateinit var camera: ImageView + private lateinit var camera: TextView private lateinit var btnCapturePhoto: Button - private lateinit var intent:Intent + private val intent= Intent(MediaStore.ACTION_IMAGE_CAPTURE) private lateinit var textClass:TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) - startActivityForResult( - intent, - CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) + startCamera() } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - - // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_capture_photo, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - - btnCapturePhoto = btn_capture_photo camera = img_view_camera textClass = text_view_class btnCapturePhoto.setOnClickListener { - startActivityForResult( - intent, - CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) + startCamera() } } @@ -68,33 +59,33 @@ class CapturePhotoFragment : Fragment() { val stream = ByteArrayOutputStream() bmp!!.compress(Bitmap.CompressFormat.PNG, 100, stream) val byteArray: ByteArray = stream.toByteArray() - // convert byte array to Bitmap val bitmap = BitmapFactory.decodeByteArray( byteArray, 0, byteArray.size ) - camera.setImageBitmap(bitmap) - textClass.text = "Loading..." + camera.text="" + camera.setBackgroundDrawable((BitmapDrawable(resources, bitmap))) + textClass.text = "Classifying..." + val imageNetClasses = ImageClassification(bitmap, context!!).objectDetection() textClass.text = imageNetClasses btnCapturePhoto.visibility=View.VISIBLE - Thread { - val imgPath = - Utils.getImagePathFromBitmap(context!!, bitmap, title = imageNetClasses) - PictureDao?.insertPicture(Picture(imageNetClasses, imgPath)) - - //textClass.text = PictureDao!!.getPictures().toString() - db?.pictureDao()?.getPictures()?.forEach() { - Log.i("Fetch Records", "Id: : ${it.id}") - Log.i("Fetch Records", "Classes: : ${it.imageNetClasses}") - Log.i("Fetch Records", "Path: : ${it.imgPath}") - } - }.start() + val imgPath = Utils.getImagePathFromBitmap(context!!, bitmap, title = imageNetClasses) + db?.pictureDao()?.insertPicture(Picture(imageNetClasses, imgPath)) + } + else { + camera.text = "" + camera.background = resources.getDrawable(R.drawable.pytorch_logo) + btnCapturePhoto.visibility = View.VISIBLE } } } - + private fun startCamera(){ + startActivityForResult( + intent, + CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) + } companion object { private const val CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 1888 } diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/ImageClassification.kt b/app/src/main/java/com/example/androidProjectOnTFLite/ImageClassification.kt index 20d64d8..66e8b0a 100644 --- a/app/src/main/java/com/example/androidProjectOnTFLite/ImageClassification.kt +++ b/app/src/main/java/com/example/androidProjectOnTFLite/ImageClassification.kt @@ -19,12 +19,11 @@ class ImageClassification(bitmap: Bitmap, context: Context) { ) public fun objectDetection(): String { - val outputTensor = module.forward(IValue.from(inputTensor)).toTensor() - val scores = outputTensor.dataAsFloatArray - val maxScoreIdx = scores.indices.maxBy { scores[it] } ?: -1 - val classNames = ImageNetClasses.IMAGENET_CLASSES[maxScoreIdx] - return classNames - } + val outputTensor = module.forward(IValue.from(inputTensor)).toTensor() + val scores = outputTensor.dataAsFloatArray + val maxScoreIdx = scores.indices.maxBy { scores[it] } ?: -1 + return ImageNetClasses.IMAGENET_CLASSES[maxScoreIdx] + } private fun loadModule(context: Context) = Module.load(Utils.assetGetAbsolutePathByName(context, "resnet18.pt")); diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/ItemViewHolder.kt b/app/src/main/java/com/example/androidProjectOnTFLite/ItemViewHolder.kt new file mode 100644 index 0000000..f5e5bcd --- /dev/null +++ b/app/src/main/java/com/example/androidProjectOnTFLite/ItemViewHolder.kt @@ -0,0 +1,26 @@ +package com.example.androidProjectOnTFLite + +import android.net.Uri +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.androidProjectOnTFLite.RoomDB.Picture + + +class ItemViewHolder(inflater: LayoutInflater, parent: ViewGroup) : RecyclerView.ViewHolder(inflater.inflate(R.layout.item, parent, false)){ + + private var classes: TextView? = null + private var photo: ImageView? = null + + init{ + classes = itemView.findViewById(R.id.classesTextView) + photo = itemView.findViewById(R.id.photo) + } + + fun bind(pic: Picture){ + photo?.setImageURI(Uri.parse(pic.imgPath)) + classes?.text = pic.imageNetClasses + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/ListOfClassifiedImagesFragment.kt b/app/src/main/java/com/example/androidProjectOnTFLite/ListOfClassifiedImagesFragment.kt index 01e69e5..a44ac88 100644 --- a/app/src/main/java/com/example/androidProjectOnTFLite/ListOfClassifiedImagesFragment.kt +++ b/app/src/main/java/com/example/androidProjectOnTFLite/ListOfClassifiedImagesFragment.kt @@ -5,18 +5,24 @@ import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.recyclerview.widget.LinearLayoutManager +import com.example.androidProjectOnTFLite.RoomDB.Picture +import kotlinx.android.synthetic.main.fragment_list_of_classified_images.* -/** - * A simple [Fragment] subclass. - */ class ListOfClassifiedImagesFragment : Fragment() { - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_list_of_classified_images, container, false) } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + recyclerView.apply{ + layoutManager = LinearLayoutManager(activity) + adapter = RecyclerViewAdapter((db?.pictureDao()?.getPictures() as MutableList?)!!) + } + + } } diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/MainActivity.kt b/app/src/main/java/com/example/androidProjectOnTFLite/MainActivity.kt index 3959987..b1f6f6d 100644 --- a/app/src/main/java/com/example/androidProjectOnTFLite/MainActivity.kt +++ b/app/src/main/java/com/example/androidProjectOnTFLite/MainActivity.kt @@ -16,10 +16,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - - //db = AppDatabase.getDatabaseInstance(this) - db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "pics-database") + db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "pics-database").allowMainThreadQueries() .build() - // val host = NavHostFragment.create(R.navigation.nav_graph) } } diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/MenuFragment.kt b/app/src/main/java/com/example/androidProjectOnTFLite/MenuFragment.kt index 74e0d08..4111cb0 100644 --- a/app/src/main/java/com/example/androidProjectOnTFLite/MenuFragment.kt +++ b/app/src/main/java/com/example/androidProjectOnTFLite/MenuFragment.kt @@ -7,16 +7,11 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.navigation.Navigation import kotlinx.android.synthetic.main.fragment_menu.* - -/** - * A simple [Fragment] subclass. - */ class MenuFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_menu, container, false) } @@ -25,7 +20,4 @@ class MenuFragment : Fragment() { toCamera.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_menuFragment_to_capturePhotoFragment)) toList.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_menuFragment_to_listOfClassifiedImagesFragment)) } - - //val navController = - } diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/RecyclerViewAdapter.kt b/app/src/main/java/com/example/androidProjectOnTFLite/RecyclerViewAdapter.kt new file mode 100644 index 0000000..25fa8bf --- /dev/null +++ b/app/src/main/java/com/example/androidProjectOnTFLite/RecyclerViewAdapter.kt @@ -0,0 +1,45 @@ +package com.example.androidProjectOnTFLite + +import android.net.Uri +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.example.androidProjectOnTFLite.RoomDB.Picture +import kotlinx.android.synthetic.main.item.view.* + +class RecyclerViewAdapter(val items: MutableList) + : RecyclerView.Adapter(){ + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) + : ViewHolder { + val v: View = LayoutInflater.from(parent.context) + .inflate(R.layout.item,parent,false) + return ViewHolder(v) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.image.setImageURI(Uri.parse(items[position].imgPath)) + holder.classes.text = items[position].imageNetClasses + holder.delete.setOnClickListener { deleteItem(position) } + } + + override fun getItemCount(): Int { + return items.size + } + + private fun deleteItem(position: Int){ + db?.pictureDao()?.delete(items[position]) //from db + items.removeAt(position) //from list + notifyItemRemoved(position) //from screen + notifyItemRangeChanged(position, itemCount) + } + class ViewHolder(itemView:View): RecyclerView.ViewHolder(itemView){ + val image: ImageView = itemView.photo + val classes: TextView = itemView.classesTextView + val delete: ImageButton = itemView.btnDelete + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/RoomDB/AppDatabase.kt b/app/src/main/java/com/example/androidProjectOnTFLite/RoomDB/AppDatabase.kt index 43d4e8b..bbf05c1 100644 --- a/app/src/main/java/com/example/androidProjectOnTFLite/RoomDB/AppDatabase.kt +++ b/app/src/main/java/com/example/androidProjectOnTFLite/RoomDB/AppDatabase.kt @@ -4,7 +4,6 @@ import android.content.Context import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase -import androidx.room.TypeConverters @Database( entities = [Picture::class], @@ -12,7 +11,6 @@ import androidx.room.TypeConverters exportSchema = false ) - abstract class AppDatabase : RoomDatabase() { abstract fun pictureDao(): PictureDao? diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/RoomDB/Picture.kt b/app/src/main/java/com/example/androidProjectOnTFLite/RoomDB/Picture.kt index 401b5d8..aefac9f 100644 --- a/app/src/main/java/com/example/androidProjectOnTFLite/RoomDB/Picture.kt +++ b/app/src/main/java/com/example/androidProjectOnTFLite/RoomDB/Picture.kt @@ -1,5 +1,6 @@ package com.example.androidProjectOnTFLite.RoomDB +import android.net.Uri import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey diff --git a/app/src/main/java/com/example/androidProjectOnTFLite/Utils/Utils.kt b/app/src/main/java/com/example/androidProjectOnTFLite/Utils/Utils.kt index 52ea7d7..51c3f5f 100644 --- a/app/src/main/java/com/example/androidProjectOnTFLite/Utils/Utils.kt +++ b/app/src/main/java/com/example/androidProjectOnTFLite/Utils/Utils.kt @@ -1,6 +1,11 @@ package com.example.androidProjectOnTFLite.Utils + +import android.content.ContentValues.TAG import android.content.Context +import android.database.Cursor import android.graphics.Bitmap +import android.net.Uri +import android.os.Environment import android.provider.MediaStore import android.util.Log import java.io.ByteArrayOutputStream @@ -8,10 +13,9 @@ import java.io.File import java.io.FileOutputStream import java.io.IOException import java.text.SimpleDateFormat -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter import java.util.* + object Utils { fun assetGetAbsolutePathByName(context: Context, assetName: String): String? { val file = File(context.filesDir, assetName) @@ -32,6 +36,7 @@ object Utils { } return null } + fun getImagePathFromBitmap(context: Context, bitmap: Bitmap, title: String = "Title", description: String? = null): String { val bytes = ByteArrayOutputStream() val sdf = SimpleDateFormat("-dd.MM.yyyy.HH-mm-ss") @@ -39,4 +44,5 @@ object Utils { bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes) return MediaStore.Images.Media.insertImage(context.contentResolver, bitmap, fileName, description) } + } \ No newline at end of file diff --git a/app/src/main/res/drawable/del.xml b/app/src/main/res/drawable/del.xml new file mode 100644 index 0000000..60e64c5 --- /dev/null +++ b/app/src/main/res/drawable/del.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/drawable/pytorch_logo.png b/app/src/main/res/drawable/pytorch_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bad49bf30b4afe5bb34f76d73a03e39fc48bbedb GIT binary patch literal 22916 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 Nkbkh>g=Oo~{{W#u9;5&O literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/fragment_capture_photo.xml b/app/src/main/res/layout/fragment_capture_photo.xml index 8fecd5b..e97d72b 100644 --- a/app/src/main/res/layout/fragment_capture_photo.xml +++ b/app/src/main/res/layout/fragment_capture_photo.xml @@ -1,36 +1,41 @@ - + android:layout_marginTop="5dp" + android:textAlignment="center" + android:textSize="20sp" + app:layout_constraintTop_toTopOf="parent" /> - - - - - + android:layout_height="450dp" + android:layout_marginTop="5dp" + android:layout_marginBottom="5dp" + android:gravity="center" + android:text="Loading\n..." + android:textSize="60sp" + app:layout_constraintBottom_toTopOf="@+id/btn_capture_photo" + app:layout_constraintTop_toBottomOf="@+id/text_view_class" + tools:layout_editor_absoluteX="-16dp" />