1.偏色检查
在图像处理中,RGB 色彩空间虽然直观,但由于其三个通道(红、绿、蓝)之间的相关性较强,不利于颜色分析和分割。因此,HSV 色彩空间(色调 Hue、饱和度 Saturation、明度 Value)被广泛使用,尤其是在偏色检查和图像分割任务中。
HSV 色彩空间的优势
-
颜色分离更清晰:
- HSV 将颜色信息(色调 H)、颜色纯度(饱和度 S)和亮度(明度 V)分离,便于单独处理。
- 相比于 RGB 空间,HSV 更符合人类对颜色的感知。
-
适合图像分割:
- 在 HSV 空间中,可以通过调整色调(H)和饱和度(S)来提取特定颜色的区域。
- 明度(V)通道可以单独处理,例如通过直方图均衡化提升亮度。
-
偏色检查更有效:
- 在 RGB 空间中,偏色检查容易受到亮度变化的影响。
- 在 HSV 空间中,色调(H)和饱和度(S)能够更准确地反映颜色偏差。
HSV 色彩空间的三个通道
-
色调(Hue, H):
- 表示颜色的基本属性,用角度度量,范围为 0°~360°。
- 红色为 0°,绿色为 120°,蓝色为 240°。
- 补色关系:黄色(60°)、青色(180°)、品红(300°)。
-
饱和度(Saturation, S):
- 表示颜色的纯度,范围为 0%~100%。
- 饱和度越高,颜色越鲜艳;饱和度越低,颜色越接近灰色。
- 光谱色的饱和度为 100%,白色的饱和度为 0%。
-
明度(Value, V):
- 表示颜色的亮度,范围为 0%(黑色)~100%(白色)。
- 对于光源色,明度与发光体的亮度相关;对于物体色,明度与透射比或反射比相关。
HSV 在图像处理中的应用
-
偏色检查:
- 在 HSV 空间中,通过分析色调(H)和饱和度(S)的分布,可以检测图像是否存在偏色。
- 例如,如果图像的色调集中在某个狭窄范围内,可能存在偏色问题。
-
图像分割:
- 通过设定色调(H)和饱和度(S)的阈值,可以提取特定颜色的区域。
- 例如,提取图像中的绿色植物或红色标志。
-
亮度增强:
- 对明度(V)通道进行直方图均衡化,可以提升图像的亮度,同时不影响颜色信息。
"""
Time :
Author :
"""
import cv2
import numpy as np
from typing import Union
from xxx.utils.logger import loger
class ColorClassify:
def __init__(self):
self.logger = loger
self.hsv_color_dict = {
"black": [np.array([0, 0, 0]), np.array([180, 255, 46])],
"gray": [np.array([0, 0, 46]), np.array([180, 43, 220])],
"white": [np.array([0, 0, 221]), np.array([180, 30, 255])],
"red": [np.array([156, 43, 46]), np.array([180, 255, 255]), np.array([0, 43, 46]), np.array([10, 255, 225])],
"green": [np.array([35, 43, 46]), np.array([77, 255, 255])],
"blue": [np.array([100, 43, 46]), np.array([124, 255, 255])],
"yellow": [np.array([26, 43, 46]), np.array([34, 255, 255])],
"orange": [np.array([11, 43, 46]), np.array([25, 255, 255])],
"purple": [np.array([125, 43, 46]), np.array([155, 255, 255])],
"pink": [np.array([0, 43, 46]), np.array([10, 255, 255])],
"brown": [np.array([0, 0, 0]), np.array([180, 30, 46])]
}
self.detect_result = {}
def analysis_picture(self, image_path: str, threshold=0.9) -> None:
for color in self.hsv_color_dict.keys():
self.detect_result[color] = self.detect_color(image_path, color, threshold)
def is_this_color(self, color: str) -> bool:
if color.lower() not in self.detect_result.keys():
return False
elif self.detect_result[color.lower()] >= 0.9:
return True
else:
return False
@staticmethod
def is_contain_chinese(img_url) -> bool:
"""
判断img_url路径是否含有中文字符
:param img_url: 图片路径
:return: True or False
"""
# 中文字符的正则表达式
import re
chinese_pattern = '[\u4e00-\u9fa5]'
result = re.search(chinese_pattern, img_url)
if result:
return True
else:
return False
def read_image_file(self, image_obj: Union[str, numpy.ndarray]) -> numpy.ndarray:
"""统一读取图片"""
if isinstance(image_obj, numpy.ndarray):
return image_obj
if self.is_contain_chinese(image_obj):
img_obj = cv2.imdecode(np.fromfile(image_obj, dtype=np.uint8), flags=cv2.IMREAD_COLOR)
return img_obj
else:
return cv2.imread(image_obj)
def detect_color(self, image_obj: Union[str, numpy.ndarray],
color: str,
threshold: float = 0.9,
get_ratio: bool = False) -> Union[str, bool]:
"""
判断图片是什么偏什么颜色的
:param image_obj: 图片路径或者数组
:param color: 什么颜色
:param threshold: 阈值
:param get_ratio: 是否获取概率值
:return:
"""
try:
# 读取图片
# self.logger.info(f"即将判断图片:{image_obj}是否是:{color}颜色")
img = self.read_image_file(image_obj)
# 转换颜色空间为HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 创建掩膜
# Note:红色需要创建两个,因为hmin和hmax有两种可能的值
if color.lower() == "red":
mask1 = cv2.inRange(hsv, self.hsv_color_dict[color.lower()][0], self.hsv_color_dict[color.lower()][1])
mask2 = cv2.inRange(hsv, self.hsv_color_dict[color.lower()][2], self.hsv_color_dict[color.lower()][3])
mask = cv2.bitwise_or(mask1, mask2)
else:
mask = cv2.inRange(hsv, self.hsv_color_dict[color.lower()][0], self.hsv_color_dict[color.lower()][1])
# 进行图像处理
# res = cv2.bitwise_and(img, img, mask=mask1)
purple_pixel_count = cv2.countNonZero(mask)
total_pixels = img.shape[0] * img.shape[1]
detect_ratio = purple_pixel_count / total_pixels
# 判断是否为color色
if get_ratio:
self.logger.info("这张图片是{}的概率为:{}".format(color, detect_ratio))
return detect_ratio
if detect_ratio > threshold:
self.logger.info("这张图片是{}的概率为:{}".format(color, detect_ratio))
self.logger.info("检测到图片偏色")
return True
else:
return False
except:
self.logger.error("判断图片偏色失败")
if get_ratio:
return '1000.0'
return True
二、颜色提取、图像分割
同样,可以将图片从RGB转换成HSV提取图片中对应颜色的区域,例如我们提取下面这张图片绿色的区域。
整体思路如下:
- 将图像从 BGR 色彩空间转换到 HSV 色彩空间。
- 定义绿色的 HSV 阈值范围。
- 使用阈值对图像进行分割,提取绿色区域。
- 对分割结果进行后处理(如形态学操作)以去除噪声。
- 展示原始图像和分割结果。
import cv2
# 读取图像
image = cv2.imread('test.jpg')
# 将图像从 BGR 转换到 HSV 色彩空间
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 定义绿色的 HSV 阈值范围
lower_green = np.array([35, 43, 46]) # 下限
upper_green = np.array([77, 255, 255]) # 上限
# 根据阈值创建掩码
mask = cv2.inRange(hsv_image, lower_green, upper_green)
# 对掩码进行形态学操作(可选)
kernel = np.ones((5, 5), np.uint8) # 定义kernel
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) # 开运算去除噪声
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 闭运算填充空洞
# 将掩码应用到原始图像,提取绿色区域
result = cv2.bitwise_and(image, image, mask=mask)
cv2.imshow('Original Image', image)
cv2.imshow('Green Mask', mask)
cv2.imshow('Extracted Green', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果如下图(图片压缩了,长宽看着不是很协调)
通过 HSV 色彩空间和阈值分割,可以轻松提取图像中的特定颜色区域。这种方法适用于许多应用场景,例如:
- 提取自然图像中的指定颜色区域。
- 检测交通标志中的红色或蓝色区域。
- 分割医学图像中的特定组织。
三、亮度增强
亮度增强是对HSV中的V(明度通道)进行处理,处理完成后再转回RGB。完成在同时保留色调和饱和度信息的前提下,增强图像的亮度。
整体思路如下:
- 将图像从 BGR 色彩空间转换到 HSV 色彩空间。
- 分离 HSV 通道,提取明度(V)通道。
- 对明度通道进行直方图均衡化,增强亮度。
- 将增强后的明度通道与原始色调(H)和饱和度(S)通道合并。
- 将图像从 HSV 转换回 BGR 色彩空间。
- 展示原始图像和亮度增强后的图像。
import cv2
# 读取图像
image = cv2.imread('test.jpg')
# 将图像从 BGR 转换到 HSV 色彩空间
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 分离 HSV 通道
h, s, v = cv2.split(hsv_image)
# 对明度(V)通道进行直方图均衡化
v_enhanced = cv2.equalizeHist(v)
# 合并增强后的明度通道与原始色调和饱和度通道
hsv_equalized = cv2.merge([h, s, v_enhanced])
# 将图像从 HSV 转换回 BGR 色彩空间
result = cv2.cvtColor(hsv_equalized, cv2.COLOR_HSV2BGR)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Brightness Enhanced Image', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
通过调整 HSV 空间中的明度(V)通道,可以有效增强图像的亮度,同时保留色调和饱和度信息。这种方法适用于以下场景:
- 提升低光照条件下拍摄的图像亮度。
- 增强图像中的细节信息。
- 改善图像的视觉效果。