HSV值获取
在计算机视觉中,颜色提取是一种常用的图像处理技术,其中HSV(色相、饱和度、明度)是一种常见的颜色空间,用于描述和提取图像中的颜色信息。
HSV颜色空间将颜色表示为三个分量:色相(H)、饱和度(S)和明度(V)。
- 色相(Hue): 色相是颜色的类型或类别,描述了颜色在光谱中的位置。在HSV模型中,色相表示为一个角度值,通常在0到360度之间,将整个颜色光谱分为不同的颜色区域,如红、橙、黄、绿、蓝、紫等。
- 饱和度(Saturation): 饱和度表示颜色的纯度或强度,即颜色的深浅程度。饱和度为0时,颜色变为灰阶;饱和度为最大值时,颜色呈现出最鲜艳的状态。饱和度的取值范围通常在0到1之间,也可以表示为0%到100%。
- 明度(Value): 明度表示颜色的明亮度,即颜色的亮度和深度。明度为0时,颜色为黑色;明度为最大值时,颜色为白色。明度的取值范围通常在0到1之间,也可以表示为0%到100%。
通过这三个参数的组合,可以在HSV模型中精确地描述各种颜色,使得调整和理解颜色更加直观和容易。在图像处理中,HSV模型常用于调整图像的颜色平衡、色调和亮度等方面。
硬件环境
操作环境及软硬件配置如下:
- OriginEye 智能相机
- PC:Ubuntu (≥20.04) + ROS2 (≥Foxy)
代码
import cv2 import numpy as np import rclpy from rclpy.node import Node from sensor_msgs.msg import Image from cv_bridge import CvBridge from collections import deque import textwrap class GetHsv(Node): def __init__(self): super().__init__('get_hsv') self.get_logger().info("Start get HSV") self.bridge = CvBridge() self.image_sub = self.create_subscription(Image, '/image_raw', self.image_callback, 10) self.pub = self.create_publisher(Image, '/camera/process_image', 10) self.count = 0 self.box_width = 60 self.collect_times = 300 self.HSV_value = deque(maxlen=self.collect_times) self.H_range, self.S_range, self.V_range = 10, 80, 80 self.lower_HSV = None self.upper_HSV = None def image_callback(self, msg): image = self.bridge.imgmsg_to_cv2(msg, 'bgr8') if self.count < self.collect_times: self.draw_rectangle(image) elif self.count < self.collect_times + self.collect_times: self.collect_hsv_value(image) else: self.save_hsv_value(image) self.count += 1 self.pub.publish(self.bridge.cv2_to_imgmsg(image, 'bgr8')) def draw_rectangle(self, image): text = 'please put the color being tested in the rectangle box!' self.add_text(image, text) rect_x = (image.shape[1] - self.box_width) // 2 rect_y = (image.shape[0] - self.box_width) // 2 cv2.rectangle(image, (rect_x, rect_y), ( rect_x + self.box_width, rect_y + self.box_width), (0, 255, 0), 3) def collect_hsv_value(self, image): text = 'HSV_value is collecting!' self.add_text(image, text) frame_x = (image.shape[1] - self.box_width) // 2 frame_y = (image.shape[0] - self.box_width) // 2 frame = image[frame_y:frame_y + self.box_width, frame_x:frame_x + self.box_width] self.HSV_value.append(self.calculate_mean_hsv(frame)) def save_hsv_value(self, image): text = 'HSV_value is collected!' self.add_text(image,text) mean_HSV = np.mean(self.HSV_value, axis=0) self.lower_HSV, self.upper_HSV = self.calculate_hsv_range(mean_HSV) self.write_hsv_to_file(self.lower_HSV, self.upper_HSV) def calculate_mean_hsv(self, img): hsv_image = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) return np.mean(hsv_image, axis=(0, 1)) def calculate_hsv_range(self, HSV_value): lower_H = np.clip(int(HSV_value[0] - self.H_range), 0, 180) upper_H = np.clip(int(HSV_value[0] + self.H_range), 0, 180) lower_S = np.clip(int(HSV_value[1] - self.S_range), 40, 255) upper_S = np.clip(int(HSV_value[1] + self.S_range), 40, 255) lower_V = np.clip(int(HSV_value[2] - self.V_range), 40, 255) upper_V = np.clip(int(HSV_value[2] + self.V_range), 40, 255) return np.array([lower_H, lower_S, lower_V]), np.array([upper_H, upper_S, upper_V]) def write_hsv_to_file(self, lower_HSV, upper_HSV): content = f"block_HSV is : {lower_HSV[0]}, {lower_HSV[1]},{lower_HSV[2]} {upper_HSV[0]},{upper_HSV[1]},{upper_HSV[2]}\n" filename = "/userdata/dev_ws/color_block_HSV.txt" with open(filename, "w+") as f: f.write(content) self.get_logger().info(f"HSV value has been saved in {filename}") self.get_logger().info(content) def add_text(self, image, text): text = textwrap.wrap(text, width = 80) text_y = image.shape[0] // 2 - 30 for line in text: text_size, _ = cv2.getTextSize(line, cv2.FONT_HERSHEY_SIMPLEX, 1.2, 2) text_x = (image.shape[1] - text_size[0]) // 2 cv2.putText(image, line, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 2, cv2.LINE_AA) def main(args=None): rclpy.init(args=args) get_hsv = GetHsv() rclpy.spin(get_hsv) get_hsv.destroy_node() rclpy.shutdown() if __name__ == '__main__': main()
点击HSV值获取 - 古月居可查看全文