본 글에서는 이미지의 특정부분을 잘라내기(Crop) 혹은 추출하여 이미지 프로세싱을 수행후
본래 이미지에 붙여넣기 하는 작업을 해보겠습니다.
자동으로 이미지상의 ROI (Region of Interest) 를 추출하여 연산을 수행하는것은 중급과정에서 다룰
예정입니다.
우선 위의 이미지 에서 보이는 특정부분 (흰색 네모상자)을 잘라내기(Crop) 하여 새로운 변수로
지정하여 보겠습니다. 임의로 지정한 좌표 - tuple ( x좌표, y좌표 ) 형식 ( 753, 1210 ) 부터 ( 2115, 2110 ) -
를 입력 파라메터로 하는 cv2.rectangle( ) 명령어를 이용하였습니다.
여기에서 주의할 점은 cv2.rectangle( ) 명령어에서는 ( x좌표, y좌표 ) 순서의 입력 파라메터를 갖지만,
일반적으로 python에서 이미지 데이터는 행 과 열을 갖는 하나의 NumPy 데이터 매트릭스(Matrix)
형태를 갖으므로 픽셀에 접근하기 위해 반드시 ( y좌표, x좌표 ) 순서로 지정하며, 범위 지정을 위한
slicing이 가능 합니다.
위 이미지는 본 블로그 맨밑 출처 1에 가셔서 다운로드 받을 수 있습니다.
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img_color = cv2.imread('national-cancer-institute-jdfn7Z03Qa4-unsplash.jpg',cv2.IMREAD_COLOR)
img_gray = cv2.cvtColor(img_color,cv2.COLOR_BGR2GRAY)
img_color_copy = img_color.copy()
# tuple (x,y-axis)
# start point: (753,1210), end point: (2115,2110),
# thickness 30, white color rectangular line
cv2.rectangle(img_color_copy,(753,1210),(2115,2110),(255,255,255),30)
cv2.rectangle( ) 는 작업수행후 새로운 변수에 결과를 리턴하는 것이 아닌,
입력 파라메터의 이미지에 작업결과를 덧붙이는 방식이기 때문에 "img_color_copy" 라는 새로운
변수에 기존의 "img_color" 를 복사( .copy( ) ) 한 것입니다.
이제는 gray scale 의 대상 이미지에 지정된 좌표로 numpy slicing을 이용하여 잘라내기(Crop) 를
하겠습니다. 지정된 좌표의 시작점과 끝점은 각각 start_pt 와 end_pt 변수에 [y좌표, x좌표] 를 지정
하였습니다. 잘라내기(Crop)한 새로운 이미지의 너비와 높이는 끝점과 시작점의 차이에 +1 픽셀을
더해야 합니다. 예를들어, 좌표 1에서 좌표 100 까지 지정한다면 길이는 100 이며, 이는 간단한 수식
(100 - 1) + 1 으로 표현됩니다.
start_pt = [1210, 753] # [y, x-axis] or (y, x-axis), both are fine
end_pt = [2110, 2115] # [y, x-axis]
img_gray_crop = img_gray[start_pt[0]:end_pt[0], start_pt[1]:end_pt[1]] # numpy slicing
fig = plt.figure(figsize=(9, 7))
fig.add_subplot(1, 2, 1)
plt.axis("off")
plt.imshow(img_gray, cmap='gray')
plt.title("Gray Image")
fig.add_subplot(1, 2, 2)
plt.axis("off")
plt.imshow(img_gray_crop, cmap='gray')
plt.title("Cropped Image")
plt.show()
다른 방법으로, 시작점에서 너비와 높이 (= 가로 x 세로 픽셀) 를 지정하면 잘라내기(Crop)가 가능합니다.
예를들어 시작점 start_pt = [ 1210, 753 ] - [y, x-axis] - 너비가 W, 높이가 H 픽셀로 지정되었다면
height_range = start_pt[0] + H + 1
wide_range = start_pt[1] + W + 1
img_gray_crop = img_gray[start_pt[0]:height_range, start_pt[1]:wide_range] # slicing with height & wide
잘라내기(Crop)할 범위지정시 너비와 높이에 +1 픽셀을 더해야 합니다.
Python의 slicing 은 A 부터 B까지가 아닌 A 부터 B-1 까지 이기 때문입니다.
위의 코드에 주의할 것은, 잘라내기(Crop) 하는 범위가 이미지 데이터의 범위를 넘어서지 않게
혹은 넘어설경우의 예외처리를 하는 코드가 추가적으로 필요합니다.
이번에는 잘라내기한 새로운 이미지에 임의로 픽셀값의 70%를 상향시켜 보겠습니다.
각각의 픽셀값에 70%를 상향시키는 작업이므로 element-wise 곱셈연산이지만 Python의
브로드캐스팅(Broadcasting) 기능으로 쉽게 계산이 가능합니다.
선형연산을 하기 전, 후를 비교하기 위해 histogram과 이미지를 나란히 표시하겠습니다.
img_gray_crop_UP = (img_gray_crop * 1.7).astype('uint8') # intensity 70% UP
img_gray_crop_hist = cv2.calcHist([img_gray_crop], [0], None, [256], [0, 256])
img_gray_crop_UP_hist = cv2.calcHist([img_gray_crop_UP], [0], None, [256], [0, 256])
fig = plt.figure(figsize=(10, 6)) # histograms
fig.add_subplot(1, 2, 1)
plt.plot(img_gray_crop_hist)
plt.title('Original')
plt.xlim([0, 256])
fig.add_subplot(1, 2, 2)
plt.plot(img_gray_crop_UP_hist)
plt.title('Intensity 70% UP')
plt.xlim([0, 256])
plt.show()
fig = plt.figure(figsize=(9, 7)) # crop images
fig.add_subplot(1, 2, 1)
plt.axis("off")
plt.imshow(img_gray_crop, cmap='gray')
plt.title('Original')
fig.add_subplot(1, 2, 2)
plt.axis("off")
plt.imshow(img_gray_crop_UP, cmap='gray')
plt.title('Intensity 70% UP')
plt.show()
위의 histogram 에서 보듯이, 픽셀값 70% 상향시 픽셀값의 분포가 원래에 비해 우측으로 확장되었고,
이미지 또한 눈에띄게 밝아졌음을 알 수 있습니다. (이것은 이미지의 brightness 개선에 사용되는 기본적인
방법 입니다)
만일 cell(세포)의 형태를 추출, 가공하는것이 이미지 프로세싱의 목적이고 그 외의 것들
(예를들어 배경이 되는 어두운 부분)을 노이즈로 가정 한다면, 이미지의 일괄적인 선형연산으로 인한
노이즈 증가를 예상할 수 있습니다.
마지막으로 본래 이미지의 잘라내기(Crop)한 부분을 픽셀값 70% 상향한 이미지 조각으로 대체해 보겠습니다.
이처럼 특정부분의 픽셀값을 상향하여 대체하는 작업은 보편적으로 수행하는 테크닉은 아닙니다.
원래 이미지의 사본 (여기서는 "img_gray2")을 만들고, 픽셀값을 대체할 부분의 범위지정에 주의하십시오.
밑의 결과 이미지에서 알 수 있듯이 특정부분의 픽셀값만 70% 상향되었고 이로인해 특정부분만
눈에띄게 밝게 표현되고 있습니다.
img_gray2 = img_gray.copy()
#start_pt = [1210,753] # [y, x-axis]
#end_pt = [2110,2115] # [y, x-axis]
img_gray2[start_pt[0]:end_pt[0],start_pt[1]:end_pt[1]] = img_gray_crop_UP
fig = plt.figure(figsize=(20, 18))
plt.axis("off")
plt.imshow(img_gray2, cmap='gray')
plt.show()
출처1: https://unsplash.com/photos/jdfn7Z03Qa4
사진 작가: National Cancer Institute, Unsplash
Cells from cervical cancer – Splash에서 National Cancer Institute의 이 사진 다운로드
unsplash.com