颜色通道(color channel)不能光用类比三原色的方法来理解,还需要理解灰度值(gray scale)。

数字图像的本质是矩阵。

每个矩阵内的元素可以看作是一个像素,每个元素都有关于 BGR 三种颜色的灰度值,而灰度值表示的是颜色的“深浅/强弱/明亮”。灰度值越高,颜色越深/强/暗,反之则是越浅/弱/亮。

如果一个像素的 BGR 的灰度是 [100, 40, 35]。那么这就表示,这个像素的蓝色通道的灰度值是100,绿色的通道的灰度值是40,红色的则是35。这些颜色混合在一起就变成了这个像素的颜色。


P1.d 的题目要求的是:

Modify the above code snipet to replace the green with blue, red with green, and blue with red channels.

也就是: green -> blue red -> green blue -> red

第一次解法:

newColor.at<Vec3b>(i, j)[0] = r;
newColor.at<Vec3b>(i, j)[1] = b;
newColor.at<Vec3b>(i, j)[2] = g;

实际上是: red -> blue blue -> green green -> red

可以将灰度想象成一个容器,灰度值则是液体。液体越多,就代表这个颜色越深。 假设有一个像素是蓝色的,那么这个像素的蓝色容器装满了液体的,而红色和绿色的容器是空的。 如果我要把像素变成红色,那么我就要把蓝色容器的液体都倒进红色容器里面。

而第一次解法中的:

// 容器                      液体
newColor.at<Vec3b>(i, j)[0] = r;
newColor.at<Vec3b>(i, j)[1] = b;
newColor.at<Vec3b>(i, j)[2] = g;

实际上将: 红色容器的液体倒进了蓝色容器。 蓝色容器的液体倒进了绿色容器。 绿色容器的液体倒进了红色容器。 因此: 原来的蓝色会变成绿色。 原来的绿色会变成红色。 原来的红色会变成蓝色。

所以原来的红色变成了蓝色,而不是蓝色变成了红色。

正确解法的应该是:

newColor.at<Vec3b>(i, j)[0] = g;
newColor.at<Vec3b>(i, j)[1] = r;
newColor.at<Vec3b>(i, j)[2] = b;

Reference: 如何通俗易懂地讲解 Photoshop 中的「通道」概念? - 知乎