DEEP.I - Lab

오프라인 공간의 지능화를 꿈꾸는 딥아이 연구실입니다.

Kotlin

[Kotlin] 라이브러리를 이용하여 실시간 그래프 그리기

Jongwon Kim 2020. 6. 25. 11:56
반응형

안드로이드 라이브러리를 이용한 꺽은선 그래프 그리기



프로젝트로 안드로이드 환경에서 간단한 기계학습 알고리즘을 구현하고 있습니다. 반복 학습을 하며 오차가 감소하는지 실시간으로 그래프로 활용하기 위해 MPAndroidChart 라이브러리를 활용하였습니다. 대학원 시절, 매트랩 코드로 쉽게 구현했던 그래프를 kotlin으로 표현하려니... 어렵네요..


출처: https://github.com/PhilJay/MPAndroidChart



1. Module/Grandle 라이브러리 적용


우선, 라이브러리 사용을 위해 Module 수준의 Grandle에 코드를 추가해주어야합니다. 이후에는 꼭 상단에 뜨는 파란색 팝업의 Sync Now를 통해 라이브러리를 실제 앱에 적용시켜주세요.


repositories {
maven { url "https://jitpack.io" }
}

dependencies {
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.2'
}


 

2. chart.xml - 레이아웃 설정


레이아웃은 그래프가 표현될 LineChart와 실시간 그래프 시작을 위한 Button으로 구성하였습니다. 사용환경에 맞춰 변경해주시면 됩니다.


<?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=".ChartActivity">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/lineChart"
android:layout_width="match_parent"
android:layout_height="500dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/startButton"/>
<Button
android:id="@+id/startButton"
android:text="그래프 TEST"
android:layout_width="match_parent"
android:layout_height="00dp"
app:layout_constraintTop_toBottomOf="@id/lineChart"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>



3. ChartActivity.kt - 실시간 그래프 구현을 위한 Thread 설정


메인 Class에서 그래프를 실시간으로 구현하게 될 경우, 안드로이드는 UI와 연산을 동시에 수행하지 못하므로 유연한 앱 환경구성이 어렵게 됩니다.그래프의 변화되는 값을 실시간으로 표현하기 위해서는 외부 Thread를 설정해야합니다.

무작위로 값을 생성한 뒤, 그래프로 확인하기 위해 Math.random() 함수로 배열을 초기화하였습니다. 또한 버튼을 클릭할때마다 중복해서 Thread가 생성되고 그래프가 그려지는것을 방지하기 위해 isrunning 변수로 제어하였으며 버튼 클릭 시 isClickable를 통해 클릭을 비활성화하였습니다.


class ChartActivity : AppCompatActivity() {

var isrunning = false

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.chart)

startButton.setOnClickListener {
if (isrunning == false) {
isrunning = true
startButton.text = "그래프 구현중"
startButton.isClickable = false
val thread = ThreadClass()
thread.start()
}
}
}

inner class ThreadClass : Thread() {
override fun run() {
val input = Array<Double>(200,{Math.random()})


// 그래프 초기값 설정은 이곳에 //

for (i in 0 until input.size){ // 그래프 표현식은 이곳에 //


}
}
}
}



4. ChartActivity.kt / ThreadClass - 그래프 초기값 및 구현 설정


다소 복잡합니다. 저는 코틀린 전문가가 아니기때문에 이러한 변수 생성과 삽입이 반복되어야 하는지 의문이지만 개발자가 그렇다면 그런거겠죠.. 절차대로 변수를 선언하고 입력해주시면 됩니다.


- 그래프 입력 데이터 선언 -

1. Entry 배열을 생성한다. 

2. 초기 그래프 구현을 위해 초기값을 입력한다.

3.생성된 Entry 배열을 LineDataSet 배열의 원소로 입력한다.

4.생성된 LineDataSet 배열을 LineData 배열의 원소로 입력한다.

5. 레이아웃과 데이터 연결


- 메인 UI에 초기 그래프 생성 -

runOnUiThread을 통해 메인 UI에 접근한 뒤, animateXY를 통해 그래프를 구현합니다.


- 메인 UI에 실시간 그래프 업데이트 -

실시간 구현을 위해 for문 내부에 data.addEntry 함수를 불러와 업데이트된 데이터를 입력해줍니다. 이후, 리사이클뷰나 뷰페이저와 같이 데이터 갱신을 위해 notifyDataSetChanged 함수를 선언하게 되면 그래프 세팅이 완료됩니다. for문이 종료되면 다시 startButton을 활성화 해줍니다.



inner class ThreadClass : Thread() {
override fun run() {
val input = Array<Double>(100,{Math.random()})
// Entry 배열 생성
var entries: ArrayList<Entry> = ArrayList()
// Entry 배열 초기값 입력
entries.add(Entry(0F , 0F))
// 그래프 구현을 위한 LineDataSet 생성
var dataset: LineDataSet = LineDataSet(entries, "input")
// 그래프 data 생성 -> 최종 입력 데이터
var data: LineData = LineData(dataset)
// chart.xml에 배치된 lineChart에 데이터 연결
lineChart.data = data

runOnUiThread {
// 그래프 생성
lineChart.animateXY(1, 1)
}

for (i in 0 until input.size){

SystemClock.sleep(10)
data.addEntry(Entry(i.toFloat(), input[i].toFloat()), 0)
data.notifyDataChanged()
lineChart.notifyDataSetChanged()
lineChart.invalidate()
} startButton.text = "난수 생성 시작" startButton.isClickable = true

isrunning = false

}
}



5. 최종 결과 및 다층 신경망 오차 함수 그래프 응용

     






# 머신러닝 프로젝트 제작, 상담 및 컨설팅  / 머신러닝 접목 졸업작품 컨설팅

# 데이터 가공, 수집, 라벨링 작업 / C, 파이썬 프로그램 제작

# email : deepi.contact.us@gmail.com

# site : www.deep-i.net

반응형