Colouring specific pixels in an image - matlab

Say I have an image. How can I colour some specific pixels in that image using MATLAB?
Thanks.

RGB Pixels
I'd suggest working with an RGB image, so that you can easily represent color and gray pixels. Here's an example of making two red blocks on an image:
img = imread('moon.tif');
imgRGB = repmat(img,[1 1 3]);
% get a mask of the pixels you want and set an RGB vector to those pixels...
colorMask = false(size(imgRGB,1),size(imgRGB,2));
colorMask(251:300,151:200,:) = true; % two discontiguous blocks
colorMask(50:100,50:100,:) = true;
redPix = permute([255 0 0],[1 3 2]);
imgRGB(repmat(colorMask,[1 1 3])) = repmat(redPix, numel(find(colorMask)),1);
AlphaData image property
Another cool way of doing this is with an image's AlphaData property. See this example on a MathWorks blog. This essentially turns color on or off in certain parts of the image by making the gray image covering the color image transparent. To work with a gray image, do like the following:
img = imread('moon.tif');
influenceImg = abs(randn(size(img)));
influenceImg = influenceImg / (2*max(influenceImg(:)));
imshow(img, 'InitialMag', 'fit'); hold on
green = cat(3, zeros(size(img)), ones(size(img)), zeros(size(img)));
h = imshow(green); hold off
set(h, 'AlphaData', influenceImg)
See the second example at the MathWorks link.

Related

Background and foreground color changes

Hello i need to make background color black and foreground color white. As u can see i did this with transfering image to 2 dimension. I want to make this color changes in 3 dimension, so we are nor allowed to transfer it bw. Is there any way to do this ?
logo=imread('logo.png');
subplot(2,2,1);
imshow(logo);
b=rgb2gray(logo);
subplot(2,2,2);
imshow(b);
c=im2bw(b,0.92)
subplot(2,2,3);
imshow(c);
c = 1-c;
subplot(2,2,4);
imshow(c);
Preface:
To set the pixel to white or black each layer of the pixel needs to be set to an intensity value of 0 (black) or 255 (white).
White Pixel → rgb(255,255,255)
Black Pixel → rgb(0,0,0)
The colon can be used to obtain all the indices in the 3rd dimension (grab all the layers). To grab one RGB-pixel in the top-left corner of the image:
RGB_Pixel = Image(1,1,:);
Method 1:
If you wish to retain the three colour channels you can use matrix indexing to change the white background to black. Matrix indexing can also be used to change anywhere that isn't white to white. This method may, unfortunately, break down if you have a coloured component with a 255 intensity component. This doesn't seem to be the case for your image though. You can use method 2 for a more safe approach.
logo = imread('logo.png');
[Image_Height,Image_Width,Depth]= size(logo);
new_logo = zeros(Image_Height,Image_Width,Depth);
new_logo(logo == 255) = 0;
new_logo(logo ~= 255) = 255;
imshow(new_logo);
Method 2:
Checks each pixel (RGB-triplet) using a set of for-loops that scan through the entire image. If the RGB-intensities of the pixel are rgb(255,255,255) then the pixels are set to 0 (black). If the RGB-intensities of the pixel are anything else the pixels are set to 255 (white). The ~ismember() function is used to check if the RGB-pixel has an intensity that is not 255 (not-white).
logo = imread('logo.png');
%Grabbing the size of the image%
[Image_Height,Image_Width,~]= size(logo);
for Row = 1: Image_Height
for Column = 1: Image_Width
%Grabbing RGB pixel%
RGB_Pixel = logo(Row,Column,:);
if(~ismember(255,RGB_Pixel))
%RGB pixel is white change
logo(Row,Column,:) = 255;
else
%RGB pixel is coloured change to black%
logo(Row,Column,:) = 0;
end
end
end
imshow(logo);
Using the repmat() function is also a great solution that the above comment suggested. Which possibly may be the quickest method since you already have the code that generates one layer from the greyscale image.
Ran using MATLAB R2019b

How to plot boundary and centroids on video frames called inside step() function

I am calling some images inside a for loop and then doing some processing on those images. After that, I am using the step function to display those frames and their masks inside a video player. How can I add a boundary to an object inside the mask image? Also, how can I make the boundary thicker and plot the centroids of each blob in the mask in the mask image? Below is the rough sketch of the code.
videoPlayer = vision.VideoPlayer();
maskPlayer = vision.VideoPlayer();
for ii = 1:nfiles
filenameii = [............]
frame= imread(filenameii);
mask = dOB(frame,BackgroundImg);
% some processing on the images
mask= bwareaopen(mask,27);
boundaries = bwboundaries(mask,'noholes');
B=boundaries{1};
Centroid = regionprops(mask,'centroid');
Centroids = cat(1, Centroid.Centroid);
plot(B(:,2),B(:,1),'g','LineWidth',3);
plot(Centroids(:,1), Centroids(:,2), 'r+', 'MarkerSize', 10); step(videoPlayer,frame);
step(maskPlayer, mask);
P.S: I know how to display it on a figure using hold on but I would like this done directly on the image before displaying it in the video player. Any guidance would be appreciated.
Simply paint the pixels on the mask first before displaying it in the video player. What you have does work, but it will plot the boundary inside the figure for the mask player. Therefore, take your boundaries that you detected from bwboundaries, create linear indices from these coordinates and set the values in your image to white. What may be even simpler is to take your mask that you detected and use bwperim to automatically produce a mask that contains the boundaries of the blobs. I also see that you are filling in the holes of the mask, so you can use imfill directly on the output of your post-processing so that it gives you an image instead of coordinates. You would then use this mask to directly index into your image and set the coordinates of the boundaries of the blob to your desired colour. If you desire to make the perimeter thicker, a simple image dilation with imdilate using the appropriately sized square structuring element will help. Simply define the size of the neighbourhood of this structuring element to be the thickness of the perimeter that you desire. Finally, if you want to insert the centroids into the mask and since you have the MATLAB Computer Vision System Toolbox, use the insertMarker function so that you can use a set of points for each centroid and put them directly in the image. However, you must be sure to change the mask from a logical to a data type more suitable for images. uint8 should work. Therefore, cast the image to this type then multiply all nonzero values by 255 to ensure the white colours are maintained in the mask. With insertMarker, you want to insert red pluses with a size of 10 so we need to make sure we call insertMarker to reflect that. Also, because you want to have a colour image you will have to make your mask artificially colour and to do this painting individually for each plane for the colour that you want. Since you want green, this corresponds to the RGB value of (0,255,0).
Therefore, I have modified your code so that it does this. In addition, I've calculated the centroids of the filled mask instead of the original. We wouldn't want to falsely report the centroids of objects with gaps... unless that's what you're aiming for, but let's assume you're not:
videoPlayer = vision.VideoPlayer();
maskPlayer = vision.VideoPlayer();
% New - Specify colour you want
clr = [0 255 0]; % Default is green
% New - Define thickness of the boundaries in pixels.
thickness = 3;
% New - Create structuring element
se = strel('square', thickness);
for ii = 1:nfiles
filenameii = [............]
frame = imread(filenameii);
mask = dOB(frame, BackgroundImg);
% some processing on the images
mask = bwareaopen(mask,27);
%boundaries = bwboundaries(mask,'noholes');
%B=boundaries{1};
% New code - fill in the holes
mask = imfill(mask, 'holes');
Centroid = regionprops(mask,'centroid');
% New code - Create a boundary mask
mask_p = bwperim(mask, 8);
% New code - Make the boundaries thicker
mask_p = imdilate(mask_p, se);
% New code - create a colour image out of the mask
[red, green, blue] = deal(255*uint8(mask));
% Paint the perimeter of the blobs in the desired colour
red(mask_p) = clr(1); green(mask_p) = clr(2); blue(mask_p) = clr(3);
Centroids = cat(1, Centroid.Centroid);
%plot(B(:,2),B(:,1),'g','LineWidth',3);
%plot(Centroids(:,1), Centroids(:,2), 'r+', 'MarkerSize', 10);
% New - Make mask into RGB image for marker painting and to
% show to the user
mask_p = cat(3, red, green, blue);
% New - Insert the centroids directly in the mask image
mask_p = insertMarker(mask_p, Centroids, '+', 'color', 'r', 'size', 10);
step(videoPlayer, frame);
% New - Show new mask in the player
step(maskPlayer, mask_p);
end

How to colour the edges after using sobel filter?

I am using sobel filter for edge detection. How to illustrate the gradient direction with color coding. For example, horizontal edges with blue and vertical edges with yellow?
Thank you.
Since you can specify whether you want horizontal or vertical edge detected (check here), you could perform 2 filtering operations (one horizontal and the other vertical) and save each resulting image, then concatenating them to form a final, 3-channels RGB image.
The RGB color code for yellow is [1 1 0] and that of blue is [0 0 1], so in your case the vertical edge image will occupy the first 2 channels whereas the horizontal edge image will occupy the last channel.
Example:
clear
clc
close all
A = imread('circuit.tif');
[r,c,~] = size(A);
EdgeH = edge(A,'Sobel','Horizontal');
EdgeV = edge(A,'Sobel','Vertical');
%// Arrange the binary images to form a RGB color image.
FinalIm = zeros(r,c,3,'uint8');
FinalIm(:,:,1) = 255*EdgeV;
FinalIm(:,:,2) = 255*EdgeV;
FinalIm(:,:,3) = 255*EdgeH;
figure;
subplot(1,2,1)
imshow(A)
subplot(1,2,2)
imshow(FinalIm)
Output:

Can we rotate an image in MATLAB filled with background color of original image?

By default, MATLAB function imrotate rotate image with black color filled in rotated portion. See this, http://in.mathworks.com/help/examples/images_product/RotationFitgeotransExample_02.png
We can have rotated image with white background also.
Question is, Can we rotate an image (with or without using imrotate) filled with background of original image?
Specific to my problem: Colored image with very small angle of rotation (<=5 deg.)
Here's a naive approach, where we simply apply the same rotation to a mask and take only the parts of the rotated image, that correspond to the transformed mask. Then we just superimpose these pixels on the original image.
I ignore possible blending on the boundary.
A = imread('cameraman.tif');
angle = 10;
T = #(I) imrotate(I,angle,'bilinear','crop');
%// Apply transformation
TA = T(A);
mask = T(ones(size(A)))==1;
A(mask) = TA(mask);
%%// Show image
imshow(A);
You can use padarray() function with 'replicate' and 'both' option to interpolate your image. Then you can use imrotate() function.
In the code below, I've used ceil(size(im)/2) as pad size; but you may want bigger pad size to eliminate the black part. Also I've used s and S( writing imR(S(1)-s(1):S(1)+s(1), S(2)-s(2):S(2)+s(2), :)) to crop the image where you can extract bigger part of image just expanding boundary of index I used below for imR.
Try this:
im = imread('cameraman.tif'); %// You can also read a color image
s = ceil(size(im)/2);
imP = padarray(im, s(1:2), 'replicate', 'both');
imR = imrotate(imP, 45);
S = ceil(size(imR)/2);
imF = imR(S(1)-s(1):S(1)+s(1)-1, S(2)-s(2):S(2)+s(2)-1, :); %// Final form
figure,
subplot(1, 2, 1)
imshow(im);
title('Original Image')
subplot(1, 2, 2)
imshow(imF);
title('Rotated Image')
This gives the output below:
Not so good but better than black thing..

Displaying a png image without the background

http://sweetclipart.com/multisite/sweetclipart/files/sunglasses_black.png
I have read the png image in MATLAB using [X,map,alpha]=imread('...','png').
Now I want to place this png image on another image. But I want the background color of the read png not to be shown. In the link I want the sunglasses alone to be shown without the 'white' background (Background is another image).
The alpha channel is opacity, the opposite of transparency.
MATLAB figures support alpha blending via the AlphaData property:
background = uint8(255*rand(size(alpha)));
imshow(background)
hold on
h = imshow(X);
set(h, 'AlphaData', alpha)
Result:
Given another image Y and your image X with it's alpha data, you can use alpha to generate a blended image. In you case, alpha has only the values 0 and 255, but in general there can be levels of opacity. In this simple case, again with noise background, but in color:
out = uint8(255*rand(size(X))); % Y
hardMask = repmat(alpha==255,1,1,3);
out(hardMask) = X(hardMask);
imwrite(out,'sunglass_alphaC.png')
It's a big image, so I resized the output here:
If your alpha channel actually had more than two levels of transparency, you could blend with the background:
s = double(alpha)/255;
Yout = uint8((bsxfun(#times,1-s,double(Y)) + bsxfun(#times,s,double(X))));
For grayscale, bsxfun can be replaced with just .- (e.g. s.*double(X)).
You can do it like this:
% Image with alpha channel
[glasses, ~, alpha] = imread('http://sweetclipart.com/multisite/sweetclipart/files/sunglasses_black.png');
% OPTIONAL: Let's rescale it (it's very big!)
glasses = imresize(glasses, 0.1);
alpha = imresize(alpha, 0.1);
% An image of a person (let's put the glasses on the person).
person = imread('http://cinemacao.com/wp-content/uploads/2013/12/Scarlett-CAPA-2.jpg');
% Lets make the alpha MxNx3 (so we can combine it with the RGB channels).
alpha = repmat(alpha, [1 1 3]);
% And convert everything from uint8 to double (to avoid precision issues).
glasses = im2double(glasses);
alpha = im2double(alpha);
person = im2double(person);
% Final image
% Let x,y be the top-left coordinates where we'll put the glasses.
x = 440;
y = 450;
% Let's combine the images.
img3 = person;
img3(y:y+size(glasses,1)-1, x:x+size(glasses,2)-1, :) = ...
glasses .* alpha + ...
person(y:y+size(glasses,1)-1, x:x+size(glasses,2)-1, :) .* (1 - alpha);
% An display the result.
imshow(img3);
Result:
I dont know much about Matlab, but seems to be that [X,map,alpha] use "alpha" as the alpha channel; alpha channel means level of transparency. (probably you already know this). Also check if the image itself has the alpha channel set. PNG doesn't recognise "white" as alpha channel by default. In this case, go to your favorite "*shop" software to edit the photo (maybe select with magic tool which will be the background, go to select inverse, copy-paste to a new image previously specifying that the background image will be transparency).