将图像放在另一个图像的黑色像素中

时间:2017-10-04 06:31:52

标签: image matlab image-processing

我有一张图像(带有1-5个黑点的白色背景),称为main.jpg(主图像)。

我正在尝试在主图像中找到的每个黑点中放置另一个图像(secondary.jpg)。

为了做到这一点:

  1. 我在主图像中找到了黑色像素
  2. 将次要影像的大小调整为我想要的特定尺寸
  3. 在我在第一步中找到的每个坐标中绘制图像。 (黑色像素应该是次要图像的中心坐标)
  4. 不幸的是,我不知道如何做第三步。

    例如:

    主要形象是:

    enter image description here

    次要图片是:

    enter image description here

    输出:

    enter image description here

    (点在椅子后面。它们是图像中心点)

    这是我的代码:

    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
    

    任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:2)

这是一种没有卷积的替代方案。您必须考虑的一个复杂因素是,如果要将每个图像放在每个点的中心,则必须确定左上角的位置并将其索引到输出图像中,以便从左上角绘制所需的对象角落到右下角。您可以通过获取每个黑点位置并在水平方向上减去一半宽度并在垂直方向上减去一半高度来实现此目的。

现在解决你的实际问题。如果循环遍历黑色的点集,而不是整个图像,则效率会更高。您可以使用find命令确定0的行和列位置。一旦执行此操作,循环遍历每对行和列坐标,减去坐标然后将其放在上面输出图像。

我会在物体重叠的地方施加额外的要求。为了适应这种情况,我将累积像素,然后找到非零位置的平均值。

为了适应这种情况而修改的代码如下。请注意,因为您正在使用JPEG压缩,所以您将有压缩瑕疵,因此0的区域可能不一定是0.我将以128的强度阈值,以确保零区域实际上为零。您还将遇到对象可能超出图像边界的情况。因此,为了适应这种情况,请将图像充分填充两倍,水平宽度的一半,垂直高度的一半,然后在放置物体后将其裁剪掉。

mainImage=imread('https://i.stack.imgur.com/gbhWJ.png');
secondaryImage=imread('https://i.stack.imgur.com/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);

我们得到:

enter image description here

修改

我没有被告知你的图像有透明度。因此,您需要做的是使用imread,但要确保您在alpha通道中读取。然后我们检查是否存在,如果存在,我们将确保没有透明度的任何值的背景设置为白色。您可以使用以下代码执行此操作。确保将其置于代码的最顶层,替换正在加载的图像:

mainImage=imread('https://i.stack.imgur.com/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...
% ...

上面的代码已被修改为在篮球图像中读取。其余的代码保持不变,因此得到:

enter image description here

答案 1 :(得分:1)

您可以使用convolution来达到预期的效果。这将在EXAMPLE中的任何地方放置im的副本。

imz

enter image description here

此外,您可能希望避免将% load secondary image im = double(imread('secondary.jpg'))/255.0; % create some artificial image with black indicators imz = ones(500,500,3); imz(50,50,:) = 0; imz(400,200,:) = 0; imz(200,400,:) = 0; % create output image imout = zeros(size(imz)); imout(:,:,1) = conv2(1-imz(:,:,1),1-im(:,:,1),'same'); imout(:,:,2) = conv2(1-imz(:,:,2),1-im(:,:,2),'same'); imout(:,:,3) = conv2(1-imz(:,:,3),1-im(:,:,3),'same'); imout = 1-imout; % output imshow(imout); 保存为main.jpg,因为它会导致有损压缩,并且可能会导致任何依赖于精确像素值的方法出现问题。我建议使用无损的.jpg,并且对于相同颜色重复多次的合成图像,也可能比.png压缩得更好。