【问题标题】:How can I delete all black pixels from an image and only use the unique RGB values found in the image如何从图像中删除所有黑色像素并仅使用图像中的唯一 RGB 值
【发布时间】:2017-07-30 22:40:25
【问题描述】:

如何从图像中删除所有黑色像素并仅使用图像中的唯一 RGB 值

What I'm trying to do is: 
1) delete all black pixels from the image and only use the unique RGB colors found in the image
2) export each combined RGB color pixels that is unique as a separate 640x480 image 
3) Convert / join these images into a movie file.

我的想法是在哪里将我的红色、绿色和蓝色通道拆分为相应的颜色,并将它们重新整形为三个数组,每个数组一列。 并开始删除黑色像素。

如何删除所有黑色的单元格值(其中 R、G、B 通道为 0)并且只查找/使用唯一的 RGB 值

我附上了下面的图片和代码的sn-p:

resize_tmp_red=reshape(fintersect_red',[1,1200*1200])(:); %will cause array to be created / reshaped left to right and top to bottom (like reading a book) into 1 column
resize_tmp_green=reshape(fintersect_green',[1,1200*1200])(:); 
resize_tmp_blue=reshape(fintersect_blue',[1,1200*1200])(:); 

%How can I delete all cell values that are black (where the R,G,B channels are 0) and only find / use the RGB values that are unique in the image

for cc=1:10

  repmat_rgb(:,:,1)=uint8(repmat(resize_tmp_red(cc,1),[640,480])); %creates 640x480 image of RGB taken from deleted black and unique color array.
  repmat_rgb(:,:,2)=uint8(repmat(resize_tmp_green(cc,1),[640,480]));
  repmat_rgb(:,:,3)=uint8(repmat(resize_tmp_blue(cc,1),[640,480]));

  %imshow(repmat_rgb)


  imwrite(repmat_rgb,strcat('/tmp/',sprintf('%03d', cc),'_img.png')); %creates image file

end

PS:我使用的是 Octave 4.0,它类似于 Matlab。 是的,我将不再看到原始图像的结构。我将根据图像中的独特颜色创建一部电影。

【问题讨论】:

  • 您想用其他颜色替换黑色像素吗?还是您只是想要所有非黑色颜色的“图像”?请注意,在第二个选项中,您将不再看到原始图像的结构。
  • @Cecilia 我只想要非黑色且独特的颜色。正确我将不再看到原始图像的结构。我将根据图像中的独特颜色创建一部电影。
  • 那么预期的输出是什么?您是否想要一个二维颜色矩阵,其中每一行都是唯一的非黑色 RGB 颜色?
  • @rayryeng 是的:-)
  • 你想去掉每个通道中的零还是只去掉 (0,0,0)?

标签: arrays image matlab colors octave


【解决方案1】:

正如您在评论中提到的,您想要一个具有唯一颜色的输出 2D 矩阵,其中每一行都是一个 RGB 元组没有黑色像素。您可以做的是将 RGB 图像重塑为 2D 矩阵,其中每列都是一个颜色通道,删除行完全为 0 的所有实例,然后通过unique 运行它以删除重复项。为此,您需要使用permute 执行每个通道的转置,然后利用reshape 的元素顺序来最终创建一个3 列的RGB 值矩阵。完成此操作后,使用any 查找具有至少一个值(即不是黑色像素)的所有行,过滤掉矩阵中完全为零的行,然后最后使用unique 但将其应用于行,以便假设您的图像存储在im 中,每一行都将被视为一个“示例”:

这样的事情会起作用:

% Reshape the RGB image into a 3 column matrix
R = reshape(permute(im, [2 1 3]), [], 3);

% Remove black pixels
R = R(any(R, 2), :);

% Remove duplicates
colours = unique(R, 'rows', 'stable');

colours 将是没有黑色的唯一颜色的输出 2D 矩阵。请注意,我使用了'stable' 标志来维护遇到颜色的顺序。通过忽略这一点,它将按输出中的行对矩阵进行排序。正如您在评论中指出的那样,Octave 不支持此功能,因此如果您不关心订单,您可以删除 'stable' 标志,我相信在这种情况下您不需要这样做,因为您只想要一个唯一的矩阵不包括黑色的颜色。

因此:

colours = unique(R, 'rows');

【讨论】:

  • 漂亮优雅的解决方案
  • @rayryeng 这是一个非常优雅的解决方案,不幸的是,Octave 4.0 似乎不适用于colours = unique(R, 'rows', 'stable'); 行中的'stable' 选项,是否有替代方案?
  • @RickT 是的,您可以删除 'stable'。我只是在那里确保颜色的顺序得到执行。如果您不关心订单...(我认为您不关心),请删除'stable'。你只想要一个颜色列表,我假设你不关心订单?
  • @RickT 在我之前的评论中查看我的问题。
  • @RickT 不用担心。谢谢你的接受。我还编辑了我的帖子以删除 'stable' 标志,因为现在 Octave 不支持它。真可惜。
【解决方案2】:

要找到黑色像素,您只需要将所有三个颜色通道都设为零。您可以告诉sum 函数在第三个维度上求和。如果三个通道都为零,则总和也为零。

im = imread('example.png');    
black_mask = sum(im, 3) == 0;

现在您有了一个指示黑色像素的二维蒙版。下一步是构造掩码以访问每个通道中的所有其他像素

red_mask = ~cat(3, black_mask, ones(size(black_mask)), ones(size(black_mask)))); %The inverse of the black mask in the red channel and any pixel in all other channels
green_mask = ~cat(3, ones(size(black_mask)), black_mask, ones(size(black_mask))));%For the other channels just change the order.
blue_mask= ~cat(3, ones(size(black_mask)), ones(size(black_mask)), black_mask));

好的,现在我们可以从每个通道中获取值了。

red = im(red_mask);
blue = im(blue_mask);
green = im(green_mask);

并在三维中连接它们以制作图像

non_unique = cat(3, red, green, blue);

non_unique 是包含所有非黑色像素的图像。要获得唯一像素,您必须置换矩阵以使用unique 的“行”选项。

non_unique = permute(non_unique, [1 3 2]);
output = unique(non_unique, 'rows'); %Get unique rows
output = permute(output, [1 3 2]); %Permute it back to recover color channels

输出图像宽 1 像素,长 94 像素。要获得所需的 640x480 形状,您需要对其进行整形和调整大小。我找不到任何好的因子来获得所需的比率,所以我只使用了最大的素因子 94:2 和 47。

reshaped_output = reshape(output, 2, 47, 3);
reshaped_output = imresize(reshaped_output, [480, 640]);

这是不同步骤的图像比较。

【讨论】:

  • 这不会找到唯一的颜色,这只是删除零并将 3D 转换为 2D。还有output = [red, green, blue] 而不是cat
【解决方案3】:

我不确定这是否是最好的方法,但您可以这样做:

R = double(im(:,:,1))*255*255;
G = double(im(:,:,2))*255;
B = double(im(:,:,3));
RGB = R+G+B; % Now you have 2D matrix

unq = sort(unique(RGB));
unq = unq(2:end); %remove (0,0,0)

B2 = rem(unq(:),255);
G2 = rem((unq-B2)/255,255);
R2 = (unq-G2*255 - B2)/255/255;
% You can make this part more efficient probably. and make sure there is no error

colors_you_want = [R2 G2 B2];

我所做的是,我将 3D 图像转换为 2D 双矩阵,并找到所有独特的元素,即你想要的所有颜色。 unq 的第一个元素是 (0,0,0),所以我删除了那个。然后我转换回二维结构,其中 R 是第一列,G 是第二列,B 是第三列。

【讨论】:

    【解决方案4】:

    我没有使用您在代码中使用的语言,但是如果我在 c/c++ 中执行此操作,我将遍历数据并计算非黑色像素,创建一个该大小的新数组,然后再次循环并将它们一一复制到新数组中。这个可以吗?

    【讨论】:

    • Matlab/Octave 有更好的方法来做到这一点,不需要循环。
    • 就算用c++,为什么还要循环两次,何不干脆用一个可以展开的向量呢?
    • 用不属于标签的语言给出答案通常没有帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-03-08
    • 1970-01-01
    • 2020-10-19
    • 1970-01-01
    • 2018-09-28
    • 2023-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多