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


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

    在这里插入图片描述

    关于HSV

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

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

      绿 青色 蓝色 品红
      00^{circ} 6060^{circ} 120120^{circ} 180180^{circ} 240240^{circ} 300300^{circ} 360360^{circ}
    • 饱和度:是指色彩的纯度,饱和度越低则颜色越黯淡(0S<10leq S < 1);

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

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

    RGB ext{RGB}的取值范围为[0,1][0, 1],令:
    Max=max(R,G,B)Min=min(R,G,B) ext{Max}=max(R,G,B)\ ext{Min}=min(R,G,B)
    色相:
    H={0(if Min=Max)60 GRMaxMin+60(if Min=B)60 BGMaxMin+180(if Min=R)60 RBMaxMin+300(if Min=G) H=egin{cases} 0&( ext{if} ext{Min}= ext{Max})\ 60 frac{G-R}{ ext{Max}- ext{Min}}+60&( ext{if} ext{Min}=B)\ 60 frac{B-G}{ ext{Max}- ext{Min}}+180&( ext{if} ext{Min}=R)\ 60 frac{R-B}{ ext{Max}- ext{Min}}+300&( ext{if} ext{Min}=G) end{cases}
    饱和度:
    S=MaxMin S= ext{Max}- ext{Min}
    明度:
    V=Max V= ext{Max}
    HSV ext{HSV}色彩表示转换到RGB ext{RGB}色彩表示通过以下方式计算:
    C=SH=H60X=C (1Hmod  21)(R,G,B)=(VC) (1,1,1)+{(0,0,0)(if H is undefined)(C,X,0)(if0H<1)(X,C,0)(if1H<2)(0,C,X)(if2H<3)(0,X,C)(if3H<4)(X,0,C)(if4H<5)(C,0,X)(if5H<6) C = S\ H' = frac{H}{60}\ X = C (1 - |H' mod 2 - 1|)\ (R,G,B)=(V-C) (1,1,1)+egin{cases} (0, 0, 0)& ( ext{if H is undefined})\ (C, X, 0)& ( ext{if}quad 0 leq H' < 1)\ (X, C, 0)& ( ext{if}quad 1 leq H' < 2)\ (0, C, X)& ( ext{if}quad 2 leq H' < 3)\ (0, X, C)& ( ext{if}quad 3 leq H' < 4)\ (X, 0, C)& ( ext{if}quad 4 leq H' < 5)\ (C, 0, X)& ( ext{if}quad 5 leq H' < 6) end{cases}
    这里将实现将色相反转(色相值加180180),然后再用RGB ext{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]
    
    	# H未定义情况处理
    	out[np.where(Max == Min)] = 0
    	# 防止越界
    	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()
    
    结果展示
    原图 色相反转
    在这里插入图片描述 在这里插入图片描述
  • 相关阅读:
    UIButton中setTitleEdgeInsets和setImageEdgeInsets的使用
    关于自定义导航条UIBarButtonItem偏移的问题
    iOS端使用二维码扫描(ZBarSDK)和生成(libqrencode)功能
    CocoaPods安装和使用教程
    IOS中NSUserDefaults的用法(轻量级本地数据存储) (转)
    UIPickerView简单选择器的基本使用
    [原]Unity手游之路&lt;三&gt; 基于Unity+Java的聊天室源码
    [原]UML建模语言进阶
    [原]Java多线程编程学习笔记之九:使用wait/notify/notifyAll实现线程间通信的几点说明
    [原]MySQL的表分区
  • 原文地址:https://www.cnblogs.com/Jack-Tim-TYJ/p/12831923.html
Copyright © 2020-2023  润新知