[英]Reflecting points in an RGB image over a reflection line (MATLAB)
我有一个大小为MxNx3的RGB图像。 让我们想象一下,我们在图像的下半部分有一条反射线。 如何将线上方的所有点反映到线上? 我知道我需要做什么,但我无法在MATLAB上做到正确。 谢谢你的帮助。
例如,在下面的图像中,蓝线是反射线。
码
%%// Read input image
img =imread(IMG_FILEPATH);
%%// Let user select the mask, top of which will basically act
%%// as the reflection line
figure,imshow(img)
[mask,xi,yi] = roipoly(img);
%%// Remove the last element as that is same as the first one
xi(end)=[];
yi(end)=[];
%%// Find the two corner points each on the left and right sides of the mask
pt_matrix = [xi yi]
[val,ind] = sort(xi)
left_two_pts = pt_matrix(ind(1:2),:)
right_two_pts = pt_matrix(ind(end-1:end),:)
four_pts = round([left_two_pts;right_two_pts])
%%// Remove a 5x5 neighborhood around the four corners, so that biggest
%%// blob that is the line could be separated out
BW1 = edge(mask,'canny');
for k = 1:4
BW1(four_pts(k,2)-2:four_pts(k,2)+2,four_pts(k,1)-2:four_pts(k,2)+1) = 0;
end
%%// Get the biggest blob that is the reflection line
[L, num] = bwlabel(BW1);
counts = sum(bsxfun(@eq,L(:),1:num));
[~,ind] = max(counts);
BW1 = (L==ind);
%%// Connect the endpoints of the line to left and right sides of the image
xlimit = [find(sum(BW1,1),1) find(sum(BW1,1),1,'last')];
[row1,col1] = ind2sub(size(BW1),find(BW1));
BW1(row1(1),1:col1(1)-1)=1;
BW1(row1(end),col1(end)+1:end)=1;
%%// Select only one per column for the reflection
[xt0,yt0] = find(BW1);
[yt1,a2,a3] =unique(yt0,'first');
xt1=xt0(a2);
sz1 = size(BW1,1)-xt1;
%%// Perform the reflection
for k = 1:numel(yt1)
img(xt1(k):end,k,:) = img(xt1(k):-1:xt1(k)-sz1(k),k,:);
end
figure,imshow(img)
roipoly
典型面具看起来像 -
产量
注意:用户必须在左侧准确选择两个点来表示蒙版的左侧边框,并且右侧边缘上恰好选择两个点。 此外,线上必须有足够的图像像素才能在线上反射。
我假设线存储在掩码中,如OP所述。 我将假设面具在线上方是黑色,在它下面是白色。 这是解决问题的“奇特”方式。 :)
% 1. Open your image (MxNx3 matrix).
img = im2double(imread('original.png'));
% 2. Open your 'line image' as a logical array (MxNx3 matrix)
line = imread('line.png') > 0;
% 3. Now, we will "align" the upper part of the image based on the line,
% so that the line will be straight at the bottom of the image. We will
% do that by sorting the 'line image', moving the ones of the mask
% above. The code was adapted from:
% http://www.mathworks.com/matlabcentral/newsreader/view_thread/28715
upper = zeros(size(line));
upper(~line) = -1;
upper = sort(upper, 'descend');
upper(upper == -1) = img(~line);
% 4. Let's concatenate both the image with it's mirror below.
imgConcat = [upper; upper(end:-1:1, :, :)];
% 5. Also, The line mask will be concatenated to it's negative, and we'll
% invert the order of the rows.
lineConcat = [line; ~line];
lineConcat = lineConcat(end:-1:1,:,:);
% 6. Now we repeat the "alignment procedure" used on step 4 so that the
% image will be positioned on the upper part. We will also remove the
% lower part, now containing only zeros.
mirror = zeros(size(lineConcat));
mirror(lineConcat) = -1;
mirror = sort(mirror, 'ascend');
mirror(mirror == -1) = imgConcat(lineConcat);
mirror = mirror(1:end/2,:,:);
在这里你看到结果(一步一步);
为了生成该图像,我使用了以下代码:
% Display the results, step by step (final result is in the 'mirror' matrix).
subplot(2,3,1), imshow(img, []); title('Step 1. Original image')
subplot(2,3,2), imshow(double(line), []); title('Step 2. Line image');
subplot(2,3,3), imshow(upper, []); title('Step 3. Image "alignment"');
subplot(2,3,4), imshow(imgConcat, []); title('Step 4. Mirror concatenation');
subplot(2,3,5), imshow(double(lineConcat), []); title('Step 5. Mask concatenation');
subplot(2,3,6), imshow(mirror, []); title('Step 6. Result by a final alignment');
假设已经定义了这条线,那么解决这个问题的简单方法就是扫描每一列,并从该线的位置开始,以相反的顺序从线上方复制尽可能多的元素。
因此,对于每列c
,让line[c]
成为该列中行的行号。 然后
maxR = size(c);
c(line[c]:end) = c(line[c]-1:-1:line[c]-(maxR - line[c] + 1));
最后一部分, line[c]-(maxR - line[c] + 1)
告诉它要复制多少。 它只需要将列底部与线条之间的距离,并将其用作要复制的像素数。
当然,这必须推广到3个频道,但我不想弄乱这个概念。 除此之外,你只需将它放在所有列的循环中, c
。
这也假设线上方有足够的数据来填充线下方的区域。 如果没有,你将不得不决定如何处理这种情况。
我确定有办法对此进行矢量化并取出循环,但我会将其留给专家:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.