我有一个名为 main.jpg
(主图像)的图像(白色背景,有 1-5 个黑点)。
我正在尝试在主图像中找到的每个黑点中放置另一个图像(secondary.jpg)。
为了做到这一点:
- 我在主图像中发现了黑色像素
- 将辅助图像调整为我想要的特定尺寸
- 在我在第一步中找到的每个坐标中绘制图像。 (黑色像素应该是辅助图像的中心坐标)
不幸的是,我不知道如何执行第三步。
例如:
主图是:
辅助图像是:
输出:
(这些点位于椅子后面。它们是图像中心点)
这是我的代码:
mainImage=imread('main.jpg')
secondaryImage=imread('secondary.jpg')
secondaryImageResized = resizeImage(secondaryImage)
[m n]=size(mainImage)
for i=1:n
for j=1:m
% if it's black pixel
if (mainImage(i,j)==1)
outputImage = plotImageInCoordinates(secondaryImageResized, i, j)
% save this image
imwrite(outputImage,map,'clown.bmp')
end
end
end
% resize the image to (250,350) width, height
function [ Image ] = resizeImage(img)
image = imresize(img, [250 350]);
end
function [outputImage] = plotImageInCoordinates(image, x, y)
% Do something
end
感谢任何帮助!
最佳答案
这是一种没有卷积的替代方案。您必须考虑的一个复杂问题是,如果要将每个图像放置在每个点的中心,则必须确定左上角的位置并索引到输出图像,以便从左上角绘制所需的对象角到右下角。您可以通过获取每个黑点位置并减去水平宽度的一半和垂直高度的一半来实现此目的。
现在解决您的实际问题。如果循环遍历黑色点集而不是整个图像,效率会更高。您可以使用 find
来完成此操作命令来确定为 0 的行和列位置。执行此操作后,循环遍历每对行和列坐标,执行坐标减法,然后将其放置在输出图像上。
我将在对象可能重叠的地方施加额外的要求。为了适应这一点,我将累积像素,然后找到非零位置的平均值。
您的代码已修改为适应此情况,如下所示。请注意,因为您使用的是 JPEG 压缩,所以您将产生压缩伪影,因此 0 的区域不一定是 0。我将使用强度 128 进行阈值,以确保零区域实际上为零。您还会遇到对象可能超出图像边界的情况。因此,为了适应这种情况,请在水平方向上充分填充图像一半宽度,在垂直方向上填充图像一半高度,然后在放置对象后对其进行裁剪。
mainImage=imread('/image/gbhWJ.png');
secondaryImage=imread('/image/P0meM.png');
secondaryImageResized = imresize(secondaryImage, [250 300]);
% Find half height and width
rows = size(secondaryImageResized, 1);
cols = size(secondaryImageResized, 2);
halfHeight = floor(rows / 2);
halfWidth = floor(cols / 2);
% Create a padded image that contains our main image. Pad with white
% pixels.
rowsMain = size(mainImage, 1);
colsMain = size(mainImage, 2);
outputImage = 255*ones([2*halfHeight + rowsMain, 2*halfWidth + colsMain, size(mainImage, 3)], class(mainImage));
outputImage(halfHeight + 1 : halfHeight + rowsMain, ...
halfWidth + 1 : halfWidth + colsMain, :) = mainImage;
% Find a mask of the black pixels
mask = outputImage(:,:,1) < 128;
% Obtain black pixel locations
[row, col] = find(mask);
% Reset the output image so that they're all zeros now. We use this
% to output our final image. Also cast to ensure accumulation is proper.
outputImage(:) = 0;
outputImage = double(outputImage);
% Keeps track of how many times each pixel was hit by the object
% This is so that we can find the average at each location.
counts = zeros([size(mask), size(mainImage, 3)]);
% For each row and column location in the image
for i = 1 : numel(row)
% Get the row and column locations
r = row(i); c = col(i);
% Offset to get the top left corner
r = r - halfHeight;
c = c - halfWidth;
% Place onto final image
outputImage(r:r+rows-1, c:c+cols-1, :) = outputImage(r:r+rows-1, c:c+cols-1, :) + double(secondaryImageResized);
% Accumulate the counts
counts(r:r+rows-1,c:c+cols-1,:) = counts(r:r+rows-1,c:c+cols-1,:) + 1;
end
% Find average - Any values that were not hit, change to white
outputImage = outputImage ./ counts;
outputImage(counts == 0) = 255;
outputImage = uint8(outputImage);
% Now crop and show
outputImage = outputImage(halfHeight + 1 : halfHeight + rowsMain, ...
halfWidth + 1 : halfWidth + colsMain, :);
close all; imshow(outputImage);
% Write the final output
imwrite(outputImage, 'finalimage.jpg', 'Quality', 100);
我们得到:
编辑
我没有被告知您的图像具有透明度。因此,您需要做的是使用 imread
但确保您在 Alpha channel 中读取。然后我们检查是否存在,如果存在,我们将确保任何不透明的值的背景设置为白色。您可以使用以下代码来做到这一点。确保将其放置在代码的最顶部,替换正在加载的图像:
mainImage=imread('/image/gbhWJ.png');
% Change - to accommodate for transparency
[secondaryImage, ~, alpha] = imread('https://i.imgur.com/qYJSzEZ.png');
if ~isempty(alpha)
m = alpha == 0;
for i = 1 : size(secondaryImage,3)
m2 = secondaryImage(:,:,i);
m2(m) = 255;
secondaryImage(:,:,i) = m2;
end
end
secondaryImageResized = imresize(secondaryImage, [250 300]);
% Rest of your code follows...
% ...
上面的代码已被修改为读取篮球图像。其余代码保持不变,因此我们得到:
关于image - 将图像置于另一图像的黑色像素中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46558382/