CS과목/디지털영상처리

[디지털영상처리] 02. 디지털 영상 기초

johyeongseob 2024. 9. 22. 15:57

교재:디지털영상처리 제3판 (2013, Rafael C. Gonzalez)

 

2.3 영상 감지 및 획득

 우리가 관심을 갖는 대부분의 영상들은 "조명" 원과, 영상화되는 "장면"의 요소들에 의한 조명 원으로부터의 에너지의 반사 또는 흡수의 결합에 의해 생성된다.

 

2.3.4 간단한 영상 형성 모델

 우리는 영상을 f(x,y) 형태의 2-D 함수로 표기한다. 공간 좌표 (x,y)에서의 f의 값 또는 진폭은 물리적 의미가 영상의 광원에 의해 결정되는 양의 스칼라량이다. 물리적 과정으로부터 영상이 생성될 때, 그 밝기 값들은 물리적 광원에 의해 방사되는 에너지에 비례한다. 그 결과, f(x,y)는 0이 아니고 유한해야 한다. 즉, $0 < f(x,y) < \infty$이다. 함수 f(x,y)는 두 성분에 의해 특정지어질 수 있다.

  1. 관찰되는 장면에 입사하는 광원 조명의 양
  2. 장면의 객체에 의해 반사되는 조명의 양.

이들은 각각 조명 성분 반사 성분이라고 불리며 i(x,y)와 r(x,y)로 표기된다. 이 두 함수가 곱해져서 f(x,y)를 형성한다. $f(x,y)=i(x,y) \times r(x,y)$여기서 0 < i(x,y) < $\infty$, 0 < r(x,y) < 1이다. 반사 성분은 반사가 0(완전 흡수)과 1(완전 반사)에 의해 제한됨을 나타낸다. i(x,y)의 특성은 조명원에 의해 결정되며, r(x,y)는 영상화된 객체의 특성에 의해 결정된다.

 

2.4 영상 샘플링 및 양자화

 우리의 목표는 감지된 데이터로부터 디지털 영상을 만다는 것이다. 대부분의 센서들의 출력은 연속적 전압 파형으로서, 그 진폭과 공간 특성이 감지되는 물리적 현상과 관련된다. 디지털 영상을 만들기 위해서 감지된 연속적 데이터를 디지털 형태로 전환시켜야 한다. 이것은 두 과정을 포함한다: 샘플링(smapling, 표본화) 양자화(quantization)

 

2.4.1 샘플링과 양자화의 기본 개념

 영상은 x-좌표와 y-좌표에 대해 연속적일 수 있으며, 진폭에서도 그렇다. 디지털 형태로 전환시키기 위해서는 함수를 좌표와 진폭 모두에서 샘플링해야 한다. 좌표 값들을 디지털화하는 것을 샘플링이라고 부르며, 진폭 값들을 디지털화하는 것을 양자화라고 부른다. 디지털 함수를 형성하기 위해서는 밝기 값들도 이산적 수량으로 전환(양자화)되어야 한다. 디지털 영상의 품질은 샘플링과 양자화에 사용된 샘플 및 이산 밝기 레벨 수에 의해 거의 결정된다.

 

2.4.2 디지털 영상 표현

 연속 영상은 M개 행과 N개 열을 포함하는 2-D 배열 f(x,y)로 샘플링한다고 하자. 여기서 (x,y)는 이산 좌표들이다. x와 y는 정수이다. 영상의 좌표들에 의해 표현되는 실수 평면 영역을 공간 도메인이라고 부른다. 그리고 x와 y를 공간 변수 또는 공간 좌표라고 부른다. 영상 표시를 매트릭스로 표현하는 수치 배열을 처리 및 알고리즘 개발을 위해 사용된다. 이 매트릭스의 각 요소는 화소(image element, picture element, pixel, pel)라고 부른다. 이 책에서는 디지털 영상과 그 요소들을 표기하는 데 영상 화소라는 용어들을 쓴다. 디지털 영상의 원점이 왼쪽 위에 있으며, x-축의 양의 방향은 아래쪽이고, y-축은 오른쪽으로 향해 있다. 이것은 많은 영상 표시기들이 왼쪽 위에서 시작해서 오른쪽으로 이동하면서 한 번에 한 행씩 영상을 주사한다는 사실에 기반한 관습적인 표현이다. 이 디지털화 과정에서 M, N 값들과 이산적 밝기 레벨 수 L 값이 결정되어야 한다. M과 N에 대해서는 양의 정수이어야 한다는 것 외에는 아무런 제약이 가해지지 않는다. 그러나 저장장치와 양자화 하드웨어 문제로 인해, 밝기 레벨 수는 대개 2의 정수 거듭제곱 수이다: $L=2^k$

 

2.4.3 공간 및 밝기 해상도 

 직관적으로, 공간 해상도는 영상에서의 식별 가능한 가장 작은 디테일의 척도이다. 정량적으로, 공간 해상도는 다양한 방법으로 기술될 수 있는데, 그중 단위 거리당 선 쌍 수, 단위 거리당 점(화소) 수 등이 가장 보편적인 척도이다. 비슷하게, 밝기 해상도는 밝기 레벨에서의 식별 가능한 가장 작은 변화를 기리킨다. 하드웨어 이유 때문에, 밝기 레벨 수는 일반적으로 2의 정수 멱승이다. 가장 흔한 숫자는 8 비트이며, 16 비트가 특정 밝기 범위의 개선이 필요한 일부 응용에서 사용되고 있다.

 

2.6 디지털 영상 처리에 사용되는 수학적 도구들의 소개

2.6.5 공간 연산

 공간 연산은 주어진 영상의 화소들에 직접 실행된다. 기하적 공간 변환에서 가장 많이 쓰이는 공간 좌표 변환 중 하나는 다음과 같은 일반 형태를 갖는 어파인 변환(affine transformation)이다.

항등:             [1 0 0; 0 1 0; 0 0 1]

스케일링:      [Cx 0 0; 0 Cy 0; 0 0 1]

회전:             [cosθ sinθ 0; -sinθ cosθ 0; 0 0 1]

이동:             [1 0 0; 0 1 0; tx ty 1]

쏠림(수직):    [1 0 0; Sv 1 0; 0 0 1]

쏠림(수평):    [1 Sh 0; 0 1 0; 0 0 1]

다음 매트릭스 식의 진정한 힘은 일련의 연산들을 이어 붙이기 위한 프레임워크를 제공한다는 것이다.

 실제에서는 위 식들을 두 가지 기본적 방법으로 사용할 수 있다. 첫 번째는 순방향 매핑으로 불리며, 입력 영상의 화소들을 스캔하고 각 위치 (v, w)에서 식들을 직접 이용해서 출력 영상의 대응 화소의 공간 위치 (x,y)를 계산하는 것으로 구성된다. 순방향 매핑 접근법의 문제는, 여러 출력 값들이 한 출력 화소로 합쳐질 수 있어서, 입력 영상에서의 둘 이상의 화소들이 출력 영상에서 같은 위치로 변환될 수 있다는 것이며, 그에 따라 여러 출력 값들을 하나의 출력 화소로 어떻게 결합시키느냐 하는 문제가 생긴다. 또한 어떤 출력 위치에는 화소가 전혀 할당되지 않을 수도 있다. 두 번째 접근법은 역방향 매핑으로 불리며, 출력 화소 위치들을 스캔하고, 각 위치 (x, y)에서 $(v,w) = T^{-1}(x,y)$를 이용해서 입력 영상에서의 대응 위치를 계산한다. 그러고 나서 출력 화소 값의 밝기를 결정하기 위해 최근접 입력 화소들에 대해 보관법을 사용한다. 역방향 매핑이 순방향 매핑보다 구현에 더 효율적이며, 많은 상용 공간 변환 구현에 사용된다.

 

2.6.6 벡터 연산과 매트릭스 연산

 다중 스펙트럼 영상 처리는 벡터 및 매트릭스 연산들이 고정적으로 사용되는 대표적인 분야이다. 예를 들면, RGB 영상의 각 화소가 아래의 열 벡터 형태로 구성될 수 있는 세 개의 성분을 가짐을 볼 수 있다. 

z = [z1; z2; z3] 여기서 z1은 적색 영상의 화소 밝기이며, 나머지 두 요소는 각각 녹색과 청색 영상의 대응 화소 밝기들이다. 따라서 M x N 크기의 RGB 칼라 영상은 이 크기의 세 개의 성분 영상 또는 총 MN개의 3-D 벡터로 표현될 수 있다. 화소가 벡터로 표현되고 나면, 벡터-매트릭스 이론의 도구들을 임의로 쓸 수 있다. 예를 들어 n-차원 공간에서 화소 벡터 z와 임의의 점 a 간의 Euclid거리 D는 다음의 벡터 곱에 의해 정의된다. $D(z,a)=\sqrt{(z-a)^T \times (z-a)}$ 다음 식은 벡터 놈(vector norm)으로 불리기도 하며, ||z-a||로 표기된다.

 

Assignment #1: Backward rotation 구현

import cv2
import numpy as np

def bw(img, angle):
    height, width = img.shape
    result = np.zeros((height, width), np.uint8)

    affine = np.array([[np.cos(np.radians(angle)), -np.sin(np.radians(angle)), 0],
                       [np.sin(np.radians(angle)), np.cos(np.radians(angle)), 0],
                       [0, 0, 1]])
    
    # Inverse affine transformation matrix
    inv_affine = np.linalg.inv(affine)

    for x in range(width):
        for y in range(height):
            # Using Affine's inverse matrix to calculate where the pixel was in the original image
            p = inv_affine.dot(np.array([x, y, 1]))
            
            xp = int(p[0])
            yp = int(p[1])

            if 0 <= yp < height and 0 <= xp < width:
                # Gets the value of the calculated source image and assigns it to the current pixel of the resulting image
                result[y, x] = img[yp, xp]

    return result

dgu_gray = "your image address"
in_image = cv2.imread(dgu_gray, 0)  # img2numpy

out_image = bw(in_image, 20)