목표 이미지 처리 마스터! 화상 처리 100개 노크 했던 Part3:HSV 변환

오늘은 Q5에 도전합니다.
우선 numpy의 지식도 부족한 뒤 통감하고 있는 곳입니다.
이것을 계기로, 여기도 마스터하고 싶다.

이대로 매번 링크하면 본사님의 링크를 가득 채울 것 같아서 오늘부터 링크 붙이는 것은 그만두어 둡니다.
그림 처리 마스터 시리즈의 이전 기사에 링크가 있으므로 꼭 거기에서 날아 도전하십시오.

Q5: HSV 변환



HSV 변환이란 무엇입니까?



몰랐기 때문에 우선 공부에서 들어갔습니다만, 이 그림 보면 기억이 있다!

RGB에서 HSV로 변환 및 복원 물리의 꼬리

색은 RGB로부터 만들어져 각각에 휘도가 있어~같이 말해지는 것보다 좀처럼 이미지하기 쉬운 그림이 나왔습니다.
왠지, 이런 것 같다고 합니다

HSV는 각각 H (Hue), S (Saturation), V (Value of Brightness)의 것으로, H는 색조 환에서 적색을 0도로했을 때의 각도로 표현됩니다. 그래서 이번 H는 360단계, S와 V는 256단계로 나타냅니다. 위의 색조환의 중심을 채도 제로의 점으로 하여 반경 256의 원반을 생각해, 그것이 명도의 단계마다 256장 늘어선 원주를 생각하면 대단히 쉽습니다.

예, 매우 이해하기 쉽습니다. 감사합니다.

HSV로 변환 할 수 있다면 무엇이 기뻐할까요?



몇가지 읽었는데 가장 배고파진 것은 픽시브 백과사전이었습니다.
htps : // c. 피 v. 네 t/아/HSV

인간은 색에 대해 생각할 때, <중략> 보통은 「무슨 색인가(색조), 선명한 색인가 차분한 색인가(채도), 밝은 색인가 어두운 색인가(명도)」라고 하는 견해를 하는 것, 즉 인간의 색에 대한 생각은 HSV 자체이다. 이것이 HSV가 직관적으로 이해하기 쉬운 컬러 모델 인 이유입니다.

구현한다



엄청 오랜 시간이 걸렸다.
HSV2RGB 부분은 아무래도 긴 것 같아 버리기 때문에 무슨 일인지 생각해 해답 보면 우아한 해답 너무 감동했습니다
import cv2
import numpy as np

img = cv2.imread("imori.jpg")

#RGBが[0,1]になるように
img = img/255

'''
Max = max(R,G,B)
Min = min(R,G,B)

H =  { 0                            (if Min=Max)
       60 x (G-R) / (Max-Min) + 60  (if Min=B)
       60 x (B-G) / (Max-Min) + 180 (if Min=R)
       60 x (R-B) / (Max-Min) + 300 (if Min=G)

V = Max
S = Max - Min
より,RGBのなかで輝度のmin値を持つもの,そのmin値,RGBの中の輝度max値を求めれば良いとわかる
'''

#RGBのなかでmin値を持つもの
arg_min = np.argmin(img,axis=2)
#輝度のmin値
min_v = np.min(img,axis=2).copy()
#輝度のmax値
max_v = np.max(img, axis=2).copy()

#hsv変換する RGB2HSV
#hを求める
hsv = np.zeros_like(img, dtype=np.float32)

hsv[:,:,0][np.where(max_v==min_v)] = 0
#if min == Bの画素
w_min = np.where(arg_min == 0)
hsv[:,:,0][w_min] = 60 * (img[:,:,1][w_min]-img[:,:,2][w_min]) / (max_v[w_min]-min_v[w_min]) + 60
#if min == Rの画素
w_min = np.where(arg_min == 2)
hsv[:,:,0][w_min] = 60 * (img[:,:,0][w_min]-img[:,:,1][w_min]) / (max_v[w_min]-min_v[w_min]) + 180
#if min == Gの画素
w_min = np.where(arg_min == 1)
hsv[:,:,0][w_min] = 60 * (img[:,:,2][w_min]-img[:,:,0][w_min]) / (max_v[w_min]-min_v[w_min]) + 300

#色相を反転する...Hに180足せばよい,元が180以上だと溢れるので360で割ったあまりを考える 
hsv[:,:,0] = (hsv[:,:,0]+180) % 360

#V求める
hsv[:,:,2] = max_v.copy()

#S求める
hsv[:,:,1] = max_v.copy() - min_v.copy()

#HSV2RGB変換
'''
C = S
H' = H / 60
X = C (1 - |H' mod 2 - 1|)

(R,G,B) = (V - C) (1,1,1) + { (0, 0, 0)  (if H is undefined)
                              (C, X, 0)  (if 0 <= H' < 1)
                              (X, C, 0)  (if 1 <= H' < 2)
                              (0, C, X)  (if 2 <= H' < 3)
                              (0, X, C)  (if 3 <= H' < 4)
                              (X, 0, C)  (if 4 <= H' < 5)
                              (C, 0, X)  (if 5 <= H' < 6)
'''
H = hsv[:,:,0]
S = hsv[:,:,1]
V = hsv[:,:,2]

C = S
H_d = H / 60
X = C * (1 - np.abs(H_d % 2 -1))

# (C, X, 0) ...の組み合わせの0の部分をZとおく
Z = np.zeros_like(H)
#RGBパタン
vals = [[Z,X,C], [Z,C,X], [X,C,Z], [C,X,Z], [C,Z,X], [X,Z,C]]

out = np.zeros_like(img, dtype=np.float32)

#最終的にはBGRにしないといけないことを考えて
for i in range(6):
    ind = np.where((i <= H_d) & (H_d < (i+1)))
    out[..., 0][ind] = (V - C)[ind] + vals[i][0][ind]
    out[..., 1][ind] = (V - C)[ind] + vals[i][1][ind]
    out[..., 2][ind] = (V - C)[ind] + vals[i][2][ind]

out[np.where(max_v == min_v)] = 0
out = np.clip(out, 0, 1)
out = (out * 255).astype(np.uint8)

#いつもの描画
cv2.imwrite("anspic_q5.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

나온 이미지. 그렇습니다!


화소마다 취급하고 있다는 기분이 아직 부족하다는 것을 실감했습니다

끝에



한가롭게 천천히 할게

좋은 웹페이지 즐겨찾기