挑战图像处理100问(5)——HSV变换及色相反转

在这里插入图片描述
读取图像,使用 HSV \text{HSV} HSV表示色彩的图像的色相反转。
Author: Tian YJ
原图如下:

在这里插入图片描述

关于HSV

HSV \text{HSV} HSV即使用色相(Hue)、饱和度(Saturation)、明度(Value)来表示色彩的一种方式。

  • 色相:将颜色使用 0 ∘ 0^{\circ} 0 36 0 ∘ 360^{\circ} 360表示,就是平常所说的颜色名称,如红色、蓝色。色相与数值按下表对应:

    绿青色蓝色品红
    0 ∘ 0^{\circ} 0 6 0 ∘ 60^{\circ} 60 12 0 ∘ 120^{\circ} 120 18 0 ∘ 180^{\circ} 180 24 0 ∘ 240^{\circ} 240 30 0 ∘ 300^{\circ} 300 36 0 ∘ 360^{\circ} 360
  • 饱和度:是指色彩的纯度,饱和度越低则颜色越黯淡( 0 ≤ S < 1 0\leq S < 1 0S<1);

  • 明度:即颜色的明暗程度。数值越高越接近白色,数值越低越接近黑色( 0 ≤ V < 1 0\leq V < 1 0V<1);

RGB \text{RGB} RGB色彩表示转换到 HSV \text{HSV} HSV色彩表示通过以下方式计算:

RGB \text{RGB} RGB的取值范围为 [ 0 , 1 ] [0, 1] [0,1],令:
Max = max ⁡ ( R , G , B ) Min = min ⁡ ( R , G , B ) \text{Max}=\max(R,G,B)\\ \text{Min}=\min(R,G,B) Max=max(R,G,B)Min=min(R,G,B)
色相:
H = { 0 ( if Min = Max ) 60   G − R Max − Min + 60 ( if Min = B ) 60   B − G Max − Min + 180 ( if Min = R ) 60   R − B Max − Min + 300 ( if Min = G ) H=\begin{cases} 0&(\text{if}\ \text{Min}=\text{Max})\\ 60\ \frac{G-R}{\text{Max}-\text{Min}}+60&(\text{if}\ \text{Min}=B)\\ 60\ \frac{B-G}{\text{Max}-\text{Min}}+180&(\text{if}\ \text{Min}=R)\\ 60\ \frac{R-B}{\text{Max}-\text{Min}}+300&(\text{if}\ \text{Min}=G) \end{cases} H=060 MaxMinGR+6060 MaxMinBG+18060 MaxMinRB+300(if Min=Max)(if Min=B)(if Min=R)(if Min=G)
饱和度:
S = Max − Min S=\text{Max}-\text{Min} S=MaxMin
明度:
V = Max V=\text{Max} V=Max
HSV \text{HSV} HSV色彩表示转换到 RGB \text{RGB} RGB色彩表示通过以下方式计算:
C = S H ′ = H 60 X = C   ( 1 − ∣ H ′ m o d    2 − 1 ∣ ) ( R , G , B ) = ( V − C )   ( 1 , 1 , 1 ) + { ( 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 ) C = S\\ H' = \frac{H}{60}\\ X = C\ (1 - |H' \mod 2 - 1|)\\ (R,G,B)=(V-C)\ (1,1,1)+\begin{cases} (C, X, 0)& (\text{if}\quad 0 \leq H' < 1)\\ (X, C, 0)& (\text{if}\quad 1 \leq H' < 2)\\ (0, C, X)& (\text{if}\quad 2 \leq H' < 3)\\ (0, X, C)& (\text{if}\quad 3 \leq H' < 4)\\ (X, 0, C)& (\text{if}\quad 4 \leq H' < 5)\\ (C, 0, X)& (\text{if}\quad 5 \leq H' < 6) \end{cases} C=SH=60HX=C (1Hmod21)(R,G,B)=(VC) (1,1,1)+(C,X,0)(X,C,0)(0,C,X)(0,X,C)(X,0,C)(C,0,X)(if0H<1)(if1H<2)(if2H<3)(if3H<4)(if4H<5)(if5H<6)
这里将实现将色相反转(色相值加 180 180 180),然后再用 RGB \text{RGB} RGB色彩空间表示图片。

代码实现
# -*- coding: utf-8 -*-
"""
Created on Tue Apr  7 22:12:41 2020

@author: Tian YJ
"""

import cv2
import numpy as np

# RGB --> HSV
def RGB2HSV(img_):
	img = img_.copy() / 255 # 进行归一化
	hsv = np.zeros_like(img, dtype = np.float32) # HSV初始化

	# 求取每一像素在不同通道的最大值Max与最小值Min
	Max = np.max(img, axis=2).copy()
	Min = np.min(img, axis=2).copy()
	# 找出最小值位于哪一通道
	Min_arg = np.argmin(img, axis=2)

	### 求色相H
	hsv[...,0][np.where(Max==Min)] = 0
	# 当Min位于B通道时
	index = np.where(Min_arg == 0)
	hsv[...,0][index] = 60*(img[...,1][index]-img[...,2][index])/(Max[index]-Min[index])+60
	# 当Min位于G通道时
	index = np.where(Min_arg == 1)
	hsv[...,0][index] = 60*(img[...,2][index]-img[...,0][index])/(Max[index]-Min[index])+300
	# 当Min位于R通道时
	index = np.where(Min_arg == 2)
	hsv[...,0][index] = 60*(img[...,0][index]-img[...,1][index])/(Max[index]-Min[index])+180

	### 求饱和度S
	hsv[...,1] = Max.copy() - Min.copy()

	### 求明度V
	hsv[...,2] = Max.copy()

	return hsv

# HSV --> RGB
def HSV2RGB(img_, hsv):
	img = img_.copy() / 255

	# 求取每一像素在不同通道的最大值Max与最小值Min
	Max = np.max(img, axis=2).copy()
	Min = np.min(img, axis=2).copy()

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

	# 求取HSV分量	
	H = hsv[...,0]
	S = hsv[...,1]
	V = hsv[...,2]

	# 按公式进行转换
	C = S
	H_ = H/60
	X = C * (1 - np.abs( H_ % 2 - 1))
	# 设置中间零矩阵
	Z = np.zeros_like(H)
	# 公式中是按RGB排列,这里倒过来按BGR排列
	temp = [[Z,X,C], [Z,C,X], [X,C,Z], [C,X,Z], [C,Z,X],[X,Z,C]]

	for i in range(6):
		index = np.where((i<H_ ) & (H_<i+1))
		# B通道
		out[...,0][index] = (V-C)[index]*1 + temp[i][0][index]
		# G通道
		out[...,1][index] = (V-C)[index]*1 + temp[i][1][index]
		# R通道
		out[...,2][index] = (V-C)[index]*1 + temp[i][2][index]
		
	# 防止越界
	out = np.clip(out, 0, 1)
	# 从归一化后的数值转回真实数值
	out = (out*255).astype(np.uint8)
	return out

# 读取图片
path = 'C:/Users/86187/Desktop/image/'


file_in = path + 'cake.jpg' 
file_out = path + 'HSV_RGB.jpg' 
img = cv2.imread(file_in)

# 调用函数RGB-->HSV
hsv = RGB2HSV(img)

# 进行色相反转即将色相值加180
hsv[..., 0] = (hsv[..., 0] + 180) % 360

# 调用函数HSV-->RGB
out = HSV2RGB(img, hsv)

# 保存图片
cv2.imwrite(file_out, out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果展示
原图色相反转
在这里插入图片描述在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值