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

时间:2017-03-09 19:32:47

标签: arrays image matlab colors octave

如何从图像中删除所有黑色像素,并仅使用图像中找到的唯一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值

我已附上下面的图片和代码片段:

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一样。 是的,我将不再看到原始图像的结构。我将使用图像中的独特颜色创建一部电影。

image

4 个答案:

答案 0 :(得分:3)

正如您在评论中提到的,您希望输出一个独特颜色的2D矩阵,其中每一行都是一个RGB元组,没有黑色像素。您可以做的是将RGB图像重新整形为2D矩阵,其中每列是一个颜色通道,删除行完全为0的所有实例,然后通过unique运行它以删除重复项。为此,您需要使用permute执行每通道转置,然后利用reshape的元素顺序最终创建RGB值的3列矩阵。执行此操作后,使用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');

答案 1 :(得分:2)

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

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

现在你有一个2d掩码,表示黑色像素。下一步是构造掩码以访问每个通道中的所有其他像素

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的'row'选项。

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]);

这是各个步骤的图像比较。

Subplots showing all non-black pixels, unique non-black pixels, and final reshaped image

答案 2 :(得分:0)

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

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),所以我删除了那个。然后我转换回2D结构,其中R是第一列,G是第二列,B是第三列。

答案 3 :(得分:-2)

我没有使用您在代码中添加的语言,但如果我在c / c ++中这样做,我会遍历数据并计算非黑色像素,创建一个具有该大小的新数组,并且再次循环并将它们逐个复制到新数组中。可以这样做吗?