当你只有一杯好咖啡时如何实现按颜色搜索

2020-06-12 10:00:16

嘿你好啊!上周,我开始重写Shefa Products,这是阿根廷的批发电子商务。

重写不仅仅是将其从Angular.JS(版本1,您还记得吗?)。到Next.JS和Adonis框架,而且能够更快地添加功能,并从SSG和伟大的灯塔得分中获得SEO好处。

所以在与一些客户交谈之后,我得到的一个发现是。

这完全说得通。商品营销就是这样一个行业,你挑选一个背包或一支笔,在上面盖上你的标志,然后把它送给你未来的客户或最好的员工。你完全需要背包或钢笔的颜色来匹配你的品牌。

所以“让我们更容易找到与你的品牌相匹配的产品”--我想。

(给读者的注意:重写还没有上线,但是如果你想看看这个特性的结果,我在这篇博文的末尾添加了一段视频来展示它。如果您想了解我遇到的困难以及我是如何想出还可以的解决方案的,请继续阅读:))。

这个问题与其他问题的不同之处在于,我无意中遇到了产品图片与颜色信息没有关联的问题。

这意味着-不像亚马逊,你从下拉列表中选择一种产品颜色,该颜色的产品图像会自动成为焦点-在这里,这是不可能的:我既有产品的颜色变化列表,也有产品的图像列表;但它们不匹配。

所以这是一个很大的问题,没有一个简单的启发式方法可以解决它。

我们掌握的关于颜色的唯一信息就是图片本身。所以我们必须从那里推断出来。

例如,对于下面的两个图像,第一个图像将是绿色的,而第二个图像不是。

拉链是绿色的,包上印有绿色标志会很不错。

然后我们必须重新表述我们前面说过的话:我们不想要绿色的图像,我们想要的是产品的图像,上面要有一个绿色的标志。

也许,让产品与标志的颜色搭配得很好的是一些细节,比如这种情况下的绿色拉链。因此,计算“绿色”像素并不能很好地代表我们的目标,因为这里的绿色像素数量会很少。

我们可以创建一个深度神经网络,并教它对我们认为“配上绿色标志就行”的产品进行分类。但是训练一个模型和设置一台烧瓶服务器似乎是一件苦差事(也许这对于初创公司来说是个好主意。我想要像Fast.ai这样简单的东西,但是要将模型部署到实时服务器上)和Overkill(过度杀伤力)。我希望这个功能最多在三天内发布。

有一个很棒的软件包叫做“颜色窃贼”,它给出了一幅图像,它告诉你图像中出现的调色板。

在那里我们可以看到,绿色出现在调色板的第三个位置。太棒了!

现在,我们可以使用图像的主要颜色列表,而不是使用图像。

但是,我们如何判断一系列颜色是否构成了与绿色搭配良好的图像呢?

一个好主意是尝试检查列表中出现的那些颜色中是否有任何一种是“绿色”的。

判断一种随机颜色是否是一种绿色比判断它有多绿要困难得多。

因为判断它是否是绿色,不仅意味着你知道这种颜色与纯绿色有多接近,而且还迫使你定义一种界限,区分属于绿色和不属于绿色的颜色。

因此,与其给出肯定或否定的答案--比如“这个特定的背包与绿色品牌匹配吗?”--也许我们可以计算出一种颜色的“绿色”分数,并用它来根据产品图片的颜色与我们试图匹配的颜色的接近程度来对产品进行排序。

现在,我们正在寻求创造一个公式,让我们知道绿色有多少是一种颜色。我们该怎么做呢?

但为了简单起见,我只取了给定颜色和(0,255,0)之间的欧几里得距离,(0,255,0)是RGB值中的绿色。

嗯,因为我必须给出一个公式,它也允许我按粉色、黄色或棕色排序。这些颜色不是由RGB矢量中的唯一字段表示的。

我非常肯定有更好的方法来做这件事,这样会产生更好的结果,但就我所见,这已经足够简单和好了。

好的好的,我给你。JavaScript不是进行繁重处理的最佳语言。

考虑到我们有数以千计的产品,每个产品有几十个图像,每个图像调色板都有几十种颜色,用javascript实现这样大小的搜索会很快降低我们的性能。

我最好的选择是直接在PostgreSQL上做这件事,这是我们将要使用的数据库,而且速度非常快。

一旦我们决定在DB上执行所有这些处理,下一步就是找出如何处理!

PostgreSQL中并没有真正的颜色类型来表示颜色,因为有一种varchar类型来表示字符串。

立方体类型使您可以使用欧几里得空间中的坐标:计算距离、检查点是否在给定空间中等…。

下一步将创建一个表Colors,并将多个颜色关联到单个图像。我不会详细介绍如何做到这一点,但是有数千个教程介绍了如何创建和链接表。我还写了一本数据库模式设计的简明指南,您可能会觉得有帮助。

现在,在Colors表中,您可以添加一个CUBE类型的列,它将保存我们的颜色的实际值,即我们的“绿色”颜色的(10,220,10)RGB向量。

现在,在javascript中,您可以保存图像的颜色列表,如下所示。

//在Colors表中创建4行,图像调色板等待Promise.map(list_of_Colors.Slice(0,4),(Color)=>;Database.raw(`Insert Into Colors(Pantone,image_id)Values(';(${color})';::cube,${imageInstance.id}`)。

注意,我们应用于color变量的::cube类型转换包含一个长度为3的数组,每个位置都有RGB组件。

我们必须为数据库中的每个图像执行此操作。因此创建一个处理它们的脚本。就我个人而言,我刚刚添加了一个自定义钩子,它在每次将新图像保存到数据库时运行。

最后,要查询数据,可以使用以下SQL查询,它不仅会返回“更环保”的产品,还会为每个产品返回其中最环保的图像

SELECT*FROM(SELECT DISTINCT ON(p.id)Near_images.Distance,p.*,pi.url from product_images.pi Join(SELECT SUM(cube_Distance(';(0,255,0)';::cube,Pantone))Distance,image_id from Colors group by image_id order by 1 ASC)near_images.image_id=pi.id连接pi.上的产品p。product_id=p.id order by p.id,near_images.s。

当客户请求另一种颜色时,请务必将(0,255,0)更改为另一种颜色。

因此,新版本的Shefa产品仍在开发中,但这里是我上传到YouTube上的功能的一个改进!