如何从图像中删除所有黑色像素,并仅使用图像中找到的唯一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一样。 是的,我将不再看到原始图像的结构。我将使用图像中的独特颜色创建一部电影。
答案 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]);
这是各个步骤的图像比较。
答案 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 ++中这样做,我会遍历数据并计算非黑色像素,创建一个具有该大小的新数组,并且再次循环并将它们逐个复制到新数组中。可以这样做吗?