본문 바로가기

JAVA

OpenCV UI 오브젝트 검출

SIFT FLANN BASED MATCHING

 

개발 환경은 아래와 같다.

  • OpenCV 4.2 (Built for Android with NONFREE)
  • Android 10

내가 검출하고자 하는 데이터는 실제(Real Object)가 아니고 안드로이드의 Display에서 특정 UI 컴포넌트를 검출하는 작업이 필요했다.

 

먼저 시도한 방법은 OpenCV의 TemplateMatching.

하지만 여러 디바이스 환경에서의 UI 컴포넌트의 사이즈와 변형(반응형 디자인)으로 인해 TemplateMatching의 특성상 검출하려는 오브젝트의 크기가 검출 대상 소스에서의 크기는 같아야 하고 Multi-scaling의 방식이나 MatPyramid 등 다양한 scale-case 를 반영해도 변형된 데이터에서는 검출이 힘들었다.

 

그래서 시도해본 것은 SURF, SIFT 그리고 ORB.

 

그 중에서 내가 검출하려는 대상에서 최고의 성능과 결과를 보여준 SIFT.

 

하지만, Find-Object에서 시행한 결과와 JAVA(Kotiln)로 작성한 결과가 매우 상이하며 정확도가 현저히 떨어졌다. 그래서 Find-Object의 소스코드를 참고하여 어떤 방식으로 오브젝트를 검출하는지 알아보기로 했다.

 

 

 

1. findHomography의 Mask를 통한 inlier와 outlier 구분.

val l = ArrayList<Double>()

for (idx in 0..outMask.rows()) {
  if (outMask.get(idx, 0) != null && outMask.get(idx, 0)[0] > 0.0)
  	l.add(outMask.get(idx, 0)[0])
}

findHomography에 mask를 이용해여 inlier을 구분하는 예.

반대로 outlier는 위 조건에 부합하지 않는 데이터이다. 주의해야할 것은 inlier, outlier의 데이터를 추출하고자 하면 DescriptorMatcher에서 계산된 매칭 데이터에 접근하여 데이터를 추출하도록 해야 한다.

 

하지만 부족하다... inlier의 최솟값을 지정해도 이는 약간의 데이터 변경만으로도 허용범위를 벗어나 버린다..

 

 

 

2. Inverted Search (Find-Object WIKI)

 

Inverted Search 즉, Object를 Scene에 비교하는 것이 아니고, Scene에 Object를 비교하는 방식이다.

정확하게 어떠한 알고리즘으로 작동하는지는 상단 링크를 통해 살펴보고 코드도 리뷰해보길 바란다...

 

검출할 Object들을 모두 미리 detect 해서 추출된 descriptors를 나열해 놓은 곳에 Scene을 비교하는 것.

 

Find-Object의 WIKI에 따르자면..

we create a vocabulary from all the objects' descriptors and we match scene's descriptors to this vocabulary. It is the inverted search mode.

검출 대상의 descriptor를 통해 vocabulary를 생성하고, scene의 descriptors를 vocabulary에 비교한다.

 

 

아무튼 나는 Kotlin(Android)로 앱을 작성 중이기 때문에 해당 Vocabulary와 검출하는 방식 등을 그대로 포팅하여 테스트해보았는데 생각보다 구현 자체는 어렵지 않았다. Java Wrapper API와 C++ API가 매우 상이한 점이 큰 걸림돌이 었긴 하다.

 

나중에 코드가 어느 정도 정리되면 Inverted Search 기능만 추출한 Kotlin 예를 첨부해보도록 하겠다.

 

 

 

3. Object Angle

 

검출된 Object 프로젝션(Homogrpahy로 변형된 Rect)의 내각들을 검사하여 비교.

우선 필자의 경우에는 UI 컴포넌트들을 추출하기 때문에 각 Angle들이 70~120도 사이에 위치해야 올바른 인식이라고 판단하기 때문에 모든 내각들을 검사하여 Angle에 따라 필터링해준다.

 

폴리곤의 내각 구하기

 

4. Overlapped

 

UI 컴포넌트의 특성상 Features의 수가 적고, 글자 하나의 다른 점으로써 중복 검출 인식, 즉 [ABCD]라는 버튼과 [ABCC]라는 버튼이 [ABCD]라는 대상으로의 검출이 될 수 있다.

 

검출된 Rect들을 대상으로 서로 겹쳐있는지 확인 후 겹친 Rect들 중 Score가 높은 쪽 (보통은 Inlier의 개수)을 살려주는 알고리즘이 필요하다.

 

이 경우에 보통 Rectangle이 아니고 Quadrilateral 이기에 계산에는 특별한 알고리즘이 필요하다. (필자의 경우에는 두 개의 Polygon의 Intersection을 구한 후 Intersection이 하나의 Polygon에 얼마큼의 영역을 포함하고 있는지 계산했다.)

 

 

 

 

5. ROI(Region of interest) 설정

 

UI라는 특성상 비슷하고 난잡한 장면에 대해서 오류를 피하고자 오브젝트가 위치할만한 곳을 ROI를 설정해준다.

 

우선 ROI를 찾는 것도 문제인데, 필자의 경우에는 해당 UI 컴포넌트들의 장소가 스크린 사이즈의 특정 division에 항상 위치한다는 점을 이용해 ScreenWidth , ScreenHeight를 적절하게 나누어 ROI값을 설정해주었다.

 

이 경우 특정 조건에서는 일부 검출이 필요한 컴포넌트를 잘라내는 경우가 있을 수 있으니 적절한 ROI설정이 필수겠다.