红色网袋会让橘子看起来更“橘”吗?

2025年4月13日 · 1326 字 · 阅读约 7 分钟 · Human-Citrus Interaction

看看这个橘子:

没有网袋的橘子

现在看看这个橘子:

装着网袋的橘子

这是同一个橘子。

但是,看看盖上红色网袋后,它看起来“橘”了多少:

橘子有无网袋的 GIF 动画

如果你买袋装橘子(至少在美国很多地方是这样),它们通常都装在红色网袋里。这种网袋会让橘子看起来更橘。更“橘”。

这是在当地一家杂货店看到的情况1:

Trader Joe’s 出售的 Sumo 橘子,一箱装着网袋,另一箱是单个橘子

成熟的橘子通常更“橘”,所以这个网袋让橘子看起来比实际更好。也许秘诀在于永远不要买袋装水果,因为这样更难评估每个橘子的质量。2

这让我好奇——网袋如何改变我们对颜色的感知?

我认为,如果我们做一些快速而巧妙的数字计算,就能看到这种差异:如果我们有在相同光线和相机条件下,橘子有无网袋的照片,然后检查平均像素会怎样?

以下是 11 张不同橘子照片的结果,有和没有网格:

橘子 | 没有网袋 | 有网袋 | 平均颜色 (无网袋) | 平均颜色 (有网袋) ---|---|---|---|---

1

| |

2

| |

3

| |

4

| |

5

| |

6

| |

7

| |

8

| |

9

| |

10

| |

11

| |

这里有一些有趣的事情。首先,说实话,平均像素根本不是我所期望的那样。我甚至使用更高级的计算方法(包括一些仅限于橙色的遮罩,以避免非橙色颜色)再次运行了平均像素计算,但我得到了相似的结果。它们都比我看着图像时眼睛所认为的要棕色得多。

奇怪的是,当你仔细观察每张图片时,这有点道理。这里有一个严重的密集恐惧症警告,但你可以打开下面的剧透。

点击查看橙色皮肤的特写照片,说实话有点奇怪

仔细看,会发现真的有很多棕色!还有点恶心。

有点奇怪,对吧?但这有点道理——这件事的起因是,我们感觉我们的眼睛被颜色欺骗了,所以我们的眼睛不如我的计算机分析所有像素那么分析。

另一个有趣的事情是,红色网袋的添加显然为每种平均颜色增加了一种温暖感。我们可以看到明显的转变,即使对于那些显示为棕色的颜色也是如此。

有趣的是,我们主要在绿色中看到了 RGB 的变化。带网袋后,RGB 值的平均变化约为 (-15, -20, -4),其中绿色有更大的变化。这有点难以可视化,但这是第一种淡黄色和第二种更浓郁的橙色之间的区别:

好吧,也许不是完全浓郁的橙色,也不是完全更开胃,但我再次认为,我们的思想可能正在玩更多的把戏。可能还有一种更好的方法来思考我不熟悉的颜色变化,但即使作为一种基本衡量标准,我们也可以看到平均像素并排的这种明显变化。

当然,正如预期的那样,眼睛 极其 复杂的,答案比平均像素值要微妙得多:我们的眼睛适应环境,记住事物的颜色,并动态变化。

鉴于这种技巧发生在我们的眼睛里,我认为更好的实验是以人为本的实验,了解我们如何感知平均颜色。也许我们可以分成两组,一组有网袋,一组没有网袋,我们向他们展示裁剪后的照片,并让他们挑选他们在照片中感知到的平均颜色(或最主要的颜色?)。然后我们可以跨组比较,以确认带网袋的照片偏红。

也许改天吧。我想我已经盯着橘子的照片太久了。

无论如何,这是我如何设置的。

我的橘子拍照实验设置,我的狗在看着 实验设置,附作者细心的助手

我拍摄了 11 张不同橘子在相同位置的照片,有和没有红色网格,并裁剪了每张照片的相同部分。

我找到了我想要的正方形的像素位置,然后将这些坐标转换为 sips 命令(Scriptable Image Processing System)的特定偏移量,这是我今天了解到的。这使得程序化裁剪非常容易。例如,以两个文件 orange-1-with.jpegorange-1-without.jpeg 裁剪 Orange 1 的两张照片,有和没有网格,位置相同:

for f in orange-1*.jpeg; 
 do sips -c 788 740 --cropOffset 1519 1083 "$f"; 
done

这让我从这两张照片:

变成这两张照片

假设我放上网格而没有干扰橘子,这意味着我们将在这两者之间进行精确比较。

在我对所有照片都这样做之后,有和没有网格,我然后使用 magick 来计算平均像素值:

$ for f in *-cropped.jpeg; 
>  do  echo -n "$f: ";  
>  magick "$f" -resize 1x1 txt:- | grep -o '#[A-Fa-f0-9]\{6\}'; 
> done
orange-1-with-cropped.jpeg: #B9310A
orange-1-without-cropped.jpeg: #D0530A
...

非常简洁!

一旦我发现一切都显示出更多的棕色,我还尝试了一个利用 OpenCV 的基本 Python 脚本。该脚本为每个图像创建一个遮罩,排除非橙色的像素,由我定义的范围定义。然后,它可以仅对落在遮罩之外的橙色像素取平均值。

for file in files:
  image = cv2.imread(file)
  # Convert to HSV color space (better for color detection)
  hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
  # Define the range for orange in HSV. This took some tinkering to get the right values.
  lower_orange = np.array([3, 150, 150])
  upper_orange = np.array([20, 255, 255])
  # Mask the image to get only the orange parts.
  mask = cv2.inRange(hsv, lower_orange, upper_orange)
  orange_pixels = cv2.bitwise_and(image, image, mask=mask)
  # For debugging, I saved the binary mask to visualize them.
  mask_filename = os.path.join(output_mask_dir, os.path.basename(file).replace(".jpeg", "_mask.png"))
  cv2.imwrite(mask_filename, mask)
  # I also saved just the orange parts to visualize it.
  orange_only_filename = os.path.join(output_orange_only_dir, os.path.basename(file).replace(".jpeg", "_orange.png"))
  cv2.imwrite(orange_only_filename, orange_pixels)
  # Now, take the mean of the orange pixels with the mask, which means we're (hopefully) ignoring all of the browner 
  # pixels when calculating the mean.
  bgr_avg = cv2.mean(orange_pixels, mask=mask)[:3]
  # Then, translate to RGB (and HSV for debugging).
  rgb_avg = tuple(reversed(bgr_avg))
  hsv_avg = cv2.cvtColor(np.uint8([[bgr_avg]]), cv2.COLOR_BGR2HSV)[0][0]
  print(file, "Average RGB orange color:", rgb_avg, "HSV:", hsv_avg)

这非常简洁,因为这意味着我可以遮盖掉任何非橙色的像素(比如非常暗的阴影)。最终看起来像这样,带有原始照片、遮罩和仅用于平均值的橙色部分:

我必须承认,我作弊并试图让上面表格中的 CSS 框看起来更橙色。这不是我们的眼睛的工作方式,而且这些最终看起来更柔和。也许是因为我在翻译中弄错了什么?平均像素值最终非常非常相似,所以我最终只是在上面的表格中使用了 magick 值。不过,尝试一下很有趣3

这也是一个很好的例子,说明了使用 LLM 进行此实验有多么容易——能够轻松发现用于裁剪或像素评估的工具意味着从想法到概念验证的时间非常非常短。

即使使用这些黯淡的棕色平均像素,我仍然确信红色网袋使橘子看起来更橙色。这不足以打电话给 FTC,但这是一个有效的小技巧,一种我们都必须忍受的小小的成熟度欺骗。

  1. 这篇文章与 Sumo Citrus 没有关联,但作者对赞助协议非常感兴趣。 ↩︎
  2. 商店也对鳄梨使用绿色袋子,以及其他东西。那将是引用这篇论文的后续论文。 ↩︎
  3. 简历的新增内容:“精通计算机视觉” ↩︎