image - 通过将一幅图像并排显示并用对角线分隔来合并 2 张图像

标签 image matlab merge image-manipulation image-comparison

我有 2 张图像(“之前”和“之后”)。我想显示最终图像,其中左半部分取自之前图像,右半部分取自之后图像。

图像应由预定义宽度(2 或 3 个像素)的白色对角线分隔,其中对角线由特定角度或 2 个起始和结束坐标指定。对角线应覆盖最终图像的一部分,使其大小与源图像相同。

示例:

Example merged image

我知道可以通过循环所有像素来重新组合并创建最终图像来完成,但是有没有一种有效的方法,或者更好的内置函数可以做到这一点?

最佳答案

不幸的是,我不相信有一个内置的解决方案可以解决您的问题,但我已经开发了一些代码来帮助您做到这一点,但不幸的是,它需要图像处理工具箱才能与代码很好地配合。正如您在评论中提到的,您已经有了这个,所以我们应该没问题。

这背后的逻辑相对简单。我们假设您的前后图片大小相同,并且 channel 数相同。第一部分是声明一个空白图像,我们在中间画一条一定厚度的直线。这背后的复杂之处在于声明一个比图像原始尺寸稍大的图像。原因是因为我要在中间画一条线,然后将这个空白图像旋转一定角度以获得您想要的第一部分。我将使用imrotate以您想要的任何角度旋转图像。第一直觉是声明一个与原始图像大小相同的图像,在中间画一条线并旋转它。但是,如果这样做,最终会导致线条断开,并且不会从图像的顶部到底部进行绘制。这是有道理的,因为以一定角度绘制的线条比垂直绘制的线条覆盖的像素更多。

使用毕达哥拉斯定理,我们知道可以在图像上绘制的最长线是对角线。因此,我们在行和列中声明一个为 sqrt(rows*rows + cols*cols) 的图像,其中 rowscols 是原始图像的行和列。之后,我们将采取天花板以确保我们覆盖了尽可能多的区域,并添加了一些额外的空间以适应线条的宽度。我们在此图像上画一条线,旋转它,然后裁剪图像,使其与输入图像的大小相同。这可以确保以您希望的任何角度绘制的线都是从上到下完全绘制的。

逻辑是最难的部分。完成此操作后,您将声明两个使用 imfill逻辑掩码。将蒙版的左侧填充为一个蒙版,我们将反转蒙版以找到另一个蒙版。您还需要使用我们之前使用 imrotate 创建的线条图像来索引蒙版并将值设置为 false,以便我们忽略图像上的这些像素线。

最后,您获取每个蒙版,将其索引到图像中并复制所需图像的每个部分。最后,您使用线条图像来索引输出并将值设置为白色。

话不多说,代码如下:

% Load some example data
load mandrill;

% im is the image before
% im2 is the image after
% Before image is a colour image
im = im2uint8(ind2rgb(X, map));

% After image is a grayscale image
im2 = rgb2gray(im);
im2 = cat(3, im2, im2, im2);

% Declare line image
rows = size(im, 1); cols = size(im, 2);
width = 5;
m = ceil(sqrt(rows*rows + cols*cols + width*width));
ln = false([m m]);
mhalf = floor(m / 2); % Find halfway point width wise and draw the line
ln(:,mhalf - floor(width/2) : mhalf + floor(width/2)) = true;

% Rotate the line image
ang = 20; % 20 degrees
lnrotate = imrotate(ln, ang, 'crop');

% Crop the image so that it's the same dimensions as the originals
mrowstart = mhalf - floor(rows/2);
mcolstart = mhalf - floor(cols/2);
lnfinal = lnrotate(mrowstart : mrowstart + rows - 1, mcolstart : mcolstart + cols - 1);

% Make the masks
mask1 = imfill(lnfinal, [1 1]);
mask2 = ~mask1;
mask1(lnfinal) = false;
mask2(lnfinal) = false;

% Make sure the masks have as many channels as the original
mask1 = repmat(mask1, [1 1 size(im,3)]);
mask2 = repmat(mask2, [1 1 size(im,3)]);

% Do the same for the line
lnfinal = repmat(lnfinal, [1 1 size(im, 3)]);

% Specify output image
out = zeros(size(im), class(im));
out(mask1) = im(mask1);
out(mask2) = im2(mask2);
out(lnfinal) = 255;

% Show the image
figure;
imshow(out);

我们得到:

enter image description here

如果您希望线朝另一个方向移动,只需将角度 ang 设置为负即可。在上面的示例脚本中,我将角度逆时针旋转 20 度(即正角)。要重现您给出的示例,请指定 -20 度。我现在得到这个图像:

enter image description here

关于image - 通过将一幅图像并排显示并用对角线分隔来合并 2 张图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44310306/

相关文章:

python - 在 Python 中从控制台使用断点进行调试

css - 为什么在ie中,绝对定位的标志是在右边?

java - 使用java通过定时器交替图像

linux - 在 Ubuntu15.10 上的 Matlab2016a 中检测到分段违规

git - 使用 MATLAB 脚本将 git 命令结果存储到变量中

python - 删除重复行但保留某些值 Pandas

python - 如何在 GNU/Linux 中使用 python 自动化 GUI 应用程序的操作?

php - 从以顺序名称存储的目录中检索图像并存储在数组中

php - 需要在一个 JSON 中合并多行

git - 从 master 中删除 merge