我是Matlab和图像处理的新手。我正在努力分离像这样的图像中的背景和前景
我有数百张这样的图片,找到here。通过反复试验,我发现了一个阈值(在RGB空间中):红色层总是小于150,绿色和蓝色层大于150,背景是。
所以如果我的RGB图像是I
而我的r
,g
和b
图层是
redMatrix = I(:,:,1);
greenMatrix = I(:,:,2);
blueMatrix = I(:,:,3);
通过查找红色,绿色和蓝色的坐标,其值大于或小于150,我可以得到背景的坐标,如
[r1 c1] = find(redMatrix < 150);
[r2 c2] = find(greenMatrix > 150);
[r3 c3] = find(blueMatrix > 150);
现在我在r1,c1,r2,c2,r3 and c3
中获得了数千个像素的坐标。
我的问题:
如何找到常用值,例如红色小于150且绿色和蓝色大于150的像素坐标?
我必须迭代r1
和c1
的每个坐标,并检查它们是否出现在r2 c2
和r3 c3
中以检查它是否是一个共同点。但那将是非常昂贵的。
这可以在没有循环的情况下实现吗?
如果我想出了[commonR commonC]
和commonR
以及commonC
这两个共同点,那么它们都是5000 X 1
的顺序,所以要访问Image的这个背景像素I
,我必须先访问commonR
然后commonC
,然后访问图片I
,如
I(commonR(i,1),commonC(i,1))
也很贵。所以我的问题是,这可以在没有循环的情况下完成。
任何帮助都将不胜感激。
我通过@Science_Fiction回答
获得了解决方案只是详细说明他/她的答案
我用过
mask = I(:,:,1) < 150 & I(:,:,2) > 150 & I(:,:,3) > 150;
答案 0 :(得分:4)
不需要循环。你可以这样做:
I = imread('image.jpg');
redMatrix = I(:,:,1);
greenMatrix = I(:,:,2);
blueMatrix = I(:,:,3);
J(:,:,1) = redMatrix < 150;
J(:,:,2) = greenMatrix > 150;
J(:,:,3) = blueMatrix > 150;
J = 255 * uint8(J);
imshow(J);
灰度图像也足以分隔背景。
K = ((redMatrix < 150) + (greenMatrix > 150) + (blueMatrix > 150))/3;
imshow(K);
我又看了一眼,也使用了你链接的其他图片。 考虑到背景颜色的差异,我认为从图像直方图中获取阈值而不是硬编码会得到更好的结果。
有时,这种算法有点严格,例如与背景一起擦除部分衣服。但我认为超过90%的图像分离得相当好,这比你希望用固定阈值实现的图像更强大。
close all;
path = 'C:\path\to\CUHK_training_cropped_photos\photos';
files = dir(path);
bins = 16;
for f = 3:numel(files)
fprintf('%i/%i\n', f, numel(files));
file = files(f);
if isempty(strfind(file.name, 'jpg'))
continue
end
I = imread([path filesep file.name]);
% Take the histogram of the blue channel
B = I(:,:,3);
h = imhist(B, bins);
h2 = h(bins/2:end);
% Find the most common bin in the *upper half*
% of the histogram
m = bins/2 + find(h2 == max(h2));
% Set the threshold value somewhat below
% the value corresponding to that bin
thr = m/bins - .25;
BW = im2bw(B, thr);
% Pad with ones to ensure background connectivity
BW = padarray(BW, [1 1], 1);
% Find connected regions in BW image
CC = bwconncomp(BW);
L = labelmatrix(CC);
% Crop back again
L = L(2:end-1,2:end-1);
% Set the largest region in the orignal image to white
for c = 1:3
channel = I(:,:,c);
channel(L==1) = 255;
I(:,:,c) = channel;
end
% Show the results with a pause every 16 images
subplot(4,4,mod(f-3,16)+1);
imshow(I);
title(sprintf('Img %i, thr %.3f', f, thr));
if mod(f-3,16)+1 == 16
pause
clf
end
end
pause
close all;
<强>结果:强>
答案 1 :(得分:3)
你的方法看似基本但体面。因为对于这个特定的图像,背景主要由蓝色组成,所以你是粗糙的,并做:
mask = img(:,:,3) > 150;
这将为&gt;设置那些评估为真的像素。 150到0,false到1.你会有一个黑白图像。
imshow(mask);
添加颜色
mask3d(:,:,1) = mask;
mask3d(:,:,2) = mask;
mask3d(:,:,3) = mask;
img(mask3d) = 255;
imshow(img);
应该为您提供有希望的脸部彩色图像,纯白色背景。所有这些都需要一些试验和错误。