opencv 使用Python从图像中提取准确的产品颜色和背景颜色

aiqt4smr  于 2023-10-24  发布在  Python
关注(0)|答案(1)|浏览(155)

我尝试从模特穿着产品(例如,一条裙子)的图像中提取产品颜色和背景颜色。我目前的方法涉及屏蔽皮肤和头发颜色,然后使用KMeans聚类来找到主色。然而,结果并不总是准确的,特别是当产品颜色与背景或模特的皮肤/头发相似时。
下面是我一直在使用的代码:

import cv2
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

def mask_human_colors(image):
    # Convert the image to HSV
    hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
    
    # Define a range for skin colors in HSV
    lower_skin = np.array([0, 20, 70], dtype=np.uint8)
    upper_skin = np.array([20, 255, 255], dtype=np.uint8)
    skin_mask = cv2.inRange(hsv, lower_skin, upper_skin)
    
    # Define a range for common hair colors in HSV (This is a rough estimate and might need adjustments)
    lower_hair = np.array([0, 0, 0], dtype=np.uint8)
    upper_hair = np.array([180, 255, 60], dtype=np.uint8)
    hair_mask = cv2.inRange(hsv, lower_hair, upper_hair)
    
    # Combine the skin and hair masks
    human_mask = cv2.bitwise_or(skin_mask, hair_mask)
    
    # Mask the image to remove human colors
    masked_image = cv2.bitwise_and(image, image, mask=~human_mask)
    
    return masked_image

def extract_top_colors(image, k=2):
    pixels = image.reshape(-1, 3)
    pixels = pixels[np.any(pixels != [0, 0, 0], axis=1)]  # Removing black pixels
    kmeans = KMeans(n_clusters=k, n_init=10)
    kmeans.fit(pixels)
    sorted_labels = np.argsort(np.bincount(kmeans.labels_))[::-1]
    colors = [kmeans.cluster_centers_[label].astype(int).tolist() for label in sorted_labels]
    return colors

# Usage:

image_path = '/content/white_dress.JPG'
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# Mask human colors
masked_image = mask_human_colors(image)

# Extract top colors
dominant_colors = extract_top_colors(masked_image, k=2)

print(f"1st Dominant Color (RGB): {dominant_colors[0]}")
print(f"2nd Dominant Color (RGB): {dominant_colors[1]}")

fig, ax = plt.subplots(1, 3, figsize=(20, 5))
ax[0].imshow(image)
ax[0].set_title("Original Image")
ax[1].imshow(masked_image)
ax[1].set_title("Image after Masking Human Colors")
ax[2].imshow([dominant_colors])
ax[2].set_title("Top 2 Dominant Colors")
plt.tight_layout()
plt.show()

下面是我正在使用的示例图像:x1c 0d1x
在某些情况下,提取的产品颜色比实际产品的颜色浅,或者它会选择背景颜色。
目前的解决方案结果显示:

我正在寻找提高颜色提取准确性的建议或可能更有效的替代技术。
谢谢你

cbwuti44

cbwuti441#

我以前从事过颜色提取工作,我知道在复杂背景的图像中很难做到这一点,但有几种方法可以提高颜色提取过程的准确性。首先,不要手动定义皮肤和头发的颜色范围,考虑使用预先训练好的深度学习模型进行前景分割(Mask R-CNN或U-Net等模型)。
分割后,你可以使用阈值来进一步细化蒙版,以去除小的伪影并微调蒙版。然后,我觉得你应该考虑分析颜色通道的直方图,以识别与产品颜色对应的峰值。你可以在这些峰值上设置阈值,以提取主导产品颜色。如果你以前没有这样做,您可以使用第三方工具,如Cloudinary,它提供了一个histogram of 32 RGB colors,使用一个简单的API调用来最好地匹配您的图像。如果您可以访问语义分割模型,它可以帮助您识别图像中的不同对象类。然后您可以专注于分类为产品的区域。同样,出于此目的,您可以使用我上面提到的API或任何其他工具。
最后,使用背景减除技术完全去除背景。这可以简化颜色提取过程。为此,您可以使用OpenCV的BackgroundSubtractorMOG2或其他在线选项。

相关问题