픽셀
기본적으로 디지털 사진은 픽셀이라 부르는 2차원 좌표 평면에 분포된다. 이미지 너비 X 이미지 높이가 이미지에 포함된 픽셀 개수이며, 이를 이미지 크기라 부른다.
(0, 0) | (0, 1) | (0, 2) | (0, 3) |
(1, 0) | (1, 1) | (1, 2) | (1, 3) |
(2, 0) | (2, 1) | (2, 2) | (2, 3) |
(3, 0) | (3, 1) | (3, 2) | (3, 3) |
(openCV 좌표)
픽셀의 데이터는 데이터의 타입이 뭐냐에 따라 다르다. 컬러인 경우 삼원색에 해당하는 b,g,r인 3개의 channel이 열린다. 흑백인 경우 1개 channel만 열린다.
(0, 0, 0) | (255, 0, 0) | (0, 255, 0) | (0, 0, 255) |
(0, 0, 0) | (255, 0, 0) | (0, 255, 0) | (0, 0, 255) |
(0, 0, 0) | (255, 0, 0) | (0, 255, 0) | (0, 0, 255) |
(0, 0, 0) | (255, 0, 0) | (0, 255, 0) | (0, 0, 255) |
(컬러인 경우 : 행순서대로 검은색-> 파란색-> 초록색-> 빨간색)
0 | 0 | 0 | 0 |
0 | 15 | 15 | 0 |
0 | 15 | 15 | 0 |
0 | 0 | 0 | 0 |
(흑백인 경우)
코드
컬러 사진을 흑백 사진으로 변환한 뒤 픽셀을 조작해서 초록색 사각형을 그리는 과정을 구현한다고 하자. 이때 흑백으로 변환하는 과정은 내부 함수가 아닌 BT.708 식을 이용해서 하자.
위에서 설명한 대로 흑백 사진에는 단일 채널만 열리기 때문에 별다른 과정이 없다면 초록색 픽셀을 그릴 때 배열 에러가 발생할 것이다.
import cv2 as cv
import numpy as np
import copy
img_color = cv.imread("sample.png", cv.IMREAD_COLOR)
height, width = img_color.shape[:2]
img_gray = np.zeros((height, width), np.uint8)
for y in range(0, height):
for x in range(0, width):
# bgr 값 저장
b = img_color.item(y, x, 0)
g = img_color.item(y, x, 1)
r = img_color.item(y, x, 2)
# BT.708
gray = int(r*0.2126+g*0.7152+b*0.07222)
img_gray.itemset(y, x, gray)
img_result = img_gray.copy() # deep copy
for y in range(50, 100):
for x in range(50, 100):
img_result.itemset(y, x, 0, 0) # b
img_result.itemset(y, x, 1, 255) # g
img_result.itemset(y, x, 2, 0) # r
cv.imshow('Original', img_color)
cv.imshow('Result', img_result)
cv.waitKey(0)
cv.destroyAllWindows()
컴파일 결과 : ValueError: incorrect number of indices for array
그렇다면 흑백 이미지를 컬러 픽셀로 다룰 수 없을까? 아니다. 가능하다. openCV 내부 함수인 cvtColor을 이용해 컬러로 바꾸면 된다. 여기서 컬러로 바꾼다는 의미는 채널을 3개로 늘린다는 의미이다. 이때 흑백 채널에 있던 값이 b,g,r에 동일하게 들어가게 된다. 반대인 경우도 마찬가지다. 3개 채널에서 단일 채널로 바뀐다.
import cv2 as cv
import numpy as np
import copy
img_color = cv.imread("sample.png", cv.IMREAD_COLOR)
height, width = img_color.shape[:2]
img_gray = np.zeros((height, width), np.uint8)
for y in range(0, height):
for x in range(0, width):
# bgr 값 저장
b = img_color.item(y, x, 0)
g = img_color.item(y, x, 1)
r = img_color.item(y, x, 2)
# BT.708
gray = int(r*0.2126+g*0.7152+b*0.07222)
img_gray.itemset(y, x, gray)
img_result = cv.cvtColor(img_gray, cv.COLOR_GRAY2BGR)
# img_result = img_gray.copy() # deep copy
for y in range(50, 100):
for x in range(50, 100):
img_result.itemset(y, x, 0, 0) # b
img_result.itemset(y, x, 1, 255) # g
img_result.itemset(y, x, 2, 0) # r
cv.imshow('Original', img_color)
cv.imshow('Result', img_result)
cv.waitKey(0)
cv.destroyAllWindows()
'openCV' 카테고리의 다른 글
[C++ openCV 도형 인식] 게임 매직 타일 매크로 [2] (완) (0) | 2021.01.28 |
---|---|
[파이썬 openCV 도형 인식] 게임 매직타일 매크로 [1] (0) | 2021.01.27 |
[Python openCV] 유로 트럭2 반자율주행 (1) | 2021.01.25 |
[파이썬 openCV] - 트랙바로 임계값 조정하기 (0) | 2021.01.21 |
[파이썬 openCV] - 이미지 데이터 공유 & 복사 (0) | 2021.01.19 |