물리는 어떻게 진화했는가

제목 그대로 물리학의 발전에 대해 다루는 교양서. 물리학사라기 보다는 물리학의 주요한 개념들이 어떻게 발전해 왔는지를 다루는 책.

갈릴레오와 뉴턴의 고전역학에서 상대성이론과 양자역학에 이르기까지의 내용을 각 개념들의 주요한 지점을 잘 설명하고 있음.

저자에 아인슈타인이 있어서 읽었는데, 실제 책 자체는 레오폴트 인펠트라는 물리학자가 주로 쓴 것 같다. 아인슈타인이 레오폴트를 도와주기 위해 같이 쓰기로 했다는 후기가 나옴.

책 자체는 분명 괜찮은데, 단순 교양적인 의미로는 근래에 나오는 책을 읽는 것이 나을 것 같다.

조커

관객을 압도하는 영화. 와킨 피닉스가 조커를 맡았다고 했을 때부터 기다린 보람이 있다. 연기 뿐만 아니라 연출, 촬영 등 모두 훌륭함. 마스터피스.

19.09.29

가난, 인간의 뇌를 바꾼다

연구진에 따르면 소득이 높은 사람일수록 돈을 사용하는 데 현명한 결정을 했을 뿐 아니라 논리 테스트와 인지능력 테스트에서도 모두 좋은 성적을 낸 것으로 나타났다. 연소득이 높은 사람과 낮은 사람의 문제 해결력은 2배 가까이 차이 났다. 연구를 이끈 물라이나단 교수는 "쉬운 문제는 소득에 상관없이 실험 참가자 대부분이 높은 점수를 받았지만 문제가 어려워지면 소득이 낮은 사람들의 점수가 현저하게 떨어졌다"며 "이는 뇌의 인지기능이 재정적 문제를 신경 쓰는 데 사용되면서 다른 결정을 내릴 때 잘못된 판단을 하는 것"으로 해석했다. 

가난은 그저 마음가짐이나 생활 수준의 문제가 아니다. 가난은 머리도 나쁘게 하고, 몸도 나쁘게 하고, 마음도 멍들게 한다. 우리가 가장 먼저 해결 해야 할 것은 비만이나 암이 아니라 가난이다.

모두가 부유해질 필요는 없지만, 모두가 가난에서 벗어나게는 해야 한다.
가난에서 벗어나면 사람들은 보다 건강해지고, 보다 관용적이게 되며, 보다 정의로워진다. 대단히 많은 사회 문제를 한 방에 해결할 수 있다는 얘기다.

뇌의 장기 기억 저장, 렘수면이 결정한다

주류 의견은, 뇌가 새로운 기억을 저장하는 데 수면이 도움을 준다는 것이다. 반면 수면 상태에서, 특히 렘수면 단계에선 뇌가 불필요한 정보를 삭제할 거라는 견해도 제기됐다. (중략)

최근의 동물 실험에선, 수면 중인 뇌가 특정한 유형을 가진 학습 관련 뉴런들의 시냅스(신경 연접부) 연결을 선별적으로 잘라낸다는 게 밝혀졌다. 그러나 이번 연구 결과가 나오기 전에는 어떻게 그런 일이 벌어지는지 알지 못했다.

흥미로운 이야기다. 불필요한 기억을 선별적으로 잘라낸다는데, 그 선별은 누가 무엇을 기준으로 하는가?

염소치기 딜레마

그때 마침 습격대는 시르카시아에서 온 떠돌이 상인과 맞닥뜨렸다. 그를 포로로 잡아둘 수도 없고 그냥 보내줄 수도 없는 상황에서(시르카시아인은 대부분 터키 동조자였다) 일부 대원은 당장 죽이라고 외쳐댔다. 결국 찾아낸 절충안은 상인을 발가벗기고 단검으로 발가락을 모조리 자르는 것이었다. 로렌스는 담담하게 기록했다. (중략)

염소치기들을 풀어준 지 한 시간 반쯤 지나 미군 네 명은 AK-47과 휴대용 로켓발사기로 무장한 탈레반 80〜100명에게 포위되었다. 곧 이어 격렬한 총격전이 벌어졌고, 세 명이 목숨을 잃었다. 탈레반 무장 세력은 실 대원을 구출하려던 미군 헬리콤터 한 대까지 격추해, 그곳에 타고 있던 군인 열여섯 명을 모두 죽였다.

전쟁에서 자비를 바라지 마라. 살아 남는 것이 가장 급선무인 곳. 때문에 가장 좋은 것은 전쟁이 안 일어나는 것이지.

OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝/ 필터링

영상의 필터링

필터링 연산 방법

  • 영상 처리에서 필터링(filtering)이란 영상에서 원하는 정보만 통과시키고 원치 않는 정보는 걸러 내는 작업.
    • 잡음(noise)를 걸러 내어 영상을 깔금하게 만드는 필터가 있고, 부드러운 느낌의 성분을 제거함으로써 날카로운 느낌이 나도록 할 수도 있다.
  • 영상의 필터링은 보통 마스크(mask)라고 부르는 작은 크기의 행렬을 이용한다.
    • 마스크는 필터링의 성격을 정의하는 행렬이며 커널(kernel), 윈도우(window)라고도 부르며 경우에 따라 마스크 자체를 필터라고 하기도 한다.
  • 마스크는 다양한 크기와 모양으로 정의할 수 있으며, 마스크 행렬의 원소는 보통 실수로 구성된다.
    • 여러 모양의 필터 마스크 중에 3 x 3 정방형 행렬이 다양한 필터링 연산에서 가장 널리 사용된다.
    • 위 그림에서 필터 마스크의 가운데 위치한 진한 색을 고정점(anchor point)라고 하는데, 고정점은 현재 필터링 작업을 수행하고 있는 기준 픽셀 위치를 나타낸다. 대부분의 경우 마스크 행렬의 정중앙을 고정점으로 사용한다.

  • 필터링 연산의 결과는 마스크 행렬의 모양과 원소 값에 의해 결정된다. 
    • 즉, 마스크 행렬을 어떻게 정의하는가에 따라 영상을 부드럽게도, 날카롭게도 할 수 있다.
    • 또는 영상에서 잡음을 제거하거나 에지(edge) 성분만 나타나도록 할 수도 있다.
  • 아래 그림은 3 x 3 정방형 마스크를 이용한 필터링 수행 방법이다.
    • 아래 그림에서 m은 마스크 행렬을 나타내고, f와 g는 각각 입력 영상과 출력 영상을 의미한다.
    • 이 그림에서 마스크 행렬 크기가 3 x 3이므로 고정점의 좌표는 중심 좌표인 (1, 1)로 설정했다.
  • 마스크를 이용한 필터링은 입력 영상의 모든 픽셀 위로 마스크 행렬을 이동시키면서 마스크 연산을 수행하는 방식으로 이루어진다.

  • 마스크 연산이란 마스크 행렬의 모든 원소에 대하여 마스크 행렬 원소 값과 같은 위치에 있는 입력 영상 픽셀 값을 서로 곱한 후, 그 결과를 모두 더하는 연산이다.
    • 그리고 마스크 연산의 결과를 출력 영상에서 고정점 위치에 대응되는 픽셀 값으로 설정한다.
    • 그러므로 마스크 행렬 m의 중심이 입력 영상의 (x, y) 좌표 위에 위치했을 때 필터링 결과 영상의 픽셀 값 g(x, y)는 다음과 같이 계산된다.

g(x, y) = m(0, 0) f(x-1, y-1) \\ + m(1, 0) f(x, y-1) \\ + m(2, 0) f(x+1, y-1) \\ + m(0, 1) f(x-1, y) \\ + m(1, 1) f(x, y) \\ + m(2, 1) f(x+1, y) \\ + m(0, 2) f(x-1, y+1) \\ + m(1, 2) f(x, y+1) \\ + m(2, 2) f(x+1, y+1)

  • (x, y) 좌표에서 마스크 연산을 통해 결과 영상의 픽셀 값 g(x, y)를 구했으면, 다음에는 마스크를 한 픽셀 옆으로 이동하여 (x+1, y) 좌표에 다시 마스크 연산을 수행하고 그 결과를 g(x+1, y)에 저장한다. 이 과정을 영상 전체 픽셀에 대해 수행하면 필터링이 완료 된다.
  • 그런데 영상의 가장 바깥쪽 픽셀에서는 (x, y) 자리에 영상에 존재하지 않는 좌표가 들어오게 된다.
    • 이 식은 계산할 수 없기 때문에 영상의 가장자리 픽셀에 대해 필터링을 수행할 때는 특별한 처리를 해야 한다.
  • OpenCV에서는 영상의 필터링을 수행할 때 영상의 가장자리 픽셀을 확장하여 영상 바깥쪽에 가상의 픽셀을 만든다.
    • 이때 바깥쪽 가상의 픽셀 값을 어떻게 설정하는가에 따라 필터링 연산 결과가 달라진다.
  • 아래 이미지는 5 x 5 크기의 필터 마스크를 적용하는 예시로서, 노란색으로 표시된 실제 존재하는 영상에 대해 가상의 픽셀을 구성하여 분홍색 픽셀을 만든 이미지이다.
    • 분홍색 픽셀의 영문자는 실제 픽셀의 영문자와 동일한 위치의 픽셀값을 나타낸다.
    • 아래 이미지는 실제 영상의 픽셀 값이 대칭 형태로 나타나도록 설정되어 있는 모습이다.

  • 대부분의 OpenCV 필터링 함수는 위와 같은 방식으로 가장자리 픽셀을 확장하지만 다른 방식으로 가상의 픽셀 값을 설정할 수도 있다.
    • 이에 대한 내용은 아래 표 참조

  • OpenCV에서 필터 마스크를 사용하는 일반적인 필터링은 filter2D() 함수를 이용하여 수행한다.
    • filter2D() 함수는 src 영상에 kernel 필터를 이용하여 필터링을 수행하고, 그 결과를 dst에 저장한다.
    • 만약 src 인자와 dst 인자에 같은 변수를 지정하면 필터링 결과를 입력 영상에 덮어쓰게 된다.
    • filter2D() 함수가 수행하는 연산을 수식으로 표현하면 다음과 같다.

dst(x, y) = \sum_{j} \sum_{i} kernel(i, j) \cdot src(x+i-anchor.x, y+j-anchor.y) + delta

  • filter2D() 함수 인자 중에서 ddepth는 결과 영상의 깊이를 지정하는 용도로 사용하며, 입력 영상 깊이에 따라 지정할 수 있는 ddepth 값은 아래 표와 같다.
    • 만약 ddepth에 -1을 지정하면 출력 영상의 깊이는 입력 영상과 같게 설정된다.
입력 영상의 깊이(src.depth()) 지정 가능한 ddepth값
CV_8U -1/ CV_16S/ CV_32F/ CV_64F
CV_16U/CV_16S -1/ CV_32F/ CV_64F
CV_32F -1/ CV_32F/ CV_64F
CV_64F -1/ CV_64F

 

  • Note)
    • 3 x 3 필터 마스크를 이용하여 입력 영상 src와 필터링을 수행하는 수식을 쓰면 다음과 같다.

dst(x, y) = \sum_{j=0}^{2} \sum_{i=0}^{2} m(i, j) \cdot src(x+i-1, y+j-1)

  • 앞 수식은 입력 영상 (x, y) 좌표에 마스크 행렬을 올려놓고, 같은 위치에 있는 마스크 행렬 원소와 입력 영상 픽셀 값을 모두 곱한 후 더하는 연산이다.
    • 이처럼 두 개의 신호가 있을 때 같은 위치에 있는 신호 값을 모두 곱한 후 다시 더하는 연산을 신호 처리 분야에서 코릴레이션(correlation) 또는 상관이라고 한다.
    • 신호 처리에서 코릴레이션은 두 신호의 유사성을 판단하는 기준으로 사용되기도 한다.
  • 두 개의 연속 신호 f와 g가 있을 때 두 신호의 코릴레이션을 구하는 수식은 다음과 간다.

(f \otimes g)(t) \int_{a}^{b} f^{*}(\tau)g(t+\tau)d\tau

  • 그런데 영상 필터링을 신호 처리의 컨볼루션(convolution) 연산이라고 말하는 경우가 많다. 컨볼루션은 회선 또는 합성곱이라고도 하며, 두 신호의 컨볼루션은 다음 수식으로 정의된다.

(f * g)(t) \int_{a}^{b} f(\tau)g(t-\tau)d\tau

  • 컨볼루션은 두 입력 신호 중 하나를 원점 기준 대칭 변환한 후 코릴레이션을 구하는 것과 같다.
    • 그러므로 2차원 마스크 행렬과 입력 영상의 컨볼루션 연산을 정확하게 수행하려면 마스크 행렬을 상하 및 좌우 대칭으로 변환한 후 필터링 연산을 수행해야 한다.
    • 그러나 필터 마스크가 상하 및 좌우 대칭으로 구성되어 있는 경우에는 코릴레이션과 컨볼루션의 결과는 서로 같다.
    • 영상 처리에서 널리 사용되고 있는 많은 필터 마스크가 상하 및 좌우 대칭으로 구성되어 있기 때문에 관용적으로 필터링 연산을 컨볼루션 연산이라고 부르고 있다.

엠보싱 필터링

  • 엠보싱이랑 직물이나 종이, 금속판 등에 올록볼록한 형태로 만든 객체의 윤곽 또는 무늬를 뜻하며, 엠보싱 필터는 입력 영상을 엠보싱 느낌이 나도록 변환하는 필터이다.
    • 보통 입력 영상에서 픽셀 값 변화가 적은 평탄한 영역은 회색으로 설정하고, 객체의 경계 부분은 좀 더 밝거나 어둡게 설정하면 엠보싱 느낌이 난다.
  • 아래 이미지는 간단한 형태의 엠보싱 필터 마스크의 예이다.
    • 필터 마스크는 대각선 방향으로 +1 또는 -1의 값이 지정되어 있는 3 x 3 행렬이다.
    • 이 필터 마스크를 사용하여 필터링을 수행하면 대각선 방향으로 픽셀 값이 급격하게 변하는 부분에서 결과 영상 픽셀 값이 0보다 훨씬 크거나 0보다 훨씬 작은 값을 가지게 된다.
    • 입력 영상에서 픽셀 값이 크게 바뀌지 않는 평탄한 영역에서는 결과 영상의 픽셀 값이 0에 가까운 값을 갖게 된다.
    • 이렇게 구한 영상을 그대로 화면에 나타내면 음수 값이 포화 연산에 의해 0이 되어 버리기 때문에 결과 영상에 18을 더하는 것이 보기에 좋다.

블러링

  • 블러링(blurring)은 초점이 맞지 않는 사진처럼 영상을 부드럽게 만드는 필터링 기법으로 스무딩(smoothing)이라고도 한다.
    • 영상에서 인접한 픽셀 간의 픽셀 값 변화가 크지 않은 경우 부드러운 느낌을 받을 수 있다.
    • 블러링은 거친 느낌의 입력 영상을 부드럽게 만드는 용도로 사용되기도 하고, 입력 영상에 존재하는 잡음의 영향을 제거하는 전처리 과정으로도 사용된다.

평균값 필터

  • 평균값 필터(mean filter)는 입력 영상에서 특정 픽셀과 주변 픽셀들의 산술 평균을 결과 영상 픽셀 값으로 설정하는 필터이다.
    • 평균값 필터에 의해 생성되는 결과 영상은 픽셀 값의 급격한 변화가 줄어들어 날카로운 에지가 무뎌지고 잡음의 영향이 크게 사라지는 효과가 있다.
    • 그러나 평균값 필터를 과도하게 사용하면 사물의 경계가 흐릿해지고 사물의 구분이 어려워질 수 있다.
  • 아래 이미지는 다양한 크기의 평균값 필터 마스크를 나타낸 것이다.
    • 각각의 행렬은 모두 원소가 1로 설저외더 있고 행렬의 전체 원소 개수로 각 행렬 원소 값을 나누는 형태로 표현되어 있다.
    • 결국 3 x 3 평균값 필터 마스크는 모든 원소가 1/9로 설정된 행렬이고, 5 x 5 평균값 필터는 모든 원소가 1/25로 구성된 행렬이다.
    • 평균값 필터는 마스크의 크기가 커질 수록 부드러운 느낌의 영상을 생성하지만, 연산량이 크게 증가할 수 있다.

  • OpenCV에서는 blur() 함수를 이용하여 평균값 필터링을 수행할 수 있다.
    • blur() 함수는 src 영상에 ksize 크기의 평균값 필터 마스크를 사용하여 dst 출력 영상을 생성한다.
    • blur() 함수에서 사용하는 커널은 다음과 같은 형태를 갖고 있다.

kernel = { 1 \over ksize.width \times ksize.height } \left[ \begin{array}{rrrr} 1 & 1 & ... & 1 \\ 1 & 1 & ... & 1 \\ ... & ... & ... & ... \\ 1 & 1 & ... & 1 \end{array} \right]

  • Note)
    • 일반적으로 필터 마스크 행렬은 모든 원소 합이 1 또는 0이 되도록 설계한다. 필터 마스크 행렬의 원소 합이 1이면 필터링 결과와 영상의 평균 밝기가 입력 영상 평균 밝기와 같에 유지되기 때문이다.
    • 만일 필터 마스크 행렬 원소의 합이 1보다 작으면 입력 영상보다 어두운 영상이 되고, 1보다 크면 밝은 결과 영상이 만들어진다.

가우시안 필터

  • 가우시안 필터(Gaussian filter)는 가우시안 분포(Gaussian distribution) 함수를 근사하여 생성한 필터 마스크를 사용하는 필터링 기법이다.
  • 가우시안 분포는 평균을 중심으로 좌우 대칭의 종 모양(bell shape)을 갖는 확률 분포를 말하며 정규 분포(normal distribution)라고도 한다.
  • 가우시안 분포는 평균과 표준 편차에 따라 분포 모양이 결정된다. 다만 영상의 가우시안 필터에서는 주로 평균이 0인 가우시안 분포 함수를 사용한다.
    • 평균이 0이고 표준 편차가 \sigma 인 1차원 가우시안 분포를 함수식으로 나타내면 다음과 같다.

G_{\sigma}(x) = {1 \over \sqrt{2 \pi \sigma}} e^{- {x^{2} \over 2 \sigma^{2}}}

  • 평균이 0이고 표준 편차 \sigma 가 각각 0.5, 1.0, 2.0인 가우시안 분포 그래프를 그리면 아래와 같다.
    • 세 개의 그래프가 모두 평균이 0이므로 x=0에서 최댓값을 가지며, x가 0에서 멀어질수록 함수 값이 감수한다.
    • \sigma 가 작으면 그래프가 뾰족한 형태가 되고, \sigma 가 크면 그래프가 넓게 퍼지면서 완만한 형태를 따른다.
    • 가우시안 분포 함수값은 특정 x가 발생할 수 있는 확률의 개념을 가지며, 그래프 면적을 합하면 1이 된다.

  • 가우시안 분포를 따르는 2차원 필터 마스크 행렬을 생성하려면 2차원 가우시안 분포 함수를 근사해야 한다.
    • 2차원 가우시안 분포 함수는 x와 y 두 개의 변수를 사용하고, 분포의 모양을 결정하는 평균과 표준 편차도 x축과 y축 방향에 따라 따로 설정한다.
    • 평균이 (0, 0)이고 x축과 y축 방향의 표준 편차가 각각 \sigma_{x}, \sigma_{y} 인 2차원 가우시안 분포 함수는 다음과 같이 정의 된다.

G_{\sigma_{x}, \sigma_{y}}(x, y) = {1 \over \sqrt{2 \pi \sigma_{x} \sigma_{y}}} e^{- ({x^{2} \over 2 \sigma_{x}^{2}} + {y^{2} \over 2 \sigma_{y}^{2}})}

  • 평균은 (0, 0)이고 \sigma_{x} = \sigma_{y} = 1.0 인 2차원 가우시안 분포 함수 그래프를 그리면 아래와 같다.
    • 평균이 (0, 0)이므로 (0, 0)에서 최댓값을 갖고, 평균에서 멀어질수록 함수가 감소한다.
    • 함수 그래프의 부피를 구하면 1이 된다.

  • 가우시안 필터는 이러한 2차원 가우시안 분포 함수로부터 구한 마스크 행렬을 사용한다. 가우시안 분포 함수는 연속 함수지만 이산형의 마스크를 만들기 위해 x와 y 값이 정수인 위치에서만 가우시안 분포 함수 값을 추출하며 마스크를 생성한다.
    • 평균이 0이고 표준 편차가 \sigma 인 가우시안 분포는 x가 -4 \sigma 부터 4 \sigma 사이인 구간에서 그 값의 대부분이 존재하기 때문에 가우시안 필터 마스크의 크기는 보통 (8 \sigma + 1) 로 결정한다.
    • 예컨대 위 그림과 같이 \sigma_{x} = \sigma_{y} = 1.0 인 가우시안 함수를 사용할 경우, x = \{ -4, -3, -2, -1, 0, 1, 2, 3, 4 \}, y = \{ -4, -3, -2, -1, 0, 1, 2, 3, 4 \} 인 경우에만 가우시안 분포 함수 값을 추출하여 필터 마스크를 생성한다.
    • 이러한 방식으로 추출한 9 x 9 가우시안 필터 마스크가 아래 그림과 같다.

  • 위 그림에 나타난 가우시안 필터 마스크 행렬은 중앙부에서 비교적 큰 값을 가지고, 주변부로 갈수록 원소 값이 0에 가까운 작은 값을 가진다.
    • 그러므로 이 필터 마스크를 이용하여 마스크 연산을 수행한다는 것은 필터링 대상 픽셀 근처에는 가중치를 크게 주고, 필터링 대상 필셀과 멀리 떨어져 있는 주변부에는 가중치를 조금만 주어서 가중 평균(weighted average)을 구하는 것과 같다.
    • 즉, 가우시안 필터 마스크가 가중 평균을 구하기 위한 가중치 행렬 역할을 하는 것이다.
  • 마스크 연산에 의한 영상 필터링은 마스크 크기가 커짐에 따라 연산량도 함께 증가한다.
    • 9 x 9 행렬의 경우 한 번의 마스크 연산 시 81번의 곱셈 연산이 필요하다. 또한 큰 표준 편차 값을 사용하면 마스크 크기도 함께 커지므로 연산 속도 측면에서 부담이 될 수 있다.
    • 다행히 2차원 가우시안 분포 함수는 1차원 가우시안 분포 함수의 곱으로 분리할 수 있으며, 이러한 특성을 이용하면 가우시안 필터 연산을 크게 줄일 수 있다.
    • 2차원 가우시안 분포 함수 수식은 아래와 같이 분리하여 작성할 수 있다.

G_{\sigma_{x}, \sigma_{y}}(x, y) = {1 \over \sqrt{2 \pi \sigma_{x} \sigma_{y}}} e^{- ({x^{2} \over 2 \sigma_{x}^{2}} + {y^{2} \over 2 \sigma_{y}^{2}})} \\ = {1 \over \sqrt{2 \pi \sigma_{x}}} e^{- {x^{2} \over 2 \sigma_{x}^{2}}} \times {1 \over \sqrt{2 \pi \sigma_{y}}} e^{- {y^{2} \over 2 \sigma_{y}^{2}}} \\ = G_{\sigma_{x}}(x) \cdot G_{\sigma_{y}}(y) 

  • 이처럼 2차원 필터 마스크 생성 함수를 x축 방향으로 함수와 y축 방향으로의 함수로 분리할 수 있을 경우, 입력 영상을 x축 방향으로의 함수와 y축 방향으로의 함수로 각각 1차원 마스크 연산을 수행함으로써 필터링 결과 영상을 얻을 수 있다.
  • 예컨대 \sigma_{x} = \sigma_{y} = 1.0 인 2차원 가우시안 마스크로 영상을 필터링하는 것은 \sigma = 1.0 인 1차원 가우시안 마스크를 가로 방향과 세로 방향으로 각각 생성하여 두 번 필터링 하는 것과 같다.
    • 실제로 \sigma = 1.0 인 1차원 가우시안 함수로부터 1 x 9 가우시안 마스크 행렬은 다음과 같다.

g = \left( \begin{array}{rrrrrrrrr} 0.0001 & 0.0044 & 0.0540 & 0.2420 & 0.3989 & 0.2420 & 0.0540 & 0.0044 & 0.0001 \end{array} \right)

  • 그러므로 행렬 g 를 이용하여 필터링을 한 번 수행하고, 그 결과를 다시 g 의 전치 행렬인 g^{T} 를 이용하여 필터링 하는 것은 2차원 가우시안 필터 마스크로 한 번 필터링 하는 것과 같은 결과를 얻을 수 있다.
    • 이 경우 픽셀 하나에 대해 필요한 곱셈 연산 횟수가 18번으로 감소하여 연산량이 크게 줄어든다.
  • OpenCV에서 가우시안 필터링을 수행하려면 GaussianBlur() 함수를 사용하면 된다.
    • GaussianBlur() 함수는 src 영상에 가우시안 필터링을 수행하고 그 결과를 dst 영상에 저장한다. x축과 y축 방향으로의 표준 편차 sigmaX와 sigmaY는 서로 다른 값을 지정해도 되지만, 특정한 이유가 없다면 sigmaX와 sigmaY는 같은 값을 사용한다.
    • GaussianBlur() 함수에서 sigmaY인자를 지정하지 않거나 0으로 설정하면 y축 방향에 대해서도 sigmaX와 같은 표준편차를 사용한다.
    • 또한 가우시안 필터의 크기를 지정하는 ksize 인자에도 특별한 이유가 없다면 Size()를 전달하여 적절한 필터 크기를 자동으로 결정하도록 하는 것이 좋다.
  • 가우시안 필터링은 x축 방향과 y축 방향으로 각각 1차원 가우시안 필터를 적용하여 수행한다고 설명했는데 실제로 GaussianBlur() 함수 내부에서 가우시안 필터링을 구현할 때에도 x축 방향과 y축 방향에 따라 1차원 가우시안 필터 마스크를 각각 생성하여 필터링을 수행한다.
    • 이때 1차원 가우시안 필터 마스크를 생성하기 위해 OpenCV에서 제공하는 getGaussianKernel() 함수를 사용한다. 이 함수는 사용자가 지정한 표준 편차를 따르는 1차원 가우시안 필터 마스크 행렬을 생성하여 반환한다.
    • getGaussianKernel() 함수는 표준 편차가 sigma인 1차원 가우시안 분포 함수로부터 ksize x 1 크기의 필터 마스크 행렬을 생성하여 반환한다.
    • ksize는 (8 x sigma + 1) 보다 같거나 크게 지정하는 것이 좋다. 
    • 이 행렬의 원소에 저장되는 값은 다음의 수식을 따른다.

G_{i} = \alpha \cdot e^{{(i - (ksize-1) \div 2)^{2} \over 2 \sigma^{2}}}

  • 앞 수식에서 i = 0, 1, ... , ksize - 1 의 범위를 가지며, \alpha \sum_{i} G_{i} = 1 이 되도록 만드는 상수이다.
  •  Note)
    • getGaussianKernel() 함수는 ksize 값이 7보다 같거나 작고 sigma 값이 0 또는 음수인 경우에는 미리 정해 놓은 배열 값을 이용하여 커널 행렬을 생성한다.

샤프닝

언샤프 마스크 필터

  • 샤프닝(sharpning)이란 영상을 날카로운 느낌이 나도록 변경하는 필터링 기법.
    • 날카로운 느낌의 영상이란 객체의 윤곽이 뚜렷하게 구분되는 영상을 의미한다.
    • 영상을 초점이 잘 맞은 사진처럼 보이게끔 변경하려면 영상 에지 근방에서 픽셀 값의 명암비가 커지도록 수정해야 한다.
  • 샤프닝 기법과 관련하여 흥미로운 사실은 샤프닝을 구현하기 위해 블러링된 영상을 사용한다는 점. 블러링이 적용되어 부드러워진 영상을 활용하여 반대로 날카로운 영상을 생성한다는 것이다.
    • 여기서 블러링이 적용된 영상, 즉 날카롭지 않은 영상을 언샤프(unsharp) 하다고 말하기도 한다.
    • 이처럼 언샤프한 영상을 이용하여 역으로 날카로운 영상을 생성하는 필터를 언샤프 마스크 필터(unsharp mask filter)라고 한다.
  • 언샤프 마스크 필터링의 과정을 아래 이미지를 통해 확인할 수 있다.
    • 아래 이미지의 가로축은 픽셀 좌표의 이동을 나타내며, 세로축은 픽셀 값을 나타낸다.
    • (a)는 영상의 에지 부근에서 픽셀 값이 증가하는 모양을 나타낸 것이다.
    • (b)에서 파란색 실선 그래프는 f(x, y) 에 블러링을 적용한 결과를 나타내며, 이를 \bar{f}(x, y) 로 표기. 블러링된 결과와 원본 픽셀값 변화를 비교해 볼 수 있도록 (b)에 f(x, y) 를 검은색 점선으로 표현하였다.
    • (c)는 입력 영상 f(x, y) 에서 블러링된 \bar{f}(x, y) 를 뺀 결과이며, 이를 g(x, y) 로 표기. 즉 g(x, y) = f(x, y) - \bar{f}(x, y) 가 된다.
    • g(x, y) 는 입력 함수 값이 증가하기 시작하는 부분에서 음수 값을 가지고, 입력 함수 값 증가가 멈추는 부근에서 양수 값을 가진다. 그러므로 입력 함수 f(x, y) g(x, y) 를 더하면 에지가 강조된 함수가 생성된다.
    • (d)에서 h(x, y) = f(x, y) + g(x, y) 가 샤프닝이 적용된 결과 영상이 된다.

  • g(x, y) 는 입력 영상에서 블러링된 영상을 뺀 결과이므로, g(x, y) 는 입력 영상에서 오직 날카로운 성분만 가지고 있는 함수라 할 수 있다.
    • 고로 입력 영상 f(x, y) g(x, y) 를 더함으로써 날카로운 성분이 강조된 최종 영상 h(x, y) 가 얻어지는 것으로 해석할 수 있다.
    • 그런데 f(x, y) g(x, y) 를 단순하게 더하는 것이 아니라 실수 가중치를 곱한 후 더하면 날카로운 정도를 조절할 수 있다.
    • 즉, 샤프닝이 적용된 결과 영상 h(x, y) 의 수식을 다음과 같이 정의할 수 있다.

h(x, y) = f(x, y) + \alpha \cdot g(x, y)

  • 위 식에서 \alpha 에 1보다 작은 값을 지정하면 덜 날카로운 영상을 만들 수 있다.
    • 위 식에서 g(x, y) 대신 f(x, y) - \bar{f}(x, y) 수식을 대입하여 식을 정리하면 다음과 같다.

h(x, y) = f(x, y) + \alpha (f(x, y) - \bar{f} (x, y)) \\ = (1 + \alpha) f(x, y) - \alpha \cdot \bar{f}(x, y)

  • OpenCV에서는 언샤프 마스크 필터 함수를 따로 제공하지 않으므로 위 수식을 이용하여 코드를 직접 작성해야 한다.

잡음 제거 필터링

영상과 잡음 모델

  • 신호 처리 관점에서 잡음(noise)란 원본 신호에 추가된 원치 않은 신호를 의미한다.
    • 영상에서 잡음은 주로 영상을 획득하는 과정에서 발생하며, 디지털 카메라에서 사진을 촬영하는 경우 광학적 신호를 전기적 신호로 변환하는 센서(sensor)에서 주로 잡음이 추가된다.
  • 디지털 카메라에서 카메라 렌즈가 바라보는 장면을 원본 신호 s(x, y) 라고 하고, 여기에 추가된 잡음을 n(x, y) 라고 한다면, 실제로 카메라에서 획득되는 영상 신호 f(x, y) 는 다음과 같이 표현한다.

f(x, y) = s(x, y) + n(x, y)

  • 잡음이 생성되는 방식을 잡음 모델(noise model)이라고 하며, 다양한 잡음 모델 중에서 가장 대표적인 잡음 모델은 가우시안 잡음 모델(Gaussian noise model)이다.
    • 가우시안 잡음 모델은 보통 평균이 0인 가우시안 분포를 따르는 잡음을 의미한다.
  • 아래 그림은 평균이 0이고 표쥰편차가 10인 1차원 가우시안 분포 그래프이다.
    • 평균이 0이고 표준 편차가 \sigma 인 가우시안 분포는 x 값이 -\sigma \leq x \leq \sigma 구간에서 전체 데이터의 67%가 존재하고, -2\sigma \leq x \leq 2\sigma 구간에는 95% -3\sigma \leq x \leq 3\sigma 구간에는 99.7%가 존재한다.
    • 그러므로 평균이 0이고 표준 편차가 10인 가우시안 분포를 따르는 잡음 모델은 67%의 확률로 -10에서 10 사이의 값이 잡음으로 추가된다. 잡음 값이 -20부터 20 사이일 확률은 95%이며, 그 밖의 값이 잡음으로 추가될 확률은 5%이다.
    • 그러므로 표준편차가 작은 가우시안 잡음 모델일수록 잡음에 의한 픽셀 값 변화가 적다고 생각할 수 있다.

양방향 필터

  • 대부분의 영상에는 가우시안 잡음이 포함되어 있으며, 많은 컴퓨터 비전 시스템이 가우시안 잡음을 제거하기 위해 가우시안 필터를 사용한다.
    • 입력 영상에서 픽셀 값이 크게 변하지 않는 평탄한 영역에 가우시안 필터가 적용될 경우, 주변 픽셀 값이 부드럽게 블러링되면서 자음의 영향도 크게 줄어든다.
  • 그러나 픽셀 값이 급격하게 변경되는 에지 근방에 동일한 가우시안 필터가 적요오디면 잡음뿐만 아니라 에지 성분까지 함께 감소하게 된다. 즉, 잡음이 줄어들면서 에지도 무뎌지기 때문에 객체의 윤곽이 흐릿하게 바뀌게 된다.
  • 이러한 단점을 보완하기 위해 많은 사람들이 에지 정보는 그대로 유지하면서 잡음만 제거하는 에지 보전 잡음 제거 필터(edge-preserving noise removal filter)에 대해 연구하였다.
    • 특히 1998년 토마시(C. Tomasi)가 제안한 양방향 필터(bilateral filter)는 에지 성분은 그대로 유지하면서 가우시안 잡음을 효과적으로 제거하는 알고리즘이다.
    • 양방향 필터 기능은 OpenCV 라이브러리 초기 버전부터 포함되어 있어서 많은 사람들이 사용하고 있다.
    • 양방향 필터는 다음 공식을 사용하여 필터링을 수행한다.

g_{p} = {1 \over W_{p}} \sum_{q \in S} G_{\sigma_{s}} (\|p - q\|) G_{\sigma_{r}}(|f_{p} - f_{q}|)f_{q}

  • 위 수식에서 f 는 입력 영상, g 는 출력 영상, 그리고 p q 는 픽셀의 좌표를 나타낸다.
    • f_{p} f_{q} 는 각각 p 점과 q 점에서의 입력 영상 픽셀 값이고, g_{p} p 점에서의 출력 영상 픽셀 값이다.
    • G_{\sigma_{s}} G_{\sigma_{r}} 는 각각 표준 편차가 \sigma_{s} \sigma_{r} 인 가우시안 분포 함수이다.
    • S 는 필터 크기를 나타내고, 
    • W_{p} 는 양방향 필터 마스크 합이 1이 되도록 만드는 정규화 상수이다.
  • 양방향 필터 수식은 복잡해 보이지만 가만히 살펴보면 두 개의 가우시안 함수 곱으로 구성된 필터이다.
    • G_{\sigma_{s}} (\|p - q\|) 함수는 두 점 사이의 거리에 대한 가우시안 함수로서 가우시안 필터와 완전히 동일한 의미로 동ㅈ가한다.
    • 반면 G_{\sigma_{r}}(|f_{p} - f_{q}|) 함수는 두 점의 픽셀 값 차이에 의한 가우시한 함수이다. G_{\sigma_{r}}(|f_{p} - f_{q}|) 함수는 두 점의 픽셀 밝기 값 차이가 적은 평탄한 영역에서는 큰 가중치를 갖게 만들고 에지를 사이에 두고 있는 두 픽셀 사이에 대해서는 |f_{p} - f_{q}| 값이 크게 나타나므로 상대적으로 G_{\sigma_{r}}(|f_{p} - f_{q}|) 는 거의 0에 가까운 값이 된다.
    • 이로 인해 에지 근방에서는 가우시안 블러링 효과가 거의 나타나지 않고 에지가 보존된다.
  • 양방향 필터 수식이 픽셀 값의 차이에 의존적이기 때문에 양방향 필터 마스크는 영상의 모든 픽셀에서 서로 다른 형태를 갖게 된다.
    • 즉 모든 픽셀 위치에서 주변 픽셀과의 밝기 차이에 의한 고유의 필터 마스크 행렬을 만들어서 마스크 연산을 수행해야 한다.
    • 이는 일반적인 가우시안 블러링이 모든 위치에서 일정한 마스크 행렬을 사용하는 것과 차이가 있다. 따라서 양방향 필터는 가우시안 블러링보다 훨씬 많은 연산량을 필요로 한다.
  • OpenCV에서는 bilateralFilter() 함수를 이용하여 양방향 필터를 수행할 수 있다.
    • bilateralFilter() 함수에서 sigmaSpace 값은 일반적인 가우시안 필터링에서 사용하는 표준 편차와 같은 개념이다. 즉, 값이 클수록 더 많은 주변 픽셀을 고려하여 블러링을 수행한다.
    • sigmaColor 값은 주변 픽셀과의 밝기 차이에 관한 표준 편차이다. sigmaColor 값을 작게 지정할 경우, 픽셀 값 차이가 큰 주변 픽셀과는 블러링이 적용되지 않는다. 반면 sigmaColor 값을 크게 지정하면 픽셀 값 차이가 조금 크더라도 블러링이 적용된다. 즉, sigmaColor 값을 이용하여 어느 정도 밝기 차를 갖는 에지를 보존할 것인지를 조정할 수 있다.

미디언 필터

  • 미디언 필터(median filter)는 인력 영상에서 자기 자신 픽셀과 주변 픽셀 값 중에서 중간값(median)을 선택하여 결과 영상 픽셀 값으로 설정하는 필터링 기법
    • 미디언 필터는 마스크 행렬과 입력 영상 픽셀 값을 서로 곱한 후 모두 더하는 형태의 연산을 사용하지 않는다.
    • 미디언 필터는 주변 픽셀 값들의 중간값을 선택하기 위해 내부에서 픽셀 값 정렬 과정이 사용된다.
    • 미디언 필터는 특히 잡음 픽셀 값이 주변 픽셀값과 큰 차이가 있는 경우에 효과적으로 동작한다.
  • 아래 이미지는 3 x 3 정방형 마스크를 사용하는 미디언 필터 동작 방식을 나타낸 것이다.

  • OpenCV에서 medianBlur() 함수를 이용하여 미디언 필터링을 수행할 수 있다.
    • medianBlur() 함수는 ksize x ksize 필터 크기를 이용하여 미디언 필터링을 수행한다.
    • 다채널 영상인 경우 각 채널별로 필터링을 수행한다.
    • medianBlur() 함수는 내부적으로 BORDER_REPLICATE 방식으로 가장자리 외곽 픽셀 값을 설정하여 필터링을 수행한다.

OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝/ 영상의 산술 및 논리 연산

영상의 산술 연산

  • 영상은 일종의 2차원 행렬이기 때문에 행렬의 산술 연산(arithmetic operation)을 그대로 적용할 수 있다.
    • 즉 두 개의 영상을 서로 더하거나 빼는 연산을 수행함으로써 새로운 결과 영상을 생성할 수 있다.
    • 다만 영상을 서로 곱하거나 나누는 연산은 사용하지 않는다.
  • 두 개의 영상을 서로 더하는 덧셈 연산은 두 개의 입력 영상에서 같은 위치 픽셀 값을 서로 더하여 결과 영상 픽셀 값으로 설정하는 연산이다.

dst(x, y) = saturate(src1(x, y) + src2(x, y))

  • OpenCV에서는 add() 함수를 이용해서 영상의 덧셈을 수행할 수도 있다.
    • add 연산에서는 자동으로 포화 연산을 수행한다.
Mat src1 = imread("aero2.bmp", IMREAD_GRAYSCALE);
Mat src2 = imread("camera.bmp", IMREAD_GRAYSCALE);

Mat dst;
add(src1, src2, dst);
  • 만약 두 영상의 타입이 같다면 add() 대신 + 연산자 재정의를 사용할 수 있다.
Mat src1 = imread("aero2.bmp", IMREAD_GRAYSCALE);
Mat src2 = imread("camera.bmp", IMREAD_GRAYSCALE);

Mat dst = src1 + src2;
  • 두 영상을 더할 때 각 영상에 가중치를 부여하여 덧셈 연산을 할 수도 있다.

dst(x, y) = saturate(\alpha \cdot src1(x, y) + \beta \cdot src2(x, y))

  • OpenCV에서는 addWeighted() 함수를 이용해서 위와 같은 연산을 수행할 수 있다.
    • addWeighted() 함수는 gamma 인자를 통해 가중치의 합에 추가적인 덧셈을 한꺼번에 수행할 수 있다.

dst(x, y) = saturate(\alpha \cdot src1(x, y) + \beta \cdot src2(x, y) + \gamma)

Mat src1 = imread("aero2.bmp", IMREAD_GRAYSCALE);
Mat src2 = imread("camera.bmp", IMREAD_GRAYSCALE);

Mat dst;
addWeighted(src1, 0.5, src2, 0.5, 0, dst);
  • 덧셈과 마찬가지로 뺄셈도 할 수 있다.

dst(x, y) = saturate(src1(x, y) - src2(x, y))

  • OpenCV에서는 subtract() 함수를 통해 두 영상의 뺄셈 연산을 수행할 수 있다.
    • 만약 입력 영상의 타입이 같다면 subtract() 대신 – 연산자 재정의를 사용할 수도 있다.
  • 덧셈과 달리 뺄셈은 연산 순서에 따라 결과가 달라진다.

  • 두 영상의 뺄셈 순서에 상관없이 픽셀 값 차이가 큰 영역을 두드러지게 나타내고 싶다면 차이 연산을 수행하면 된다.
    • 차이 연산은 뺄셈 연산 결과에 절댓값을 취하는 연산이며, 차이 연산으로 구한 결과 영상을 차영상(difference image)라고 한다.

dst(x, y) = saturate(|src1(x, y) - src2(x, y)|)

  • OpenCV에서는 absdiff() 함수를 이용하여 차영상을 구할 수 있다.

영상의 논리 연산

  • 영상의 논리 연산(logical operation)은 픽셀 값을 이진수로 표현하여 각 비트(bit) 단위 논리 연산을 수행하는 것을 의미한다.
    • OpenCV에서는 다양한 논리 연산 중 논리곱(AND), 논리합(OR), 배타적 논리합(XOR), 부정(NOT) 연산을 지원한다.
입력 결과
a b a AND b a OR b a XOR b NOT a
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0

 

  • OpenCV에서 비트 단위 논리 연산을 수행하는 함수는 bitwise_and(), bitwise_or(), bitwise_xor(), bitwise_not()이다.
    • OpenCV는 영상의 비트 단위 논리 연산을 수행하는 연산자 재정의도 지원하므로 &, |, ^, ~ 등을 이용하여 연산할 수도 있다.

OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝/ 영상의 밝기와 명암비 조절

영상의 밝기 조절

그레이스케일 영상 다루기

  • 과거에 개발된 영상 처리 알고리즘이 주로 그레이스케일 영상을 대상으로 개발되었기 때문에, 특별히 컬러 정보를 이용해야 하는 경우가 아니면 컬러 영상도 그레이스케일 영상으로 변환해서 사용하는 경우가 많다.
    • 컬러 영상은 3개 채널을 갖고 있기 때문에 그레이스케일 영상보다 3배 더 수행 시간이 길다.

영상의 밝기 조절

  • 영상의 밝기(brightness) 조절이란 영상의 전체적인 밝기를 조절하여 좀 더 밝거나 어두운 영상을 만드는 작업으로, 영상의 밝기를 조절하려면 입력 영상의 모든 픽셀에 일정 값을 더하거나 빼는 작업을 수행한다.
  • 영상의 밝기 조절 수식은 다음과 같다.

dst(x, y) = src(x, y) + n

  • src는 입력 영상, dst는 출력 영상이다. n이 +면 밝기는 증가하고, -면 밝기는 감소한다.

  • 픽셀 값은 0-255 사이의 값을 갖기 때문에 255보다 큰 값이 나오면 255로 맞춰지고, 0보다 작은 값이 나오면 0으로 맞춰야한다. 이런 연산을 OpenCV에서는 포화(saturate) 연산이라고 한다.

saturate(x) = \begin{cases} 0 & x < 0 \\ 255 & x > 255 \\ x & otherwise \end{cases}

dst(x, y) = saturate(src(x, y) + n)

영상의 명암비 조절

기본적인 명암비 조절 방법

  • 명암비란 영상에서 밝은 영역과 어두운 영역 사이에 드러나는 밝기 차이의 강도를 의미하고, 명암 대비 또는 큰트라스트(contrast)라고 한다.
    • 영상이 전반적으로 어둡거나 전반적으로 밝은 픽셀로만 구성된 경우 명암비가 낮다고 하고 밝은 영역과 어두운 영역이 골고루 섞인 경우 명암비가 높다고 한다.
  • 밝기 조절이 영상의 모든 픽셀에 대해 덧셈 연산을 하는 것에 비해 명암비 조절은 곱셈 연산을 사용하여 구현한다.

dst(x, y) = saturate(s \cdot src(x, y))

  • src는 입력 영상, dst는 출력 영상이다. s는 0보다 큰 양의 실수로 s가 1보다 작은 경우 명암비가 낮아지고 1보다 큰 경우 명암비가 높아지는 효과가 있다.

효과적인 명암비 조절 방법

  • 명암비를 효과적으로 조절하려면 밝은 픽셀은 더욱 밝게, 어두운 픽셀은 더욱 어둡게 변경해야 한다.
    • 이때 픽셀 값이 밝고 어둡다는 기준은 그레이스케일 범위의 중간값인 128을 기준으로 하거나, 입력 영상의 평균 밝기를 구하여 기준으로 삼을 수도 있다.
    • 그레이스케일 범위의 중간값인 128을 기준으로 명암비를 조절하는 방식은 다음과 같다.

dst(x, y) = src(x, y) + (src(x, y) - 128) \cdot \alpha

  • \alpha 는 -1보다 크거나 같은 실수

히스토그램 분석

히스토그램 구하기

  • 영상의 히스토그램(histogram)이란 영사으이 픽셀값 분포를 그래프 형태로 표현한 것을 말한다.
    • 그레이스케일 영상의 경우, 각 그레이스케일 값에 해당하는 픽셀의 개수를 구하고 이를 막대 그래프로 표현함으로써 히스토그램을 구할 수 있다.
    • 컬러 영상일 경우 세 개의 색상 성분 조합에 따른 픽셀 개수를 계산하여 히스토그램을 구할 수 있다.
  • 아래와 같이 영상의 픽셀 정보가 주어졌다면 히스토그램은 그 오른쪽의 그래프와 같다.

  • 히스토그램 그래프에서 가로축을 히스토그램의 빈(bin)이라고 한다.
    • 고로 위 그림의 히스토그램에서 빈의 개수는 8개가 된다.
  • 히스토그램의 빈 개수가 항상 픽셀 값 범위와 같아야 하는 것은 아닌데, 경우에 따라 히스토그램의 빈 개수를 픽셀 값 범위보다 작게 설정할 수도 있다.
    • 예컨대 위 이미지의 8개의 밝기 값을 가질 수 있는 영상에서 히스토그램의 빈의 개수를 아래와 같이 4로 설정할 수도 있다.

  • OpenCV에서 영상의 히스토그램을 구할 때는 calcHist() 함수를 이용한다. 
    • calcHist() 함수는 한 장의 영상 뿐만 아니라 여러 장의 영상으로부터 히스토그램을 구할 수도 있고, 여러 채널로부터 히스토그램을 구할 수도 있고, 빈 개수를 조절할 수도 있다.
  • (calcHist() 함수에 대한 설명과 예제 코드 생략)

히스토그램 스트레칭

  • 히스토그램 스트레칭(histogram stretching)은 영상의 히스토그램이 그레이스케일 전 구간에 걸쳐서 나타나도록 변경하는 선형 변환 기법이다.
    • 보통 명암비가 낮은 영상은 시스토그램이 특정 구간에 집중되어 나타나게 되는데, 이러한 히스토그램을 고무줄 잡아 늘이듯이 펼쳐서 히스토그램 그래프가 그레이스케일 전 구간에서 나타나도록 변환하는 기법이다.
    • 히스토그램 스트레칭을 수행한 영상은 명암비가 높아지기 때문에 대체로 보기 좋은 사진이 된다.

dst(x, y) = { src(x, y) - G_{min} \over G_{max} - G_{min}} \times 255

  • 위 식에서 src와 dst는 각각 입력, 출력 영상을 의미하고, G_{max}, G_{min} 는 입력 영상의 픽셀 값 중에서 가장 큰 그레이스케일 값과 가장 작은 그레이스케일 값을 의미한다.
  • 아래 이미지는 왼쪽의 이미지를 히스토그램 스트레칭 하여 오른쪽의 결과를 얻은 것이다.

  • 히스토그램 스트레칭을 위한 함수는 OpenCV에서 제공하지 않는다.
    • 그러나 minMaxLoc() 함수 등을 이용하여 쉽게 구현할 수 있다.
void histogram_stretching()
{
Mat src = imread("hawkes.bmp", IMREAD_GRAYSCALE);

if (src.empty())
{
cerr << "Image load failed!" << endl;
return;
}

double gmin, gmax;
minMaxLoc(src, &gmin, &gmax);

Mat dst = (src - gmin) * 255 / (gmax - gmin);

imshow("src", src);
imshow("srcHist", getGrayHistImage(calcGrayHist(src)));
imshow("dst", dst);
imshow("dstHist", getGrayHistImage(calcGrayHist(dst)));

waitKey();
destroyAllWindows();
}

히스토그램 평활화

  • 히스토그램 평활화(histogram equalization)은 히스토그램 스트레칭과 더불어 영상의 픽셀 값 분포가 그레이스케일 전체 영역에서 골고루 나타나도록 변경하는 알고리즘의 하나이다.
    • 히스토그램 평활화는 히스토그램 그래프에서 특정 그레이스케일 값 근방에서 픽셀 분포가 너무 많이 뭉쳐 있는 경우 이를 넓게 펼쳐 주는 방식으로 픽셀 값 분포를 조절한다.
    • 히스토그램 평활화는 히스토그램 균등화 또는 히스토그램 평탄화라고도 한다.
  • 히스토그램 평활화를 구현하기 위해서는 먼저 히스토그램을 구해야 한다. 
    • 그레이스케일 영상의 히스토그램을 그레이스케일 값 g에 대한 함수 h(g)로 표현하면, h(g)는 영상에서 그레이스케일 값이 g인 픽셀 개수를 나타낸다.
    • 히스토그램 평활화를 계산하기 위해서는 h(g)로부터 히스토그램 누적 함수 H(g)를 구해야 한다. 히스토그램 누적 함수 H(g)는 다음 수식으로 정의된다.

H(g) = \sum_{0 \leq i \leq g} h(i)

  • 히스토그램 평활화는 이 히스토그램 누적 함수 H(g)를 픽셀 값 변환 함수로 사용한다. 다만 H(g) 값의 범위가 보통 그레이스케일 값의 범위(0~255) 보다 훨씬 크기 때문에 H(g) 함수의 최댓값이 255가 되도록 정규화 과정을 거쳐야 한다.
    • 만약 입력 영상의 픽셀 개수를 N이라고 표기하면 히스토그램 평활화는 다음과 같이 정의 된다.

dst(x, y) = round(H(src(x,y)) \times {L_{max} \over N})

  • 위 식에서 L_{max} 는 영상이 가질 수 있는 최대 밝기 값을 의미하며 일반적인 그레이스케일 영상의 경우 L_{max} = 255 이다.
    • round()는 반올림 함수
  • 아래 이미지의 (a)와 같이 4 x 4 크기의 영상이 0~7 사이의 밝기를 가졌다고 가정하고, 이 영상으로부터 구한 히스토그램 h(g)와 히스토그램 누적 함수 H(g)를 표로 나타내면 아래 이미지의 (b)가 된다.
    • 영상의 픽셀 개수가 16개이므로 H(7)에 해당하는 값이 16인 것을 확인할 수 있다.
    • 테스트로 사용한 영상은 최대 밝기 값이 7이고 전체 픽셀 개수가 16이므로 정규화를 위한 상수는 7/16을 사용해야 한다. 즉, H(g)에 7/16을 곱한 값을 결과 영상의 픽셀 값으로 설정한다.
    • 다만 H(g)에 7/16을 곱한 결과가 실수로 계산되기 때문에 이를 반올림하여 결과 영상의 픽셀 값으로 설정한다.
    • 이러한 연산 과정을 나타낸 것이 아래 이미지의 (c)이다.
    • 최종 평활화 과정을 거친 결과는 (d)를 통해 확인할 수 있다.

  • OpenCV는 그레이스케일 영상의 히스토그램 평활화를 수행하는 equalizeHist() 함수를 제공한다.
    • equalizeHist() 함수는 CV_8UC1 타입을 사용하는 그레이스케일 영상만 입력으로 받는다.
void histogram_equalization()
{
Mat src = imread("hawkes.bmp", IMREAD_GRAYSCALE);

if (src.empty())
{
cerr << "Image load failed!" << endl;
return;
}

Mat dst;
equalizeHist(src, dst);

imshow("src", src);
imshow("srcHist", getGrayHistImage(calcGrayHist(src)));
imshow("dst", dst);
imshow("dstHist", getGrayHistImage(calcGrayHist(dst)));

waitKey();
destroyAllWindows();
}

이상엽/ 수학적 벡터 (벡터공간)

대수구조

대수구조

수 뿐만 아니라 수를 대신할 수 있는 모든 것을 대상으로 하는 집합과 그 집합에 부여된 연산이 여러 가지 공리로써 엮인 수학적 대상.

간단히 일련의 연산들이 주어진 집합을 대수구조라고 한다.

여러 대수구조

  • 집합: 아무런 연산이 부여되지 않은 대수구조
  • 반군: 집합과 그 위의 결합법칙을 따르는 하나의 이항 연산을 갖춘 대수구조
  • 모노이드: 항등원을 갖는 반군
  • 군: 역원을 갖는 모노이드
  • 아벨군(가환군): 교환법칙이 성립하는 군
    • 아벨군이 되면 1종류의 이항 연산에 대해 4개의 기본 연산을 만족하게 됨. (결합법칙/교환법칙/항등원/역원)
  • 환: 덧셈에 대하여 아벨군, 곱셈에 대하여 반군을 이루고 분배법칙이 성립하는 대수구조
    • 환부터는 2종류의 이항 연산이 부여 됨.
    • 1종류의 이항 연산은 아벨군을 만족해야 하고, 나머지 1종류의 이항 연산은 반군을 만족 시켜야 함.
  • 가군: 어떤 환의 원소에 대한 곱셈이 주어지며, 분배법칙이 성립하는 아벨군
    • 벡터공간은 가군의 한 종류
    • 가군은 환에서 원소를 받는게 기본이지만, 벡터공간은 보다 엄격하게 체에서 원소를 받아 온다.
  • 가환환: 곱셈이 교환법칙을 만족하는 환
    • 환 중에 반군을 만족 시키는 나머지 1종류의 연산이 추가로 교환 법칙을 만족. 하지만 항등원과 역원은 존재하지 않는다.
  • 나눗셈환: 0이 아닌 모든 원소가 역원을 가지며, 원소의 개수가 둘 이상인 환
    • 환 중에 반군을 만족 시키는 나머지 1종류의 연산이 항등원과 역원을 가짐. 하지만 교환 법칙은 만족하지 않는다.
  • 체: 가환환인 나눗셈환. 즉, 사칙연산이 자유로이 시행될 수 있고 산술의 잘 알려진 규칙들을 만족하는 대수구조
    • 2종류의 이항연산이 모두 4개의 기본연산을 만족 함.

(\mathbb{R}, *), (V, +, \cdot) -> 이런식으로 표기되면 대수구조가 된다. 대상이 되는 집합을 정의하고 그 집합에 적용되는 연산에 대한 정의가 되면 대수구조가 된다.

환 이전까지는 연산의 종류가 1종류이고 환 이후로 체까지는 연산의 종류가 2가지가 됨. 연산의 종류가 3개 이상인 경우도 있으나 여기서는 생략.

벡터공간

벡터공간

F 에 대한 가군 (V, +, \cdot) 을 벡터공간, V의 원소의 벡터라 한다.

이때 + 는 벡터의 덧셈이고, \cdot 는 벡터의 스칼라배이다.

  • 참고)
    • + : V \times V \to V 인 함수
    • \cdot : F \times V \to V 인 함수
  • (V, +) 는 아벨군이다. (u, v, w \in V)
    • (u + v) + w = u + (v + w)
    • u + v = v + u
    • u + \vec{0} = u \vec{0} V 에 존재한다.
    • u + (-u) = \vec{0} -u V 에 존재한다.
  • (V, +, \cdot) F 의 가군이다. (k, m \in F)
    • k \cdot (m \cdot u) = (km) \cdot u
    • F 의 곱셈 항등원 1에 대해 1 \cdot u = u
    • (k + m) \cdot (u + v) = k \cdot u + m \cdot u + k \cdot v + m \cdot v

수학적으로 벡터란 벡터공간의 원소를 의미함. 벡터공간이란 벡터 대수구조를 만족하는 것을 의미. –아래 예시와 같이 덧셈 연산을 곱셈으로, 곱셈 연산을 지수 연산으로 바꾸어도 벡터 대수구조를 만족하므로 벡터 공간이 된다. 고로 그 집합에 속하는 원소 또한 벡터가 됨–

방향 같은 개념은 수학적인 벡터의 고려 대상이 아님. 그러나 이와 같은 정의가 만족되면 물리적인 벡터에 대해서도 동일하게 적용이 가능. 물리적인 벡터 개념에서 엄밀한 개념만 남긴 것이 수학적 벡터 개념.

  • ex)
    • 벡터에 대한 집합과 다음과 같이 정의할 때
      • V = \{ x | x \in \mathbb{R}, x > 0 \}
      • F = \mathbb{R}
      • + : V \times V \to V, u + v = uv
        • +를 곱셈으로 정의
        • V의 원소와 V의 원소에 대한 +을 하면 그 결과가 V가 나온다.
      • \cdot = F \times V \to V, k \cdot u = u^{k}
        • \cdot 을 지수곱으로 정의
        • F의 원소와 V의 원소에 대한 \cdot 을 하면 그 결과가 V가 나온다.
    • 이와 같은 정의 또한 벡터공간의 대수구조를 만족하므로 벡터공간이라 할 수 있다.
      • (V, +) 는 아벨군이 되고, (V, +, \cdot) 은 가군이 된다.

선형생성

부분벡터공간

벡터공간 V 상에서 정의된 덧셈과 스칼라배에 대하여 그 자체로서 벡터공간이 되는 V 의 부분집합 W V 의 부분벡터공간 또는 부분공간이라 한다.

선형생성

벡터공간 V 의 공집합이 아닌 부분집합 S = \{ v_{1}, v_{2}, ... , v_{n} \} 내의 벡터들의 가능한 모든 선형결합으로 이루어진, V 의 부분벡터공간을 S 의 (선형)생성 span(S) 이라 한다. 즉,

span(S) = \{ \sum_{i = 1}^{n} k_{i} v_{i} | k_{i} \in F, v_{i} \in S \}

이때 S span(S) 을 (선형)생성한다 라고 한다.

  • ex)
    • S = { (1, 0), (0, 1) }, F = \mathbb{R} 라 할 때 –S는 (1, 0), (0, 1)의 벡터를 가진 집합
    • span(S) = \{ k(1, 0) + m(0, 1) | k, m \in F \} 
    • = \{ (k, m) | k, m \in F \}
    • = \mathbb{R}^{2}
    • S라는 집합은 2차원 실수 벡터 공간을 생성한다. (= (1, 0), (0, 1) 이라는 벡터 2개만 있으면 2차원 실수 벡터 공간을 만들 수 있다)

선형 독립

벡터공간 V 의 공집합이 아닌 부분집합 S = \{ v_{1}, v_{2}, ... , v_{n} \} 에 대하여

k_{1} v_{1} + k_{2} v_{2} + ... + k_{n} v_{n} = \vec{0} \\ \Rightarrow k_{1} = k_{2} = ... = k_{n} = 0

이면 S 가 선형독립이라고 한다. 만약 k_{1} = k_{2} = ... = k_{n} = 0 외의 다른 해가 존재하면 S가 선형종속이라고 한다.

  • ex)
    • S_{1} = { (1, 0), (0, 1), (1, 1) } 라 할 때
      • k_{1}(1, 0) + k_{2}(0, 1) + k_{3}(1, 1) = \vec{0} 를 만족하는 K의 값은
      • k_{1} = k_{2} = k_{3} = 0 \\ k_{1} = k_{2} = 1, k_{3} = -1 ... 과 같이 모든 k가 0이지 않은 해가 존재하므로 S_{1} 은 선형종속집합이 된다.
    • S_{2} = { (1, 0), (0, 1) } 라 할 때
      • k_{1}(1, 0) + k_{2}(0, 1) = \vec{0} 를 만족하는 K의 값은
      • k_{1} = k_{2} = 0 뿐이므로 S_{2} 은 선형독립집합이 된다.

여러 벡터공간

노름공간

노름이 부여된 K-벡터공간 (V, \|\cdot\|)

노름이란 \forall u, v \in V, \forall k \in K 에 대해 아래 세 조건을 만족시키는 함수

\|\cdot\| : V \to [0, \infty) 이다. (K \in \{ \mathbb{R}, \mathbb{C}\})

  • \|kv\| = |k|\|v\|
  • \|u + v\| \leq \|u\| + \|v\|
  • \|v\| = 0 \Leftrightarrow v = \vec{0}

내적공간

내적이 부여된 K-벡터공간 (V, <\cdot, \cdot>)

내적이란 \forall u, v, w \in V, \forall k \in K 에 대해 아래 네 조건을 만족시키는 함수

<\cdot, \cdot> : V \times V \to K 이다. (K \in \{ \mathbb{R}, \mathbb{C}\})

  • <u + v, w> = <u, w> + <u, w>
  • <ku, v> = k<v, u>
  • <u, v> = <\overline{v, u}>
    • (복소수체 일 때는 위에 바가 붙고, 실수에서는 붙지 않는다)
  • v \neq \vec{0} \Rightarrow <v, v> > 0

유클리드공간

음이 아닌 정수 n 에 대하여 n 차원 유클리드공간 R^{n} 은 실수집합 R n 번 곱집합이며, 이를 n 차원 실수 벡터공간으로써 정의하기도 한다.

이 위에 내적 <u, v> = \sum_{i=1}^{n} u_{i} v_{i} = u \cdot v 을 정의하면 점곱, 스칼라곱이라고도 한다.

기저와 차원

기저

벡터공간 V 의 부분집합 B 가 선형독립이고 V 를 생성할 때, B V 의 기저라 한다.

  • ex)
    • V = \mathbb{R}^{2}
    • B_{1} = \{ (1, 0), (0, 1) \} 일 때
      • \Rightarrow span(B_{1}) = \mathbb{R}^{2}  
      • \therefore B_{1} V 의 기저
    • B_{2} = \{ (1, 0), (1, 1) \} 일 때
      • (a, b) = k(1, 0) + m(1, 1) = (k+m, m)
      • \therefore m = b, k = a - b  
      • \therefore B_{2} V 를 생성할 수 있고 선형독립이므로 V 의 기저가 된다.
    • S = \{ (1, 0), (0, 1), (1, 1) \} 일 때
      • span(S) = \mathbb{R}^{2} 를 만족하지만, 선형독립이 아니므로 S V 의 기저가 안 된다.

차원

B 가 벡터공간 V 의 기저일 때 B 의 원소의 개수를 V 의 차원 dim(V) 라 한다.

  • ex)
    • 앞선 예에서 B_{1}, B_{2} V 의 기저이고 B_{1}, B_{2} 의 원소의 개수는 2개이므로 V 는 2차원이 된다.

정규기저

다음 조건을 만족하는 노름공간 V 의 기저 B 를 정규기저라 한다.

\forall b \in B, \|b\| = 1

직교기저

다음 조건을 만족하는 내적공간 V 의 기저 B 를 직교기저라 한다.

\forall b_{1}, b_{2} \in B, <b_{1}, b_{2}> = 0

정규직교기저

정규기저이자 직교기저인 내적공간의 기저를 정규직교기저라 한다.

특히 R^{n} 의 정규직교기저 

\{ (1, 0, ... , 0), (0, 1, ... , 0), ... , (0, 0, ... , 1) \}

를 표준기저라 한다.

  • ex) R^{2} 에 대하여
    • B_{1} = \{ (1, 0), (0, 1) \} 는 정규기저도 아니고 직교기저도 아니다.
    • B_{2} = \{ (1, 0), ({1 \over \sqrt{2}}, {1 \over \sqrt{2}}) \} 는 정규기저지만 직교기저는 아니다.
    • B_{3} = \{ (1, 1), (1, -1) \} 는 정규기저는 아니지만 직교기저이다.
    • B_{4} = \{ (1, 0), (0, 1) \} 는 정규기저이고 직교기저이다. 이를 특별히 표준기저라고 한다.

[유튜브] 카오스 사이언스

대중을 위한 교양 과학 컨텐츠를 만드는 KAOS의 유튜브 채널. –개인적으로 복잡계를 좋아해서 이름도 참 마음에 든다.

전문 과학 채널 답게 과학적 사실을 최대한 정확히 전달하고자 하면서, 대중이 이해하기 쉽도록 편집도 잘 되어 있다.

19.09.22

‘얼굴 인식’ 인공지능으로 암흑물질 탐색

‘약한 중력 렌즈(weak gravitational lensing)’로 알려진 이 효과는 은하들의 이미지를 매우 미묘하게 왜곡한다. 이는 마치 뜨거운 날 먼 곳에 있는 물체가 흐리게 보이는 것과 같은 이치다. 빛이 온도가 다른 공기층을 통과할 때 왜곡되기 때문이다. (중략)

이들은 논문 제1저자이자 레프리기아 교수실 박사과정생 야니스 플루리(Janis Fluri) 연구원과 함께 심화 인공신경망으로 불리는 기계학습 알고리즘을 사용해 암흑 물질 지도에서 가능한 한 최대치의 정보량을 추출하도록 학습시켰다. (중략)

이 훈련 결과는 매우 고무적이었다. 신경망은 사람이 만든 통계 분석에 기초한 전통적인 방법으로 얻은 값보다 30% 더 정확한 값을 산출했다. 연구자들에게 이는 커다란 개선으로서, 마치 망원경 수를 두 배로 늘리고 비용과 시간을 많이 들여 관측의 정확성을 높이는 것과 같다.

자동차도 증기기관으로 달리는 차가 나오고(1776년), 사람이 탈만한 속도가 나오는 가솔린 차가 벤츠에서 출시되기까지(1886년) 무려 100년이 더 걸렸다. AI도 지금은 이미지 인식 정도지만 수십 년 후에는 누구나 일상적으로 AI –보다 엄밀히 말하면 좀 더 복잡한 영역에 대한 자동화– 의 도움을 받는 시대가 될 것이다.

50대 사건으로 보는 돈의 역사

현직 이코노미스트가 쓴 돈과 관련한 경제 역사 요양서.

개인적으로 문명화 후 인류의 역사는 먹고 사는 문제, 다시 말해 부의 흐름 –이념이 아니라– 이었다고 생각하기 때문에, 부를 통한 역사를 이해가 중요하다고 생각하는데, 내 생각에 딱 맞는 책이 없어서 아쉽다. –예전에 읽었던 <금융으로 본 세계사>도 아쉬웠음.

이 책도 네덜란드에서 주식 시장이 열렸던 시점 이후를 주로 다루고 있기 때문에, 그 이전 시기의 부의 대해 기대한다면 아쉬울 수 있음. 

그래도 개괄적이고 나름 의미 있는 내용들이 담겨 있기 때문에 가볍게 본다면 괜찮은 책이라고 생각 됨.