[컴퓨터비전]이미지 변환시 DoF(Degrees of Freedom)에 대한 고찰

공대생의 팁 2015. 10. 13. 00:13

 영상처리와 컴퓨터비전 분야에서 가장 중요한 요소로 Matrix 변환을 기반으로 하는 선형대수(Linear Algebra)가 있습니다. 특히 화면에 나타나는 이미지를 변환할 때 (Geometric Transformations를 하기 위해 사용되는 행렬), DoF라는 개념이 언급됩니다. 본 포스팅에서는 이 DoF에 대해 이야기해 보려 합니다.


-DoF(Degrees of Freedom)란?

 DoF(Degrees of Freedom), 우리말로 '자유도'라 일컫는 요소로 이미지가 변환이 될 때 최소한으로 필요로 하는 독립변수의 수라고 정의할 수 있습니다. 이에 대해 각 Geometric Transformations들을 통해 알아보도록 하겠습니다.


-Translation


 이미지 변환중 가장 단순하다고 할 수 있는 변환 중 하나입니다. 이를 Matrix로 나타내면 다음과 같습니다.


위의 식에서 보이는 바와 같이 총 2개의 변수에 의해 이미지가 변환되고 있는 것을 알 수 있습니다. 각 변수는 이미지의 x축과 y축을 이동하는 식으로서 이는 Translation의 DoF가 2임을 알 수 있습니다.

 또한 Translation의 결과물은 원본 이미지에서 큰 변화가 일어나지 않습니다.


-Rigid(Euclidean)

위에서 보았던 Translation을 수행한 후 이미지를 일정 각도로 회전시킨 결과입니다. 이를 Matrix로 나타내면 다음과 같습니다.


위의 식에서 보는 바와 같이 x축으로의 이동, y축으로의 이동, 회전각도 Θ로 DoF는 3임을 알 수 있습니다.

 위 Rigid의 최종 결과물은 원본 이미지의 높이 및 너비와 같은 길이가 보존되는 것을 알 수 있습니다.


-Similiary

위의 Rigid Transform에서 결과물의 사진 크기가 변하였음을 확인할 수 있습니다. 이를 Matrix로 나타내면 다음과 같습니다.


 위의 식에서 보는 바와 같이 x축으로의 이동, y축으로의 이동, 회전각Θ, 크기변수s 로 DoF는 4임을 알 수 있습니다.

 위 Similary의 최종 결과물은 원본 이미지의 직각 부분이 유지되는 것을 알 수 있습니다.


-Affine

원본 이미지에 Affine Matrix가 적용되면 이미지가 위에서 보는 바와 같이 일그러진 모습을 하고 있는 것을 보실 수 있습니다. 이를 Matrix로 나타내면 다음과 같습니다.


Affine Matrix의 DoF는 6임을 확인하실 수 있습니다.

 위 Affine의 최종 결과물은 원본 이미지의 두 변의 평행이 보존됨을 확인하실 수 있습니다.


-Projective

 원본이미지에 Projectiive가 젹용되면 마치 이미지가 정사영에 투영된 듯이 이미지를 기울여서 보는 듯한 느낌이 들 겁니다. 이를 Matirx로 나타내면 다음과 같습니다.


Projective Matrix의 DoF는 8임을 알 수 있습니다.

 위 Projective의 최종 결과물은 원본 이미지의 특정 두 변의 평행이 유지되는 것을 알 수 있습니다.

300x250

Error: The SDK Build Tools revision is too low for project

 Eclipse에서 사용하던 프로젝트를 Android Studio로 가져왔을 때 아래와 같은 상황의 에러가 발생하였습니다.


Error: The SDK Build Tools revision (19.0.0) is too low for project. Minimum required is 19.1.0


 위 에러는 프로젝트가 기존 Eclipse에서 사용하던 Build Tools가 Android Studio에 설치된 Build Tools보다 버전이 낮아 발생하는 에러 입니다. 위 에러를 해결하기 위해서는 아래와 같은 과정을 수행합니다.


1.에러가 발생한 프로젝트의 폴더 -> build.grade 를 실행합니다.

2.android 부분에서 BuildToolsVersion 부분을 최소 요구 버전으로 설정합니다. 본 예제의 경우 버전을 19.1.0으로 수정합니다.



 위와 같이 적용한 후 Android Studio를 종료한 후 다시 실행하면 제대로 적용되어 있는 것을 확인하실 수 있습니다.




300x250

저장된 사진및 파일이 보이지 않을 때 미디어스캐닝(Media Scanning) 방법 [Kitkat 이후의 버전에서 적용방법]

 Socket을 활용하여 안드로이드 프로그래밍을 하는 분들이라면 누구나 한 번 즈음은 난관에 부딪치는 경우가 하나 있습니다. 그 중 하나가 분명 소켓 통신을 통해 받은 이미지나 동영상 파일을 저장하였는데 갤러리를 통해 확인해 보려 하면 보이지 않는 경우이지요! 희한하게도 안드로이드 기기의 전원을 끈 후 다시 확인해보면 안보이던 사진이 버젓이 보인다는 사실!


갤러리에 내가 다운로드 받은 파일이 누락되어 있다면 상당히 당황스러울 것이다.


 실제로 안드로이드 기기는 파일을 바로 저장한 상태로는 이를 기기가 바로 인식을 하지 못합니다. 그렇다면 기껏 다운로드 받은 파일을 보기 위해서 안드로이드  기기를 리셋 하는 방법밖에 없는 걸까요?



 안드로이드 기기를 쓰다가 위와 같이 미디어스캐닝(Media scanning)이 진행중인 것을 종종 보실 수 있습니다. 이것이 바로 종적을 감추어버린 파일들의 위치를 다시 찾는 기능을 하는 녀석입니다. 종종 개발자들이 애플리케이션을 개발하던 도중 다운로드가 완료된 후 미디어스캐닝을 해주지 않게 될 경우 파일을 볼 수 없는 상황이 벌어지는 것입니다.


 이번 포스팅에서는 소스코드를 통하여 미디어스캐닝을 수행하는 방법에 대해 알아볼 것입니다. 또한 본 포스팅은 Kitkat에서부터 변경된 미디어 저장 방식을 반영한 방법에 대해 다루어 보도록 할 것입니다.


 아래의 소스코드는 카메라로부터 촬영된 사진 데이터를 저장하는 과정을 나타낸 소스코드입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
        private Camera.PictureCallback picb = new Camera.PictureCallback() {
 
            @Override
            public void onPictureTaken(byte[] data, Camera camera) {
                // TODO Auto-generated method stub
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                long time = System.currentTimeMillis();
                SimpleDateFormat day = new SimpleDateFormat("yyyymmddhhmmssSSS");
                String output = day.format(new Date(time));
 
                String folder = Environment.getExternalStorageDirectory().getAbsolutePath()
                        + "/DCIM/FrameworkTest";
                String file = folder + File.separator + output + ".jpg";
 
                File FolderPath = new File(folder);
                if (!FolderPath.exists()) {
                    FolderPath.mkdirs();
                    Log.d("MKDIR", folder);
                }
 
                try {
                    FileOutputStream out = new FileOutputStream(file);
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 50out);
                    out.close();
                    sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, 
                            Uri.parse("file://"+file)));
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
 
                camera.startPreview();
            }
        };
cs

  위 소스코드의 내용대로 byte[] 형식으로 들어온 사진 데이터가 FileOutputStream 클래스를 통해 저장되는 과정을 나타내고 있습니다. 이를 위해 위의 소스코드 몇 줄을 확인해 보도록 하겠습니다.


String folder = Environment.getExternalStorageDirectory().getAbsolutePath();


 저장할 파일의 폴더명을 설정해 줍니다. 위의 소스코드를 통해 안드로이드 기기의 외부저장소의 최상단에서의 절대주소를 얻을 수 있습니다.


sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+file)));


 FileOutputStream을 통해 저장된 파일 하나를 나타내기 위해 해당 파일에 대해 Media Scanning을 수행합니다. Uri.parse() 의 인자값으로 해당 파일의 절대주소를 입력하며, Intent의 첫번째 인자인 Intent.ACTION_MEDIA_SCANNER_SCAN_FILE에 주의하시면 해당 소스코드를 사용하는 데에 큰 문제는 없을 것입니다. 위와 같이 설정된 Intent 클래스를 sendBroadcast() 매서드를 통해 전달하면 저장된 파일에 대한 Media Scanning이 정상적으로 동작되에 갤러리를 통해 해당 파일을 확인하실 수 있을 것입니다.

300x250