알파 채널이 있는 png를 투명 이미지로 붙여넣기 with Python/OpenCV

TL; DR


bg.jpg 의 왼쪽 상단에 png_image.png (알파 채널이 있는 이미지)를 겹치는 경우의 코드입니다.
import cv2

frame = cv2.imread("bg.jpg")
png_image = cv2.imread("alpha.png", cv2.IMREAD_UNCHANGED)  # アルファチャンネル込みで読み込む

# 貼り付け先座標の設定。とりあえず左上に
x1, y1, x2, y2 = 0, 0, png_image.shape[1], png_image.shape[0]

# 合成!
frame[y1:y2, x1:x2] = frame[y1:y2, x1:x2] * (1 - png_image[:, :, 3:] / 255) + \
                      png_image[:, :, :3] * (png_image[:, :, 3:] / 255)


bg.jpg
alpha.png
결과







간단한 해설



PNG 파일에는 "알파 채널"이라는 각 픽셀의 투명도를 나타내는 데이터가 들어 있습니다. 값 범위는 RGB와 마찬가지로 0-255입니다. 255일 때 100% 유효하고 0일 때 0%(완전 투명)입니다.
# 画像の読み込み
png_image = cv2.imread("alpha.png", cv2.IMREAD_UNCHANGED)  # アルファチャンネル込みで読み込む

보통 cv2.imread() 에서는 [h, w, 3]numpy.ndarray 의 형태가 됩니다만, cv2.IMREAD_UNCHANGED 를 지정해 cv2.imread() 를 호출하면, [h, w, 4] 의 형태가 됩니다. BGRBGRA 와 마지막에 알파 채널이 붙습니다.

이미지를 불러오면 합성합니다. 그렇다고해도, NuPy 의 통상의 행렬 연산으로 합성 가능합니다. 하고 있는 것은, 원래의 배경 화상·묘화하는 화상을, 각각 알파 채널의 수치로 배분해, 더해 놓고 있습니다.
# 合成!
frame[y1:y2, x1:x2] = frame[y1:y2, x1:x2] * (1 - png_image[:, :, 3:] / 255) + \
                      png_image[:, :, :3] * (png_image[:, :, 3:] / 255)
png_image[:, :, 3:] 가 알파 채널의 추출입니다. 알파 채널의 값 영역은 0-255이므로 255로 나누어 0-1의 비율로 합니다. 그리는 이미지에는 계산된 비율을 곱하고 배경 쪽에는 비율의 "남은"을 곱하여 양자를 더하여 최종 이미지를 얻을 수 있습니다.

그건 그렇고, png_image[:, :, 3]라고 쓰면 행렬의 크기가 맞지 않으면 화가 나므로주의하십시오 (잘못되었습니다).

여록



여러가지 참고가 되는 사이트는 있으면서, 그 자체 즈바리인 코드를 잘 검색할 수 없었기 때문에, 기사를 만들어 보았습니다. (당연히 너무 오히려 쓰지 않을 수도 있습니다)

참고로 한 사이트


  • OpenCV에서 알파 채널이 있는 PNG 보기 - Qiita
  • Python, OpenCV, NumPy로 이미지 알파 블렌딩 및 마스크 처리 | note.nkmk.me

  • 이미지는 귀여운 무료 소재 모음 소재를 사용했습니다.

    좋은 웹페이지 즐겨찾기