水下色块识别的问题及解决方案【Opencv】

背景:

在水下环境中,由于水质、光线和拍摄设备的影响,图像通常会出现色彩失真、对比度降低等问题。这些问题对于色块识别任务来说是一个挑战。要求使用OpenCV库,设计一个算法,实现对水下环境中特定色块的识别。

RGB三色卡

水下识别的任务需求为在一组水下拍摄的视频中逐帧识别,即一套算法在应对光照变化、颜色失真等问题下依然可以正常识别,为模拟水下的实践识别需求,本题目数据由多组色块在泳池中的实拍合成,不同组别色块环境(光照,角度)不同。

要求

要求对下图进行识别,将图中的色块圈出,并进行图像识别。

对此整图进行识别

示例:

 

识别示例1-较差

识别示例2-较好

事项:

1.考虑到水下环境的特殊性,算法应具有较好的鲁棒性,能够应对光照变化、颜色失真等问题。

2.在实现算法时,注意代码的可读性和可维护性,适当添加注释和说明。

工具

Rgbhsv转换工具:https://www.rapidtables.org/zh-CN/convert/color/rgb-to-hsv.html

解题:

import cv2
import numpy as np
import matplotlib.pyplot as plt
def find_color_blocks(image):
    # 将图像转换为HSV颜色空间
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    
    # 定义背景的HSV颜色范围
    lower_bg = np.array([90, 50, 50])
    upper_bg = np.array([160, 255, 255])
    
    # 根据背景的颜色范围创建背景掩码
    mask_bg = cv2.inRange(hsv, lower_bg, upper_bg)
    
    # 对图像进行二值化处理,将背景设置为白色,前景设置为黑色
    _, binary = cv2.threshold(mask_bg, 100, 255, cv2.THRESH_BINARY)
    
    # 反转二值化图像,使前景为白色,背景为黑色
    binary = cv2.bitwise_not(binary)
    
    # 查找图像中的轮廓
    contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    # 绘制轮廓
    result = image.copy()
    cv2.drawContours(result, contours, -1, (0, 255, 0), 2)
    
    # 显示二值化结果和轮廓
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.imshow(binary, cmap='gray')
    plt.title('Binary Image')
    plt.axis('off')
    
    plt.subplot(1, 2, 2)
    plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
    plt.title('Contours')
    plt.axis('off')
    
    plt.show()
    
    # 对每个轮廓进行颜色判断
    for contour in contours:
        area = cv2.contourArea(contour)
        if area > 100:  # 忽略面积小于100的轮廓
            # 获取轮廓的外接矩形
            x, y, w, h = cv2.boundingRect(contour)
            roi = image[y:y+h, x:x+w]
            
            # 在图像中绘制外接矩形
            cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
            
            # 计算外接矩形区域的颜色平均值
            mean_color = cv2.mean(roi)[:3]
            color = get_color_name(mean_color)
            
            # 在图像中显示颜色标签
            cv2.putText(image, color, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
    
    # 显示最终结果
    plt.figure(figsize=(5, 5))
    plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    plt.title('Final Result')
    plt.axis('off')
    plt.show()

def get_color_name(color):
    # 定义颜色名称
    colors = {'Red': (0, 0, 255),
              'Green': (0, 255, 0),
              'Blue': (255, 0, 0)}
    
    # 计算颜色与已知颜色的距离
    distances = {name: np.linalg.norm(np.array(color) - np.array(value)) for name, value in colors.items()}
    
    # 找到距离最小的颜色名称
    color_name = min(distances, key=distances.get)
    
    return color_name

# 读取图像
image = cv2.imread('test.png')

# 查找并标记色块
find_color_blocks(image)
cv2.imshow('Result', image)

结果:

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值