-
중간과제2. 코사인 유사도를 이용한 색상 추출의 타당성(실습)공부/likelion 2021. 10. 3. 20:22
https://endure-life.tistory.com/27
지난 글에서는 개념에 대해서 알아보았으니, 이번에는 실제로 코사인 유사도와 이를 이용하여
사진에서 내가 원하는 색상만 화면에 나올 수 있도록 추출 코드를 작성해보자.크게 분류해보자면
1. 이미지 불러오기
2. 이미지의 각 채널을 이용한 단위 벡터 생성
3. 우리가 원하는 색상을 추출하기 위한 색상 기준 이미지 생성
4. 3의 단위 벡터 생성
5. 2,4를 이용하여 코사인 유사도 비교
6. 유사도가 일정 점수를 넘을 때만 색상, 아니면 회색이 출력되도록 함이 되겠다.
코드
1. 이미지를 불러온다
2. 이미지의 각 RGB 채널을 가져온다. (채널이라고 부르는 모양이다)#이미지를 불러온 뒤, float64로 인코딩했다. img = plt.imread('color_map.JPG').astype(np.float64) #이미지의 각 채널을 나눠주었다. r_channel, g_channel, b_channel = img[...,0],img[...,1],img[...,2] print(img.shape)
3. 해당 이미지, 즉 전체 채널에 대하여 norm을 구한다.
4. 이를 이용하여 이미지 / 이미지의 norm = 이미지의 단위 벡터를 구한다
※ 원소가 0인 경우가 있어 이미지의 원소가 나눠지지 않아 단위 벡터가 구해지지 않으므로,
0.01을 각 원소들에게 전부 더해주었다.#0인 경우가 발생해서, 0.01을 norm에 더해줬다. 거의 영향이 없을 것. img_norm = np.sqrt(r_channel**2 + g_channel**2 + b_channel**2) img_norm += np.full_like(img_norm, fill_value=0.01) img_unit = img / img_norm.reshape((img.shape[0],img.shape[1],1))
이미지와 norm, 단위 벡터의 메타 데이터들을 한번 확인해보자.
print(img.shape,img.dtype) print(r_channel.shape, g_channel.shape, b_channel.shape) print(img_unit.shape, img_norm.shape) print(img_norm.max(), img_norm.min())
각 채널별로 데이터가 잘 나누어졌으며,
norm의 최댓값은 441, 최소는 더해줬던 0.01이 된 것으로 보아 0인 요소가 있었던 것으로 확인할 수 있었다.5. 각각 우리가 원하는 채널의 값을 설정한다.
6. 6을 이용하여 우리가 원하는 이미지의 단위 벡터를 만든다#비교하고자 하는 기준만들기 R, G, B = 0. ,255., 0. target_color = np.array([R,G,B]) #각 채널을 제곱하여 합산하고, 제곱근을 구하여 norm을 구한다. t_color_norm = np.sqrt(R**2 + G**2 + B**2) #기준을 norm으로 나누어 단위 벡터를 생성한다. t_color_unit = target_color / t_color_norm print(img_unit.shape,t_color_unit.shape)
7. 4와 6을 이용하여 두 단위 벡터가 얼마나 비슷한지 코사인 유사도를 측정한다.#내적을 담당하는 부분을 만들기 = 코사인 유사도 img_dot = np.sum(img_unit * t_color_unit, axis = -1) print(img_dot.shape)
기존 이미지와 우리가 만든 기준의 코사인 유사도가
이미지의 요소별로 구해진 것을 이미지의 배열을 통해 확인해볼 수 있다.잠깐 중간 단계를 짚고 넘어가보자. 우리가 가져온 이미지, 코사인 유사도, 단위벡터는 과연 어떤 식으로 나타날까?
fig, axes = plt.subplots(1,3,figsize=(30,15)) axes[0].imshow(img.astype(np.uint8)) axes[1].imshow(img_dot,'gray') axes[2].imshow(img_unit,'gray') plt.show()
이미지, 코사인 유사도, 단위벡터 해당 이미지를 보면 위에서 우리가 설정했던 기준 중 G채널이 255, 최대값이었다.
코사인 유사도와 이미지를 비교해보면 녹색이 있는 곳이 흰색으로 드러나고, 나머지는 검정색, 즉 0으로 나오는 것을 볼 수 있다. 단위 벡터 하단을 자세히 보면 초록색 부분이 어디까지인지를 확인할 수 있다.8. 우리가 목표로 하는 이미지와 동일한 크기의 회색 벡터를 만든다
img_ch_mean = np.mean(img,axis = -1) #넣은만큼 해당 차원이 쌓이는 dstack 이용 img_gray = np.dstack((img_ch_mean,img_ch_mean,img_ch_mean)) fig, axes = plt.subplots(1,1,figsize=(30,15)) axes.imshow(img_gray.astype(np.uint8))
모든 값에 평균을 낸 이미지이기 때문에 회색톤으로 이미지가 그려지는 것을 볼 수 있다.
9. 7에서 잰 유사도보다 낮은지 높은지를 측정하는 변수를 만든다
10. 8의 영벡터에 9의 변수 결과를 입력한다.
11. 결과를 확인한다.#9. 유사도가 해당 점수를 넘으면 출력, 아니면 출력되지 않도록 하는 기준을 설정 cut_off = 0.95 #(0~1사이로) indices_bool = img_dot > cut_off n_indices_bool = img_dot <= cut_off #빈 공간을 세팅 bg_img = np.zeros_like(img) #10. 빈 공간에 9에서 만든 기준을 이용하여 기준이 넘으면 이미지를, 아니면 회색을 출력 bg_img[indices_bool] = img[indices_bool] bg_img[n_indices_bool] = img_gray[n_indices_bool] #11. 시각화 fig, axes = plt.subplots(1,2,figsize=(20,10)) axes[0].imshow(img.astype(np.uint8)) axes[1].imshow(bg_img.astype(np.uint8)) plt.show()
G 채널 값을 255로, 기준을 0.95로 줬기 때문에 유사도가 95이상인 영역인 초록만 색깔이 표시되고, 다른 곳은 색이 표시되지 않는 것을 볼 수 있다. 그렇다면 다른 경우는 어떨까?
(0,255,255)를 준 경우 초록색과 파란색을 준 경우, 하늘색이 출력된다. 그렇다면 빨간색과 파란색을 줘보자.
(255,0,255)를 준 경우 보라색, 자주색에 가까운 값이 출력된다.
그렇다면 이 값들은 정상일까? 빛의 삼원색을 보면서 이를 확인해보자.
각각 조합과 비교하면 하늘색, 보라색이 맞다 빛의 삼원색과 비교해봤을때도 이상이 없는 것을 볼 수 있다.
결론
과정을 해석해보자면
본래 이미지의 각 요소, 한 점에 대하여 각 채널별로 단위 벡터를 측정했기 때문에
이미지는 요소마다 채널별 단위 벡터를 수치로 가지고 있었을 것이다.그 요소(원본)의 단위 벡터와 우리가 기준으로 삼은 요소(임의)의 단위 벡터가
얼마나 유사한지를 코사인 유사도로 비교해봤을 때우리가 정한 cut_off 라는 기준에 따라 그 유사도가 cut_off보다 큰 경우에서만
새로 만든 이미지에 원본 이미지의 요소를 집어넣었으므로
해당 색깔만 색깔이 나오고, 나머지는 회색으로 출력된다고 볼 수 있겠다.
단, 채도, 색상을 기준으로 만들었기 때문에 명도, 밝기를 기준으로 하는 같은 경우에는 작동하지 않는다.
만약 명도를 기준으로 작동하게 하고 싶다면
각각의 채널 값들이 특정 값 이상일때만 나오게 해야할 것이므로,
3채널의 값이 일정 값 이상일때만 출력되도록 하면 될 것이다.
결론적으로, 코사인 유사도를 통한 색상 추출은 정상적으로 작동한다고 볼 수 있다.
단, 색상을 기준으로 할때만. 명도는 안된다.'공부 > likelion' 카테고리의 다른 글
8. axis and keepdims Arguments (0) 2021.10.08 7. Indexing and Slicing ndarrays (0) 2021.10.06 중간 과제2 : 코사인 유사도를 이용한 색상 추출의 타당성(개념) (0) 2021.10.03 6. Element-wise Operations and Broadcasting (0) 2021.10.01 5. Changing ndarrays (0) 2021.09.30