【OpenCV】HSV를 직교 좌표계로 변환 표시
개요
이미지 분석 시 HSV 색 공간을 사용하는 경우가 많다고 생각합니다. 특히 H(색조)와 S(채도)를 산점도에 플롯하면 이미지의 색채의 특징을 잘 파악할 수 있습니다.
단, H 와 S 는 국 좌표 공간의 파라미터입니다. 이 때문에 H는 0~360도(OpenCV에서는 0~180)의 위상각이 됩니다. 여기에 문제가 있습니다. H 가 0 부근과 H 가 360 부근은 同じような色相
를 나타내게 되어 버립니다. 값이 크게 다르지만 특성은 매우 유사하다는 것은 바람직하지 않습니다. 기계 학습 외, 수리 통계 처리를 실시하려면, 궁리가 필요하겠지요.
그래서 국 좌표에서 직교 좌표로 변환하면 잘 처리 할 수 있다고 생각합니다. 조금 시도해 보았습니다.
HSV 색 공간 : H와 S의 산점도
시험에 붉은 (H가 0 부근 및 OpenCV의 180 부근의 값을 취하는 점이 많다) 이미지를 조사해 보겠습니다. 샘플을 lena로 해 보겠습니다.
필요한 라이브러리를 가져옵니다.
import cv2
from matplotlib import pyplot as plt
lena를 읽고 OpenCV에서 읽은 BGR 형식의 이미지를 HSV 변환합니다.
#matplotlib에서도 표시하기 위해 함께 RGB 형식도 만들어 둡니다.
lena_bgr = cv2.imread('lena.png')
lena_hsv = cv2.cvtColor(lena_bgr,cv2.COLOR_BGR2HSV)
lena_rgb = cv2.cvtColor(lena_bgr,cv2.COLOR_BGR2RGB)
이미지의 색채의 특성을 보기 위해 가로축 H, 세로축 S로 산점도를 만들어 봅니다.
plt.figure(figsize=(12,4))
plt.subplot(1,3,1)
plt.imshow(lena_rgb)
plt.subplot(1,3,2)
plt.xlim(0,180)
plt.ylim(0,255)
plt.grid()
plt.scatter(x=lena_hsv[:,:,0],y=lena_hsv[:,:,1],alpha=0.01,marker='x',color='g')
plt.show()
채도는 넓은 범위에 분포되어 있지만 色相は 0付近、あるいは180付近
에 편향되어 있습니다. lena가 붉은 이미지임을 잘 보여줍니다.
다만 「붉은」이기 때문에 산포도상의 점이 2개의 그룹으로 나누어지는 것은 조금 혼란을 초래하네요. SVM 다른 머신러닝을 할 때도 별로 편리하지 않을 수 있습니다. 그래서 이것을 직교 좌표계로 나타내는 것을 생각합니다.
직교 좌표계에 의한 색채의 표현
직교 좌표계로 변환하는 것은 어렵지 않습니다. H(색조)가 위상, S(채도)가 절대값이므로,
\begin{align}
x = S\,\cos(\,H\,)\\
\\y = S\,\sin(\,H\,)
\end{align}
이것으로 구할 수 있네요.
주의가 필요한 것은, OpenCV에서는 H(색조)를 0~360이 아니고, 0~179로 취급하고 있다는 점입니다. 계산할 때는 H 의 값을 2배로 해야 합니다.
# 8 비트의 부호없는 정수에서는, 255까지 밖에 나타낼 수 없기 때문에 편의상입니다
또한, numpy의 삼각 함수는 단위에 라디안을 사용하고 있으므로, 거기도 주의해 주세요.
그럼, 직교 좌표계로 변환해 보겠습니다.
lena_temp = lena_hsv.astype(np.float32)
lena_xyv = np.zeros(lena_hsv.shape).astype(np.float32)
# 位相の単位をラジアンに変換
# x = cos((2*H) * 2pi / 360) = cos(H * pi / 90)
# y = sin((2*H) * 2pi / 360) = sin(H * pi / 90)
lena_xyv[:,:,0] = lena_temp[:,:,1] * np.cos(lena_temp[:,:,0]*(np.pi)/90)
lena_xyv[:,:,1] = lena_temp[:,:,1] * np.sin(lena_temp[:,:,0]*(np.pi)/90)
lena_xyv[:,:,2] = lena_hsv[:,:,2]
sin, cos 는 실수 계산이므로, float32 에 형태 변환한 인스턴스를 만들어 작업하고 있습니다.
또, 명도 V 는 여기에서는 사용하지 않지만, 만약을 위해, 보존해 두었습니다.
결과 비교
앞에서와 같이 원래 이미지와 H-S 산점도, 거기에 이번에 직교 좌표 변환한 x-y 산점도를 나란히 봅니다.
plt.figure(figsize=(12,4))
plt.subplot(1,3,1)
plt.title('lena')
plt.imshow(lena_rgb)
plt.subplot(1,3,2)
plt.title('H-S')
plt.xlim(0,180)
plt.ylim(0,255)
plt.grid()
plt.scatter(x=lena_hsv[:,:,0],y=lena_hsv[:,:,1],alpha=0.2)
plt.subplot(1,3,3)
plt.title('x-y')
plt.xlim(-255,255)
plt.ylim(-255,255)
plt.grid()
plt.scatter(x=lena_xyv[:,:,0],y=lena_xyv[:,:,1],alpha=0.01,marker='x',color='r')
plt.show()
직교 좌표계에서 보면, 붉은 레나가 한 덩어리가 되어 보다 잘 특징을 나타내고 있는 것 같습니다.
색조, 채도를 사용해 기계 학습할 때에는, 직교 좌표계로 생각하면 잘 되는 경우도 많지 않을까요.
Reference
이 문제에 관하여(【OpenCV】HSV를 직교 좌표계로 변환 표시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/masami65/items/1dea57f1cb622cfe79dc
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
시험에 붉은 (H가 0 부근 및 OpenCV의 180 부근의 값을 취하는 점이 많다) 이미지를 조사해 보겠습니다. 샘플을 lena로 해 보겠습니다.
필요한 라이브러리를 가져옵니다.
import cv2
from matplotlib import pyplot as plt
lena를 읽고 OpenCV에서 읽은 BGR 형식의 이미지를 HSV 변환합니다.
#matplotlib에서도 표시하기 위해 함께 RGB 형식도 만들어 둡니다.
lena_bgr = cv2.imread('lena.png')
lena_hsv = cv2.cvtColor(lena_bgr,cv2.COLOR_BGR2HSV)
lena_rgb = cv2.cvtColor(lena_bgr,cv2.COLOR_BGR2RGB)
이미지의 색채의 특성을 보기 위해 가로축 H, 세로축 S로 산점도를 만들어 봅니다.
plt.figure(figsize=(12,4))
plt.subplot(1,3,1)
plt.imshow(lena_rgb)
plt.subplot(1,3,2)
plt.xlim(0,180)
plt.ylim(0,255)
plt.grid()
plt.scatter(x=lena_hsv[:,:,0],y=lena_hsv[:,:,1],alpha=0.01,marker='x',color='g')
plt.show()
채도는 넓은 범위에 분포되어 있지만
色相は 0付近、あるいは180付近
에 편향되어 있습니다. lena가 붉은 이미지임을 잘 보여줍니다.다만 「붉은」이기 때문에 산포도상의 점이 2개의 그룹으로 나누어지는 것은 조금 혼란을 초래하네요. SVM 다른 머신러닝을 할 때도 별로 편리하지 않을 수 있습니다. 그래서 이것을 직교 좌표계로 나타내는 것을 생각합니다.
직교 좌표계에 의한 색채의 표현
직교 좌표계로 변환하는 것은 어렵지 않습니다. H(색조)가 위상, S(채도)가 절대값이므로,
\begin{align}
x = S\,\cos(\,H\,)\\
\\y = S\,\sin(\,H\,)
\end{align}
이것으로 구할 수 있네요.
주의가 필요한 것은, OpenCV에서는 H(색조)를 0~360이 아니고, 0~179로 취급하고 있다는 점입니다. 계산할 때는 H 의 값을 2배로 해야 합니다.
# 8 비트의 부호없는 정수에서는, 255까지 밖에 나타낼 수 없기 때문에 편의상입니다
또한, numpy의 삼각 함수는 단위에 라디안을 사용하고 있으므로, 거기도 주의해 주세요.
그럼, 직교 좌표계로 변환해 보겠습니다.
lena_temp = lena_hsv.astype(np.float32)
lena_xyv = np.zeros(lena_hsv.shape).astype(np.float32)
# 位相の単位をラジアンに変換
# x = cos((2*H) * 2pi / 360) = cos(H * pi / 90)
# y = sin((2*H) * 2pi / 360) = sin(H * pi / 90)
lena_xyv[:,:,0] = lena_temp[:,:,1] * np.cos(lena_temp[:,:,0]*(np.pi)/90)
lena_xyv[:,:,1] = lena_temp[:,:,1] * np.sin(lena_temp[:,:,0]*(np.pi)/90)
lena_xyv[:,:,2] = lena_hsv[:,:,2]
sin, cos 는 실수 계산이므로, float32 에 형태 변환한 인스턴스를 만들어 작업하고 있습니다.
또, 명도 V 는 여기에서는 사용하지 않지만, 만약을 위해, 보존해 두었습니다.
결과 비교
앞에서와 같이 원래 이미지와 H-S 산점도, 거기에 이번에 직교 좌표 변환한 x-y 산점도를 나란히 봅니다.
plt.figure(figsize=(12,4))
plt.subplot(1,3,1)
plt.title('lena')
plt.imshow(lena_rgb)
plt.subplot(1,3,2)
plt.title('H-S')
plt.xlim(0,180)
plt.ylim(0,255)
plt.grid()
plt.scatter(x=lena_hsv[:,:,0],y=lena_hsv[:,:,1],alpha=0.2)
plt.subplot(1,3,3)
plt.title('x-y')
plt.xlim(-255,255)
plt.ylim(-255,255)
plt.grid()
plt.scatter(x=lena_xyv[:,:,0],y=lena_xyv[:,:,1],alpha=0.01,marker='x',color='r')
plt.show()
직교 좌표계에서 보면, 붉은 레나가 한 덩어리가 되어 보다 잘 특징을 나타내고 있는 것 같습니다.
색조, 채도를 사용해 기계 학습할 때에는, 직교 좌표계로 생각하면 잘 되는 경우도 많지 않을까요.
Reference
이 문제에 관하여(【OpenCV】HSV를 직교 좌표계로 변환 표시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/masami65/items/1dea57f1cb622cfe79dc
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
\begin{align}
x = S\,\cos(\,H\,)\\
\\y = S\,\sin(\,H\,)
\end{align}
lena_temp = lena_hsv.astype(np.float32)
lena_xyv = np.zeros(lena_hsv.shape).astype(np.float32)
# 位相の単位をラジアンに変換
# x = cos((2*H) * 2pi / 360) = cos(H * pi / 90)
# y = sin((2*H) * 2pi / 360) = sin(H * pi / 90)
lena_xyv[:,:,0] = lena_temp[:,:,1] * np.cos(lena_temp[:,:,0]*(np.pi)/90)
lena_xyv[:,:,1] = lena_temp[:,:,1] * np.sin(lena_temp[:,:,0]*(np.pi)/90)
lena_xyv[:,:,2] = lena_hsv[:,:,2]
앞에서와 같이 원래 이미지와 H-S 산점도, 거기에 이번에 직교 좌표 변환한 x-y 산점도를 나란히 봅니다.
plt.figure(figsize=(12,4))
plt.subplot(1,3,1)
plt.title('lena')
plt.imshow(lena_rgb)
plt.subplot(1,3,2)
plt.title('H-S')
plt.xlim(0,180)
plt.ylim(0,255)
plt.grid()
plt.scatter(x=lena_hsv[:,:,0],y=lena_hsv[:,:,1],alpha=0.2)
plt.subplot(1,3,3)
plt.title('x-y')
plt.xlim(-255,255)
plt.ylim(-255,255)
plt.grid()
plt.scatter(x=lena_xyv[:,:,0],y=lena_xyv[:,:,1],alpha=0.01,marker='x',color='r')
plt.show()
직교 좌표계에서 보면, 붉은 레나가 한 덩어리가 되어 보다 잘 특징을 나타내고 있는 것 같습니다.
색조, 채도를 사용해 기계 학습할 때에는, 직교 좌표계로 생각하면 잘 되는 경우도 많지 않을까요.
Reference
이 문제에 관하여(【OpenCV】HSV를 직교 좌표계로 변환 표시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/masami65/items/1dea57f1cb622cfe79dc텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)