how can i replace white pixel (in binary image) with a color pixel of another image?

i have two images , an RGB image(rgbimage) and it's binary image(b), i wanna know how to replace white pixel in (b) with an RGB pixel at same position as the position of RGB image.
i tried this code:
close all;
clear all;
clc;
rgbimage=imread('RGBimage.jpg');
whos rgbimage
b=imread('foreg.jpg');
whos b
[m n]=size(b)
for i=1:n
for j=1:m
if (b(i,j)==0)
b(i,j)=rgbimage(i,j)
end
end
end
imshow(b)

Answers (3)

I do this all the time. This is what I do:
mask is the binary image mask (2D) (converted to logical values). rgbImg is the RGB Image (3D). Assuming the number of rows and columns are same in both these matrices:
output (:,:,3) = rgbImg(:,:,3) .* mask;
output (:,:,2) = rgbImg(:,:,2) .* mask;
output (:,:,1) = rgbImg(:,:,1) .* mask;

1 Comment

Or you can use immultiply instead of the .* operator, provided both inputs have same data-type.

Sign in to comment.

bay rem - what are the dimensions of rgbimage and b? Presumably the former is mxnx3 (since RGB) but is the latter two- or three-dimensional? Note that it will have to be converted into three dimensions so that you can copy over the colour pixel from rgbimage.
bIn3Dims = repmat(b,1,1,3);
The above should create a three dimensional equivalent of your binary image. Now, when you find a white pixel
if (b(i,j)==1)
bIn3Dims(i,j,:)=rgbimage(i,j,:)
end
you will copy over the RGB pixel from rgbimage into your new matrix.
Also, why is 0 considered to be white? Isn't 0 usually considered to be black? )That is why I replaced the 0 in the condition with 1.)

3 Comments

thank you so much Geoff,...the dimension of rgbimage is 480x720*3 and for b 480x720 i modified the code, but an error appeared:
Index exceeds matrix dimensions.
Error in invrgb (line 14)
if (b(i,j)==0);
Look closely at your for loops
[m n]=size(b)
for i=1:n
for j=1:m
if (b(i,j)==0)
m is the number of rows and n is the number of columns of b. Notice how i is used to index the row of b and j is used to index the column of b but the upper bound on i is the number of columns in b (and similarly, the upper bound on j is the number of rows of b). So you just have a mismatch and the code should be
for i=1:m
for j=1:n
As an aside, it is good practice to avoid using i and j as indexing variables since MATLAB uses these to represent the imaginary number.
The best way to avoid this sort of confusion (is i iterating over the rows or columns?) is to use meaningful names for your variables (as you did for rgbimage). The following is self-documenting because the variable names have meaning:
binaryimage = imread('foreg.jpg');
[height, width] = size(binaryimage);
for column = 1 : width
for row = 1 : height
binaryimage(row, column) = ...

Sign in to comment.

You can cast b into a color image then mask
mask = b; % Make a copy of b and save it in mask
b = rgbimage; % b is now the original image.
% Mask the image using bsxfun() function
maskedRgbImage = bsxfun(@times, rgbImage, cast(mask, 'like', rgbImage));
No double for loop is needed.

12 Comments

thank you but i already tried "bsxfun" but only few colors appreared
Did you try my code yet? It works. A full demo is attached.
Explain your comment. As you can see, all the colors that are in the original image are sent to where "b" is white. No colors are missing for me so why should they be for you? Please attach your images so we can work with them and show you what you're doing wrong.
HERE THERE ARE BOTH TWO IMAGES:
and here the code that i used:
rgbimage=imread('beforeAC.jpg');
b=imread('foreg.jpg');
mask = b;
b = rgbimage;
[m n]=size(b);
bIn3Dims = repmat(b,1,1,3);
maskedRgbImage = bsxfun(@times, rgbimage, cast(mask, 'like', rgbimage));
for i=1:m;
if (b(i)==0);
maskedRgbImage(i,:)=rgbimage(i,:);
end
end
imshow(maskedRgbImage);
The full demo is the "test2.m" below my image.
You did not use my code. Nowhere do I have that for loop. In fact I specifically told you NOT to use it: "No double for loop is needed." in my answer.
How did you get the binary image?? If you don't mind can you post the code? Did you use the nested for loops of no??
Sandeep, my full demo code is in the comments above. You have to show the old comments to see it. But anyway, here is the demo again.
workspace;
clear all;
fontSize = 13;
rgbImage = imread('peppers.png');
% Display the original color image.
subplot(2, 2, 1);
imshow(rgbImage);
title('Original Color Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'Outerposition', [0, 0, 1, 1]);
grayImage = rgb2gray(rgbImage);
% Display the image.
subplot(2, 2, 2);
imshow(grayImage);
title('Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'Outerposition', [0, 0, 1, 1]);
b = grayImage > 128;
% Display the image.
subplot(2, 2, 3);
imshow(b);
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
mask = b; % Make a copy of b and save it in mask
b = rgbImage; % b is now the original image.
% Mask the image using bsxfun() function
maskedRgbImage = bsxfun(@times, rgbImage, cast(mask, 'like', rgbImage));
% Display the image.
subplot(2, 2, 4);
imshow(maskedRgbImage);
title('Masked Image', 'FontSize', fontSize, 'Interpreter', 'None');
You can see there is no for loop.
"bay rem" used a loop for some reason but it was totally unnecessary.
Is this gonna work for all RGB image or It depends??
Is what going to work? There is nothing in this image that is special to 'peppers.png' so of course it will work for all RGB images, but what does "work" mean to you? Of course the result depends on what the threshold is. I used 128 but you could use whatever you want or even interactively set it with the Color Thresholder on the Apps tab of the tool ribbon, or for gray scale images use my interactive thresholder app in my File Exchange.
can we use same code to separate the background and foreground too?
Again, not sure what you mean. It would be helpful if you were more exact in your wording.
Case 1: masking with bsxfun(): If the mask was created such that white was foreground and black was background, or vice versa, then yes, bsxfun() can give you each separately.
Case 2: segmenting with Color Thresholder. If you're talking about color thresholding, then using that won't segment into foreground and unless the foreground and background have different ranges of colors, like background is all black or green or blue or whatever, and none of the foreground is. If there is a little bit of one color in the other's region (like a small amount of black in the foreground) then those can be cleaned up with morphological operations like hole filling or size filtering.

Sign in to comment.

Asked:

on 3 Dec 2015

Commented:

on 3 Jul 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!