MainActivity
아래의 모든 코딩은 class MainActivity : AppCompatActivity()의 TODO에서 진행한다.
class MainActivity : AppCompatActivity() { // TODO }
기본 설정
activity_main과 연결하기
모든 안드로이드 코딩의 시작이다.
findViewByID로 view와 MainActivity의 모든 성분을 연결한다.
private val imageView: ImageView by lazy {
findViewById<ImageView>(R.id.imageView)
}
private val leftButton: AppCompatButton by lazy {
findViewById<AppCompatButton>(R.id.leftButton)
}
private val rightButton: AppCompatButton by lazy {
findViewById<AppCompatButton>(R.id.rightButton)
}
Asset
Asset 함수를 만들어 gray로 변경할 이미지를 미리 넣어준다.
추후 이름을 유지하며 갤러리 내 이미지를 붙여넣는 방식으로 원하는 이미지를 흑백으로 바꿔보려고 한다.
폴더 설정
file - new - folder - assets folder
를 통해 asset 폴더를 생성한다.
그럼 이렇게 assets 함수가 추가되게 된다.
해당 assets 폴더에 미리 이미지 10개를 추가한다.
img_xxxx의 형태로 이미지를 추가했다.
참고로 assets 폴더는
오른쪽 클릭 - Show in Explorer
를 통해 바로 윈도우 창으로 열 수 있다.
Gradle 압축 방지
png 파일 압축 방지를 위해 build.gradle내에 아래 code를 추가한다.
android {
...
aaptOptions {
noCompress 'png'
}
}
Assets 폴더 내 파일 불러오기
setImage
setImage 함수를 만들어 assets 내 이미지를 불러온다.
num은 보여질 수 있는 이미지의 개수를, index는 현재 show하는 이미지의 index를 의미한다.
private val num: Int = 10
private var index: Int = 0
private lateinit var bitmap: Bitmap
private fun setImage(index: Int) {
val inputStream: InputStream
var image = Mat()
val name: String = "img_" + String.format("%04d", index) + ".png"
Log.d("MainActivity", "name : $name") // name 확인을 위한 출력
inputStream = assets.open(name) // name에 해당하는 파일 open
bitmap = BitmapFactory.decodeStream(inputStream)
Utils.bitmapToMat(
bitmap,
image
)
// Gray 이미지 변경 과정 진행
image = getGrayImage(image)
Utils.matToBitmap(image, bitmap)
// view에 이미지를 설정한다.
imageView.setImageBitmap(bitmap)
}
cvtColor는 이미지를 흑백으로 변경한다.
그럼 이제 이런 식으로 이미지가 출력되는 것을 볼 수 있다.
Button으로 이미지 교체
Button에 따른 num 변환 (MainActivity.kt)
left, right 버튼이 클릭될 때 마다 이제 num을 변경하며 다른 이미지를 출력해보겠다.
global value index가 현재 이미지의 번호를 나타내므로
left 버튼이 눌릴 때 index--를, right 버튼이 눌릴 때 index++를 진행한다.
이때 범위 내 이미지만을 출력해야 하므로 아래와 같이 에러 방지를 진행한다.
fun getLeftButton(view: View) {
index--
if(index < 0) {
Toast.makeText(this, "첫번째 이미지입니다.", Toast.LENGTH_SHORT).show()
index = 0
}
Log.d("MainActivity", "index : $index")
setImage(index)
}
fun getRightButton(view: View) {
index++
if(index >= num) {
Toast.makeText(this, "마지막 이미지입니다.", Toast.LENGTH_SHORT).show()
index = num - 1
}
Log.d("MainActivity", "index : $index")
setImage(index)
}
Button에 따른 num 변환 (activity_main)
setOnClickListner를 사용해도 되지만 쉬운 사용을 위하여 xml 내 adroid:onClick 을 통해 바로 함수를 불러와 실행한다.
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/leftButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="#40000000"
android:onClick="getLeftButton"
android:text="left"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/rightButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="#40000000"
android:onClick="getRightButton"
android:text="right"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
onCreate
첫 이미지 초기화
마지막으로 처음 화면이 실행될 때 이미지 초기화도 해야하므로 onCreate 함수 내에 setImage(index) 함수를 추가한다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setImage(index)
}
Result
이와 같이 진행한다면 left, right 값에 따라 이미지가 변하는 App을 만들 수 있다.
현재는 가장 쉬운 GrayScale로 이미지를 출력했지만 SIFT, Gaussian Blur 등 다양한 양상으로 Asset 내 이미지를 변경해 볼 수 있다.
마무리
아무래도 첫 글이라 많이 어렵고 중구난방이었던 것 같다...
누가 이 글을 읽을지는 모르겠지만 정리가 잘 되어있지 않아 많이 미안하다.
조금 모듈화하여서 조금씩 많이 올리는 방안을 생각해보아야 할 것 같다.
전체 code
activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/leftButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="#40000000"
android:onClick="getLeftButton"
android:text="left"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/rightButton"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:background="#40000000"
android:onClick="getRightButton"
android:text="right"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity
package edu.android.project.opencv_kotlin_test
class MainActivity : AppCompatActivity() {
companion object {
// Used to load the 'native-lib' library on application startup.
init {
if(!OpenCVLoader.initDebug()){
Log.d("MainActivity", "OpenCV is not loaded!")
} else {
Log.d("MainActivity", "OpenCV is loaded successfully!")
}
System.loadLibrary("native-lib")
}
}
private val imageView: ImageView by lazy {
findViewById<ImageView>(R.id.imageView)
}
private val leftButton: AppCompatButton by lazy {
findViewById<AppCompatButton>(R.id.leftButton)
}
private val rightButton: AppCompatButton by lazy {
findViewById<AppCompatButton>(R.id.rightButton)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setImage(index)
}
private val num: Int = 10
private var index: Int = 0
private lateinit var bitmap: Bitmap
private fun setImage(index: Int) {
val inputStream: InputStream
var image = Mat()
val name: String = "img_" + String.format("%04d", index) + ".png"
Log.d("MainActivity", "name : $name") // name 확인을 위한 출력
inputStream = assets.open(name) // name에 해당하는 파일 open
bitmap = BitmapFactory.decodeStream(inputStream)
Utils.bitmapToMat(
bitmap,
image
)
// Gray 이미지 변경 과정 진행
image = getGrayImage(image)
Utils.matToBitmap(image, bitmap)
// view에 이미지를 설정한다.
imageView.setImageBitmap(bitmap)
}
private fun getGrayImage(img: Mat): Mat {
Imgproc.cvtColor(img, img, Imgproc.COLOR_RGB2GRAY)
return img
}
fun getLeftButton(view: View) {
index--
if(index < 0) {
Toast.makeText(this, "첫번째 이미지입니다.", Toast.LENGTH_SHORT).show()
index = 0
}
Log.d("MainActivity", "index : $index")
setImage(index)
}
fun getRightButton(view: View) {
index++
if(index >= num) {
Toast.makeText(this, "마지막 이미지입니다.", Toast.LENGTH_SHORT).show()
index = num - 1
}
Log.d("MainActivity", "index : $index")
setImage(index)
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
external fun stringFromJNI(): String
}
'IT > Android' 카테고리의 다른 글
[OpenGL ES] Android NDK 환경에서 glm 라이브러리 사용하기 (0) | 2021.09.01 |
---|---|
[Android] kotlin으로 NDK 환경 FAST keypoint detetion (0) | 2021.08.03 |
[Android] Android으로 OpenCV 사용하기 - 2 (0) | 2021.08.03 |
[Android] Android으로 OpenCV 사용하기 - 1 (0) | 2021.08.03 |