Framework/OpenCV

[OpenCV] 안드로이드에서 속도 개선해보기

깜태 2023. 9. 21. 19:41
728x90

최근에 안드로이드와 iOS에서 openCV를 사용할 일이 생겼다.

환경설정까지는 다른 분께서 해주셔서 큰 신경 쓰지 않고,

바뀐 언어 환경에서 같은 로직을 적용해본 결과 생각보다 느렸다.

오랜만에 급하게 하다가 깜빡한 게 생각나서 기록하는 겸,

왜 느려졌는지 그 이유와 개선방법에 대해서 적어보려고 한다.

 

먼저 로직을 간단하게 적어보자면 이렇다.

- 이미지를 받아온다.

- ROI 관심영역을 추출한다.

- 추출한 영역 내에서 픽셀마다 값을 변경한다.

- 변경된 이미지를 내보낸다.

 

openCV를 써본 사람이면 아주 쉽게 접하는 일이다.

안드로이드에서 간단하게 예시를 보여주자면 이렇다.

val src = Mat() //grayScale 이라고 가정
val dest = Mat()

for(rowIdx: Int in 0 until src.rows()) {
	for(colIdx: Int in 0 until src.cols()){
    	var pixel = dest.get(rowIdx, colIdx)
    	dest.put(rowIdx, colIdx, pixel-100)
    }
}

 

 

코드상으로 보았을 땐 별 문제 없이 깔끔해보이지만, 속도는 처참하다.

영역이 더 커질수록 더 느려진다. 왜그럴까??

그 이유는 라이브러리를 너무 많이 호출했기 때문이다.

라이브러리 호출이 많은 게 왜 느려질까??

자바 쪽에서는 JNI(Java Native Interface)라고 하여 JVM위에서 실행되는 코드가

다른 언어들로 작성된 라이브러리를 호출할 때 사용되는 인터페이스가 있다.

위의 절차대로 안드로이드에서 OpenCV를 호출한다는 것은

Android -> JNI -> OpenCV 의 절차를 거친다는 것이다.

픽셀 단위로 적용하면 라이브러리를 호출 횟수는 Row * Col 이 되면서 무수히 많은 전달과정이 생기며 느려진다.

 

그렇다면 위의 코드는 꼭 OpenCV를 써야만 할까??

openCV의 Mat을 선언할 때 내부동작을 이해해보면

- Row * Col 크기의 바이트를 할당하고

- put, get과 같은 메소드제공하는 것으로,

- 덕분에 한줄의 코드로 인해 코드 길이 줄었고,

- 사람이 이해하는 행렬 방식으로 직관적이고 편리하게 작업할 수 있도록 도와준다.

 

하지만 위의 코드를 기준으로 핵심 로직은 픽셀마다 간단한 산술연산만 해주면 되는 작업인데,

굳이 openCV의 Mat 타입으로 변경해가면서 오버헤드를 가져갈 필요가 없고,

내부 동작 부분을 똑같이 Android 상에서 처리할 수 있다.

 

val src = Mat() //GRAY 예시(8UC1)
val srcValues = IntArray(src.total().toInt())

//srcValues 에 복사

// srcValues에서 계산
for(rowIdx: Int in 0 until src.rows()) {
    for(colIdx: Int in 0 until src.cols()){
        srcValues[rowIdx*src.cols() + colIdx] -= 100
    }
}
src.put(0,0, srcValues)

 

이런 방식으로 보면 내용상으로는 같지만 openCV는 불러올 때와 다시 할당할 때만 사용하여

과도한 openCV 호출을 방지해 오버헤드를 줄일 수 있다.

 

이렇게 간단한 예시를 들었지만,

openCV 라이브러리를 과하게 호출되는 것 같다면

오버헤드를 덜어내기 위해 네이티브 코드를 사용하자는 게 핵심이다.

 

다른 방법으로는 CUDA와 같은 GPU 기반의 병렬처리를 이용하는 것도 방법도 있긴 하다.

 

결론

openCV 라이브러리를 적당히 쓰자 (알잘딱깔센)

 

 

참고

https://velog.io/@vrooming13/JNI-JAVA-Native-Interface

https://developer.android.com/training/articles/perf-jni?hl=ko 

http://mcs.csueastbay.edu/~grewe/CS6825/Mat/OpenCV/speed/speed.html

728x90