繁体   English   中英

python django 按主色搜索图像

[英]python django search image by dominant color

我正在使用 django(3.0) python(3.8) 构建一个包含一堆图片的网站。 我正在尝试制作一个过滤器,其中用户 select 一种颜色并返回主色是用户请求的颜色的图像。 要做到这一点,

  1. 使用 colorgram (pip install colorgram.py) 提取两种主色(除了那些太白的颜色),并在保存实例时将其保存到“dominant_color”字段。
def RgbToInt(rgb):
    red = rgb[0]
    green = rgb[1]
    blue = rgb[2]
    RGBint = (red << 16) + (green << 8) + blue
    return RGBint

class Design(models.Model):
    ...fields...
    image = ImageField(upload_to=upload_image_path)
    dominant_color = models.CharField(max_length=80, blank=True)

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        img = Image.open(self.image.path).resize((180, 180))
        colors = colorgram.extract(img, 3)
        white = 210
        color = [f'{RgbToInt(c.rgb)},{int(round(c.proportion * 100, 0))}' for c in colors
                 if not (c.rgb[0] > white and c.rgb[1] > white and c.rgb[2] > white)]
        if len(color) > 3: color = color[:2]
        self.dominant_color = color
        super(Design, self).save(force_insert=False, force_update=False, using=None,
                                 update_fields=None)

-- Colorgram 给出如下结果:

[<colorgram.py Color: Rgb(r=252, g=251, b=249), 72.43592003666748%>, 
<colorgram.py Color: Rgb(r=196, g=170, b=103), 18.46067059196841%>, 
<colorgram.py Color: Rgb(r=194, g=150, b=37), 9.103409371364101%>]

-- 我在设计 model 中将其保存为字符串,如下所示:

['12888679,18', '12752421,9']
  1. 从请求中获取颜色查询参数并在视图内进行比较。 这是我完全迷失的部分。
    ... view... 
    def get_queryset(self):
        qs = super().get_queryset()
        color = self.request.GET.get('color')
        if color:
            ...GOTTA FIND IMAGES WITH DOMINANT COLOR SIMILAR TO REQUESTED COLOR...
        return qs

- 我一直在寻找 deltaE,但据我了解,它是比较两个图像而不是两个颜色值。 感谢阅读和帮助..

扩展我的评论:

如果您将 RGB 值存储为单个打包的 integer,那么您将很难比较它们。

我建议添加一个单独的 model:

class Image:
   # ...

class ImageColor(models.Model):
   image = models.ForeignKey(Image, related_name='colors')
   proportion = models.FloatField()
   rank = models.PositiveIntegerField()
   r = models.PositiveIntegerField()
   g = models.PositiveIntegerField()
   b = models.PositiveIntegerField()
   hue = models.FloatField()
   sat = models.FloatField()
   val = models.FloatField()

   class Meta:
       unique_together = (('image', 'rank'),)

在哪里

  • proportion将是计算的比例值
  • rank将是最主要的 colors 中的颜色索引(1 表示最主要,2 表示第二等)
  • r / g / b是颜色的原始 RGB 值
  • hue / sat / val是颜色的 HSV 值( import colorsys等); 这些可能会派上用场

(您可以选择在其他对您的用例有意义的颜色系统中添加 colors。)

然后,如果用户发布一种颜色,则查询其最主要颜色接近该颜色的图像会变成类似(干编码,可能有问题或不起作用)

from django.db.models.functions import Abs, Sqrt


images = Image.objects.annotate(
    r_distance = Abs(F('colors__r') - user_r),
    g_distance = Abs(F('colors__g') - user_g),
    b_distance = Abs(F('colors__b') - user_b),
).filter(
    colors__rank=1,
    r_distance__lt=30, 
    g_distance__lt=30, 
    b_distance__lt=30,
).annotate(
    color_distance=F('r_distance') + F('g_distance') + F('b_distance')
).order_by('color_distance')

(您可以选择在 RGB 空间上选择曼哈顿距离以外的其他指标。)

查询可能不会很轻量或优化,但我敢肯定,对于初学者来说是可以的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM