지난 번 포스트에 이어 Segalin et al. (2017) 에서 사용된 photo features 중에서, Composition 관련 feature 들을 살펴보도록 한다. composition 은 우리말로 ‘구성’이나 ‘구도’ 정도에 해당되는데, 사진의 내용이 무엇이냐와는 별도로 사진 속 시각적 요소들이 어떻게 구조화되어 있는지를 나타내주는 feature 들이라고 할 수 있다.

1. 먼저 Edge pixel 에 관한 feature 이다.

21) Edge pixels

정확히 말하자면 edge 에 해당되는 화소가 전체 사진의 화소 중에서 차지하는 비중을 가리킨다. edge 는 화소의 밝기가 급격하게 변화하는, 즉 연속적이지 않은 지점을 가리킨다. 따라서 edge 에 해당되는 화소가 많다는 것은 그러한 변화 지점이 많다는 뜻으로써, 물체 또는 무늬들이 많이 등장한다는 것을 말한다. 구현은 컴퓨터 비전 분야에서 널리 사용되는 Canny edge detector 를 써서 edge 를 판정하고, edge 에 해당되는 화소의 비중을 계산하면 된다.

그런데, Canny edge detector 를 어떻게 해야 제대로 구현하는 것인지가 좀 애매하다. 함수 자체는 OpenCV 에 구현되어 있고, 예제도 있다. 하지만 원래의 Canny 알고리즘에는 첫 번째 단계가 Gaussian Blur 를 적용하는 것으로 되어 있는데(오일석, 2014, p.132), 이것이 OpenCV 함수에 포함되어 있는지, 아니면 포함되어 있지 않기 때문에 별도로 적용해줘야 하는지가 분명하지 않다(원래 코드는 C++ 이고 Python 코드는 단순한 wrapper 라서…ㅠ). 몇몇 책에 나오는 예제들은 대부분 Gaussian Blur 없이 그냥 Canny 를 적용하고 있다(김동근, 2018, p.161; 이세우, 2019, p.236; 정성환, 배종욱, 2020, p.315). 반면, 논문의 코드에서는 OpenCV 의 Canny 함수를 쓰기 전에 Gaussian Blur 를 적용하고 있다. 또 Gaussian Blur 의 필터 사이즈를 어떤 크기로 해야 하는지도 하나의 이슈이다. 논문의 코드에서는 (3, 3)으로 했다. 그런데 책의 알고리즘 설명(이세우, 2019, p.235)이나 OpenCV 함수와 비교하기 위해 그냥 코딩한 예제(정성환, 배종욱, 2020, p.315)에서도 (5, 5)로 되어 있다. 심지어 어떤 블로그의 예제에서도 (5, 5)이다. 일단은 그냥 OpenCV 의 코드를 따라서 Gaussian Blur 없이 사용하는 것으로.

Canny 알고리즘의 또다른 파라미터인 threshold 또한 애매한 부분이다. lower 와 upper 두 threshold 사이에서 edge 를 판정하게 되는데, 이것을 (100, 200) 처럼 정해진 값을 줄 수도 있고, adaptive 하게 정하는 방법도 있는 것 같다. 논문의 코드에서는

thresh_low = min(100, np.quantile(blur_img, q=0.4))
thresh_up = max(200, np.quantile(blur_img, q=0.8))

이런 식으로 했는데, 분명한 인용이나 코멘트가 없어서 왜 이렇게 했는지는 모르겠다. 또 어떤 블로그의 예제에서는 다른 식으로 adaptive threshold 를 구현한 것 같은데, 역시 왜 이렇게 했는지는 모르겠다.

sigma = 0.33
v = np.median(blur_img)
thresh_low = int(max(0, (1.0 - sigma) * v))
thresh_up = int(min(255, (1.0 + sigma) * v))

일단 당분간은 위 블로그의 예제를 사용하는 것으로.

2. 다음으로는 Level of detail 관련 두 개의 feature 들이다. 핵심은 이미지를 segmentation 한 다음, segmentation 의 개수와 각 segment 들의 normalized average 면적을 구하는 것이다.

22) level of detail (number of segment)
23) the normalized average extension of the regions

논문에서는 Mean-shift 알고리즘(Comaniciu & Meer, 2002)을 써서 이미지 segmentation 을 하고, 그 결과를 통해 각 지역의 평균 면적을 구한다. Mean-shift 알고리즘에 대한 설명을 책에서 찾아보니 거의 없다. 그나마 찾은게 아래 정도.

This algorithm starts by placing a circle centered on each instance; then for each circle it computes the mean of all the instances located within it, and it shifts the circle so that it is centered on the mean. Next, it iterates this mean-shifting step until all the circles stop moving (i.e., until each of them is centered on the mean of the instances it contains). Mean-shift shifts the circles in the direction of higher density, until each of them has found a local density maximum. Finally, all the instances whose circles have settled in the same place (or close enough) are assigned to the same cluster. Mean-shift has some of the same features as DBSCAN, like how it can find any number of clusters of any shape, it has very few hyperparameters (just one—the radius of the circles, called the bandwidth), and it relies on local density estimation. But unlike DBSCAN, mean-shift tends to chop clusters into pieces when they have internal density variations. Unfortu‐ nately, its computational complexity is O(m2n), so it is not suited for large datasets. (Géron, 2023, p.282)

논문의 코드도 특별한 건 없다. 다만, mean-shift 알고리즘의 파라미터가 원의 지름(bandwidth)인데, 그것을 자동으로 추정해주는 방법이 별도로 있는 모양이다. 그리고 코드의 마지막에 크기가 작은 지역을 제거하는 부분이 있는데, 무슨 근거로 전체 면적에다가 0.05를 곱한 것보다 큰 것들만을 남겼는지가 불분명하다. 그래도 일단은 당분간 이 코드를 사용하는 것으로.

3. Low depth of field (DOF) indicator 에 대한 feature 들로써, HSV 각각 하나씩 총 세 개이다.

24) low DOF indicator for hue
25) low DOF indicator for saturation
26) low DOF indicator for value

피사계 심도(Depth of field)는

“사진술에서 한 사진의 초점이 맞은 것으로 인식되는 범위이다. 렌즈의 초점은 단 하나의 면에 정해지게 되어 있으나 실제 사진에서는 초점면을 중심으로 서서히 흐려지는 현상이 나타나는데, 이때 충분히 초점이 맞은 것으로 인식되는 범위의 한계를 피사계 심도라 한다”(위키백과)

라고 한다. 영어 위키피디아에서는

“The depth of field (DOF) is the distance between the nearest and the furthest objects that are in acceptably sharp focus in an image captured with a camera.”

라고 달리 표현한다. 따라서 DOF 가 낮다(low DOF)는 얘기는 초점이 맞은 것으로 인식되는 범위의 한계가 좁다는 뜻이 된다. 사진의 가운데 부분은 초점이 맞고 가장자리 부분은 초점이 안 맞으면 DOF 가 낮게 된 것으로, 사진의 중심이 되는 인물이나 사물에 대해 집중이 잘 된다고 한다.

이것을 측정하는 것이 문제다. 논문의 코드에서는 기본적으로 Daubechies wavelet transform 이란 것으로부터 시작한다. Wavelet transform 은 신호를 wave 형태의 기본 단위(wavelet)들의 조합으로 변환하는 것이다. 이미지 같은 신호는 불연속 신호이기 때문에 Discrete Wavelet Transform (DWT)을 한다. DWT 를 한번 하게 되면, 원래 이미지를 4등분한 것 중에 1사분면에 해당되는 위치에 low frequency coefficient 가, 나머지 세 사분면에 high frequency coefficient 가 만들어진다(coefficient 라고 해서 scalar 인 줄 알았더니 벡터다). 그리고 1사분면의 이미지에 같은 작업을 한번 더 하면 level 2, 한번 더 하면 level 3 의 DWT 가 된다. 이렇게 level 3 DWT 를 한 결과의 high frequency coefficient 에 해당되는 행렬들을 각각 16개($4 \times 4$)의 패치로 분할한다. 가운데에 해당되는 6, 7, 10, 11번째 패치 속 값들의 합과 전체 패치 속 값들의 합 사이의 비율이 low DOF indicator 가 된다. 휴우…

논문의 코드는 큰 오류 없이 잘 구현되어 있는 듯 하다. 다만 pywt 라는 모듈의 wavedec2() 라는 함수를 사용했는데, 함수의 옵션들에 대한 설명이 안 되어 있다. 옵션 중 wavelet 이라는 옵션이 있는데, 여기에서 ‘db’가 곧 Daubechies 이다. 정확히는 ‘db3’라는 옵션을 썼는데, db 뒤에 붙는 숫자는 number of vanishing moments 라고 한다(뭔소린지는 모르겠다). 그리고 mode 옵션에서는 ‘periodization’ 을 썼는데, 문서에 따르면

“To receive the smallest possible number of coefficients, computations can be performed with the periodization mode”

라고 한다. 그냥 쓰면 될 듯.

4. 다음으로는 Rule of thirds 에 관한 feature 두 가지이다.

27) saturation rule of thirds
28) value rule of thirds

사진의 구도에 대한 내용이다. 사진을 가로와 세로로 삼등분 하는 줄을 그었을 때, 사진 속 중요한 대상들은 그 선들 위 또는 교차점에 위치하도록 해야 한다는 것이다. 구현은 간단하다. 사진을 9개의 블록(3 * 3)으로 나눴을 때, 가운데 블록의 saturation 과 value 의 평균값으로 구한다. 근데 Rule of thirds 의 정의를 왜 그런 측정치로 구할 수 있는지는 잘 모르겠다. 이 논문이 인용하고 있는 원래 논문인 Datta et al. (2006)과 Machajdik & Hanbury (2010)까지 읽어보면 나오려나.

5. 마지막으로 이미지 사이즈이다. 이것은 총 pixel 개수로 구한다.

29) image size

얼마 안 되는 분량이지만 자세히 하나하나 살펴보니 공부가 필요한 내용들이 참 많다. 다음은 texture 관련 feature 들을 공부할 예정이다.


<참고문헌>

  • 김동근 (2018). <Python으로 배우는 OpenCV 프로그래밍>. 서울: 가메출판사.

  • 오일석 (2014). <컴퓨터 비전>. 서울: 한빛아카데미.

  • 이세우 (2019). <파이썬으로 만드는 OpenCV 프로젝트>. 서울: 인사이트.

  • 정성환, 배종욱 (2020). <OpenCV-Python으로 배우는 영상처리 및 응용>. 파주: 생능출판사.

  • Comaniciu, D., & Meer, P. (2002). Mean shift: A robust approach toward feature space analysis. IEEE Transactions on Pattern Analysis and Machine Intelligence, 24(5), 603-619. https://doi.org/10.1109/34.1000236

  • Datta, R., Joshi, D., Li, J., & Wang, J. Z. (2006). Studying aesthetics in photographic images using a computational approach. In A. Leonardis, H. Bischof, & A. Pinz (Eds.), Computer vision: ECCV 2006 (pp. 288-301). Berlin, Heidelberg: Springer. https://doi.org/http://doi.org/10.1007/11744078_23

  • Géron, A. (2023). Hands-on machine learning with Scikit-Learn, Keras, and Tensorflow: Concepts, tools, and techniques to build intelligent systems (3rd ed.). Sebastopol, CA: O’Reilly.

  • Machajdik, J., & Hanbury, A. (2010). Affective image classification using features inspired by psychology and art theory. Presented at International Conference on Multimedia (MM ‘10), Firenze, Italy. https://doi.org/10.1145/1873951.1873965

  • Segalin, C., Perina, A., Cristani, M., & Vinciarelli, A. (2017). The pictures we like are our image: Continuous mapping of favorite pictures into self-assessed and attributed personality traits. IEEE Transactions on Affective Computing, 8(2), 268-285. https://doi.org/10.1109/taffc.2016.2516994