Skip to main content

이미지 연산

이미지 덧셈

  • 일괄적으로 모든 픽셀에 100을 더하기 (결과가 255보다 크면 255)
    cv.add(image, 100)
  • 덧셈의 결과 보기(이하의 코드에서도 결과를 보려면 show()를 추가)
    show(cv.add(image, 100))
  • 두 개의 이미지 더하기
    chair = cv.imread('chair.webp')
    explosion = cv.imread('explosion.webp')
    cv.add(chair, explosion)
  • 가중치를 곱하여 더하기(2:8로 더하고 일괄적으로 10 더함)
    cv.addWeighted(chair, 0.2, explosion, 0.8, 10)

이미지 뺄셈

  • 일괄적으로 모든 픽셀에 100을 빼기(결과가 0보다 작으면 0)
    cv.subtract(image, 100)
  • 두 개의 이미지 빼기
    black_circle = cv.imread('black_circle.png')
    cv.subtract(chair, black_circle)
  • 두 개의 이미지 차이의 절대값(순서에 영향 X)
    cv.absdiff(chair, explosion)
    cv.absdiff(explosion, chair)

이미지 곱셈과 나눗셈

  • 곱셈
    cv.multiply(image, 3.0) # 3.0을 곱하면 모든 픽셀의 밝기가 3배 밝아짐
  • 나눗셈
    cv.divide(image, 3.0) # 3.0으로 나누면 모든 픽셀의 밝기가 1/3으로 어두워짐
  • 색 반전
    255 - image

컬러 스페이스

  • 색을 표현하는 방법
  • RGB: 빛의 삼원색인 빨강(R), 초록(G), 파랑(B)을 사용
    • 과거에는 BGR이 널리 쓰이다, 현재는 RGB로 주류가 바뀜
    • OpenCV는 BGR이 주로 쓰이던 시절에 개발되어 BGR이 기본
  • HSV:
    • 색상(Hue): 빨강, 파랑, 노랑 등
    • 채도(Saturation): 진하다, 흐리다
    • 명도(Value): 밝다, 어둡다
  • Gray: 흑백

컬러 스페이스 바꾸기

  • BGR에서 흑백으로
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
  • 흑백 이미지는 PIL 형식으로 바꿀 때 show 대신 Image.fromarray만으로도 됨 (채널이 1개 뿐임)
    • show(gray)도 됨
    Image.fromarray(gray)
  • 흑백에서 BGR로(눈에 보이는 색은 바뀌지 않음)
    cv.cvtColor(gray, cv.COLOR_GRAY2BGR)
  • BGR에서 HSV로
    hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)

채널 분리

  • BGR 채널을 분리
    b, g, r = cv.split(image)
  • B 채널만 보기(흑백으로 보임)
    Image.fromarray(b)
  • GR 채널을 0으로 채우면 파란색으로 볼 수 있음
    z = np.zeros_like(b) # b와 같은 모양의 0으로 가득찬 배열
    show(cv.merge((b, z, z))) # 초록과 빨강은 0으로 채워서 합침

특정 색상만 추출

  • HSV에서 H가 40-80 사이, SV는 50-255 사이인 부분만 추출
    lower = np.array([40, 50, 50])
    upper = np.array([80, 255, 255])
    mask = cv.inRange(hsv, lower, upper)
    Image.fromarray(mask)
  • 원래 이미지에서 mask 부분만 보기
    cv.bitwise_and(image, image, mask=mask)

비트와이즈 AND

  • 각각의 비트를 비교하여 비트 단위로 AND 연산
    a = 10
    bin(a) # 이진수 1010
    aa = np.array(a) # 배열로 바꿈

    b = 12
    bin(b) # 이진수 1100
    bb = np.array(b)

    cc = cv.bitwise_and(aa, bb)
    c = cc.item() # cc == 8
    bin(c) # 이진수 1000
자리abAND
8의 자리111
4의 자리010
2의 자리100
1의 자리000

비트와이즈 OR과 XOR

  • 각각의 비트를 비교하여 비트 단위로 OR 연산
    dd = cv.bitwise_or(aa, bb)
    d = dd.item() # dd == 14
    bin(d) # 이진수 1110
자리abOR
8의 자리111
4의 자리011
2의 자리101
1의 자리000
  • 각각의 비트를 비교하여 비트 단위로 XOR 연산
    ee = cv.bitwise_xor(aa, bb)
    e = ee.item() # dd == 6
    bin(e) # 이진수 0110
자리abXOR
8의 자리110
4의 자리011
2의 자리101
1의 자리000

마스크

  • 마스크를 적용할 경우, 마스크에 색이 존재하는(1보다 큰) 영역에서만 비트와이즈 연산을 적용
    src = np.array([[10, 12]])
    mask = np.array([[1, 0]], dtype=np.uint8)

    # mask가 없으면 10과 10, 12와 12의 비트와이즈 AND 연산
    cv.bitwise_and(src, src)

    # mask가 있으면, mask 값이 0보다 큰 10과 10만 비트와이즈 AND 연산
    cv.bitwise_and(src, src, mask=mask)

퀴즈