Related
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
I'm trying to color code some parameter values on a gray image in MATLAB. I'm wondering how to show gray image, make parameter values colored on the gray appearance image and on some pixels, and finally draw a colorbar aside the image just showing parameter values range.
Unsuccessful Code since now:
I = Igray; % gray image
Icc = zeros(size(I,1),size(I,2),3); % color coded image
Icc(:,:,1) = I;
Icc(:,:,2) = I;
Icc(:,:,3) = I;
Icc('some address in the image',3) = 'some number between 0 and 255';
imshow(Icc,[])
colorbar % colorbar showing colored parts spectrum
Result image that I need:
Try something like this:
I = Igray; % gray image
RGB = [1.0,0.7,0.2]; % color for patch
x = 30:50;
y = 70:90;
% If you gray image is in the range [0,255], make it range [0,1]
I = double(I)/255;
Icc = repmat(I,[1,1,3]);
block = I(y,x);
Icc(y,x,1) = 1 - ((1-block) * (1-RGB(1)));
Icc(y,x,2) = 1 - ((1-block) * (1-RGB(2)));
Icc(y,x,3) = 1 - ((1-block) * (1-RGB(3)));
imshow(Icc)
I'm sure there is a prettier way to encode this, but this way it shows the intent.
You're basically multiplying the grey values with the RGB color you want to make the patch. By inverting the patch and the color first, and inverting the result, the multiplication makes the patch brighter, not darker. That way you get the effect you want where the dark parts show the color also. If you multiply directly without inverting first, black stays black and doesn't show the color.
You'll have to figure out how to coordinate with the color bar after that. There are commands in MATLAB to set the limits of the color bar, you can find those reading the documentation.
The color bar you show uses the PARULA color map. You could do this to find the right RGB value to color your patch:
T; % value to color your patch in, in range [0,1]
cm = parula(256);
RGB = interp1(cm,T*255,'linear')
I want to plot 2D representation of a Gaussian wave function in MATLAB. I want the 2D plot to be in one color (green), which gets transparent away from the center of the Gaussian.
When I use imagesc (like in the next code) I get a Gaussian over a black square (as shown in the figure below).
I do not want the black backgrount, and I want the Gaussian to be in one color, but gets transparent away from the center, so that I won't get the black square, only green circle (over a white background) where the circle gets transparent away from its center.
How can I do that ???
close all;clc
figure
xlim_min=-4;
xlim_max=4;
ylim_min=-4;
ylim_max=4;
ylim([ylim_min ylim_max])
xlim([xlim_min xlim_max])
x=-1:0.001:1;
y=-1:0.001:1;
[X,Y]=meshgrid(x,y);
c1=10;
c1_new=c1*0.3;
x_offset=0;
y_offset=0;
w_function=0.5*0.25*exp(-c1_new*((X+x_offset).^2+...
(Y+y_offset).^2));
imagesc(x,y,w_function);
ylim([ylim_min ylim_max])
xlim([xlim_min xlim_max])
To obtain transparency, use the AlphaData and AlphaDataMapping properties of the image. In the following, I'm explicitly computing the transparency (alpha) as an affine function of the data values, in order to specify minimum and maximum transparency values; and I set AlphaDataMapping to none so those values are used without any modifications.
So, replace your line
imagesc(x,y,w_function);
by
min_alpha = .2; % desired minimum alpha
max_alpha = 1; % desired maximum alpha
alpha = min_alpha + (max_alpha-min_alpha)/max(w_function(:))*w_function; % compute alpha
imagesc(x,y,w_function,'AlphaData',alpha,'AlphaDataMapping','none'); % image with alpha
Note how the blue part is more transparent (smaller alpha) than the yellow part.
To have the color blend smoothly with the outer region, set a mininum alpha of 0 and define the function on a larger grid. You can also change the colormap if desired. Since the transparency already varies, you probably want constant color in the colormap.
close all;clc
figure
xlim_min=-4;
xlim_max=4;
ylim_min=-4;
ylim_max=4;
ylim([ylim_min ylim_max])
xlim([xlim_min xlim_max])
x=-2:0.001:2; % large enough that the function approximately ...
y=-2:0.001:2; % ... reaches 0 within this rectangle
[X,Y]=meshgrid(x,y);
c1=10;
c1_new=c1*0.3;
x_offset=0;
y_offset=0;
w_function=0.5*0.25*exp(-c1_new*((X+x_offset).^2+...
(Y+y_offset).^2));
min_alpha = 0; % desired minimum alpha: set to 0
max_alpha = 1; % desired maximum alpha
alpha = min_alpha + (max_alpha-min_alpha)/max(w_function(:))*w_function; % compute alpha
imagesc(x,y,w_function,'AlphaData',alpha,'AlphaDataMapping','none'); % image with alpha
cm = [0 .7 0]; % define colormap: single color, dark green
colormap(cm) % apply colormap
ylim([ylim_min ylim_max])
xlim([xlim_min xlim_max])
I'm working in project that basically I have to detect the threes on image and delete the other information. I used HSV as segmentation and the function regionprops to detect each element. It works fine, but in same cases that has house roofs, they aren't deleted because the value of Hue is similar to the threes. So far, this is the result:
To remove the roofs, I thought that maybe is possible detecting the color green in each region detected. If the region dont have 70% of green (for example) that region is deleted. How can I do that? How Can I detect only the green color of the image?
Solution Explanation
Evaluating the level of green in a patch is an interesting idea. I suggest the following approach:
convert your patches from RGB to HSV color system. In the HSV color system it is easier to evaluate the hue (or - the color) of each pixel, by examining the first channel.
Find the range for green color in the hue system. In our case it is about [65/360,170/360], as can be seen here:
for each patch, calculate how many pixels have the hue value which is in the green range, and divide by the size of the connected component.
Code Expamle
The following function evaluate the "level of greenness" in a patch:
function [ res ] = evaluateLevelOfGreen( rgbPatch )
%EVALUATELEVELOFGREEN Summary of this function goes here
% Detailed explanation goes here
%determines the green threshold in the hue channel
GREEN_RANGE = [65,170]/360;
INTENSITY_T = 0.1;
%converts to HSV color space
hsv = rgb2hsv(rgbPatch);
%generate a region of intereset (only areas which aren't black)
relevanceMask = rgb2gray(rgbPatch)>0;
%finds pixels within the specified range in the H and V channels
greenAreasMask = hsv(:,:,1)>GREEN_RANGE(1) & hsv(:,:,1) < GREEN_RANGE(2) & hsv(:,:,3) > INTENSITY_T;
%returns the mean in thie relevance mask
res = sum(greenAreasMask(:)) / sum(relevanceMask(:));
end
Results
When using on green patches:
greenPatch1 = imread('g1.PNG');
evaluateLevelOfGreen(greenPatch1)
greenPatch2 = imread('g2.PNG');
evaluateLevelOfGreen(greenPatch2)
greenPatch3 = imread('g3.PNG');
evaluateLevelOfGreen(greenPatch3)
Results:
ans = 0.8230
ans = 0.8340
ans = 0.6030
when using on non green patches:
nonGreenPatch1 = imread('ng1.PNG');
evaluateLevelOfGreen(nonGreenPatch1)
result:
ans = 0.0197
I am doing a research for my higher studies in automation. I have done the automation part of the microscope but I need help in MATLAB. An example of what I would like to segment is shown here:
I need to extract the dark purple pixels from this image and only display that in a figure. It is almost like colour based segmentation but I just want to only take the dark purple pixel from the whole image.
What would I do in this case?
Here's something to get you started. Let's go with the theme of colour segmentation where you only want to extract pixels that are of a deep purple. I would like to point you to the HSV colour space before we get started. The HSV colour space is ideal for representing colours in a way that is most intuitive to humans. We tend to describe colours by their dominant colour, followed by attributes such as how washed out or how pure the colour is, and how bright or dark the colour is. The dominant colour is represented by the Hue, the appearance of how washed out or how pure the colour is is represented by the Saturation and the intensity of the colour is represented by the Value, and hence Hue-Saturation-Value, or the HSV colour space.
We can transform a RGB image so that it becomes HSV by rgb2hsv. This will return a 3D matrix that has the hue, saturation and value as 2D slices in a 3D matrix, much like a RGB image where each slices represents the red, green and blue channels. Let's see what each component looks like once we transform the image into HSV:
im = imread('https://www.cdc.gov/dpdx/images/malaria/ovale/Po_gametocyte_thickB.jpg');
hsv = rgb2hsv(im2double(im));
figure;
for idx = 1 : 3
subplot(1,3,idx);
imshow(hsv(:,:,idx));
end
The first line of code reads in an image from a URL. I'm going to use the one that Hoki referred you to, as it's the most simplest one to deal with. For self-containment, this is what the original image looks like:
Once we do this, we convert the image into the HSV colour space. It is important that you convert the image to double precision and you normalize each component to [0,1], and that is performed by im2double. Next, we spawn a new figure, and place each component in a single row over three columns. The first column represents the hue, next column the saturation and finally the last column being the value. This is the figure that we see:
With the first figure, it looks like the dominant colour is purple, whether it's a light shade or a dark shade of the colour, so the hue won't help us here. If you look at a HSV colour wheel:
(source: hobbitsandhobos.com)
Normalize the wheel so that it falls between [0,1] instead of 0 to 360 degrees. The hue is actually represented as degrees due to the nature of the colour space, but MATLAB normalizes this to [0,1]. You can see that purple falls within a hue of [0.6,0.8], which corresponds to the first figure I showed you that displays the hue for our image. If you examine the pixels around the image, they fluctuate between this range. Therefore, the hue won't help us much here.
What will certainly help us are the saturation and value components. If you take a look, the deep purple pixels have a higher saturation than the rest of the background, which makes sense because the deep purple has a much more pure version of purple than the rest of the background. For the value, you can see that the brightness of the dark purple is darker than the background.
We can use these two points as an exploit to segment out the purple colour in the image. The easiest thing to do would be to threshold the saturation and value planes so that any values that are within a certain range you keep while those that are outside you throw away. Therefore, you can do something like this:
sThresh = hsv(:,:,2) > 0.6 & hsv(:,:,2) < 0.9;
vThresh = hsv(:,:,3) > 0.4 & hsv(:,:,3) < 0.65;
I used impixelinfo and I hovered my mouse over the saturation and value components to examine what the values were for the deep purple regions. It looks like those pixels that are deep purple have a saturation value between 0.6 and 0.9, while the value component has values between 0.4 and 0.65. The above code will create two binary masks where true means that the pixel satisfies our criteria while false means it doesn't. Because I want to combine both things together and not leave any stone unturned, let's logical OR the masks together for the final result:
figure;
result = sThresh | vThresh;
imshow(result);
We will also show the result too. This is what we get:
As you can see, this does a pretty good job, but we have remnants of the red arrow that we don't want in the final result. To do a bit of cleanup, we can use morphology - specifically an opening filter of a small window so that we don't affect the pixels that we want as much. We can use imopen to perform our opening operation for us. A morphological opening removes isolated pixels that appear around your image. You use what is called a structuring element that is used to look at local neighbourhoods of your image. For the basics, any pixel regions that are as small as the shape that is contained within the structuring element get removed. Because we want to preserve the shape of the other objects, we can try using a 5 x 5 disk structuring element to clean these pixels up:
figure;
se = strel('disk', 2, 0);
final = imopen(result, se);
imshow(final);
This is what we get:
Not bad! There are some holes that we need to patch up, so let's fill in those holes with imfill:
figure;
final_noholes = imfill(final, 'holes');
imshow(final_noholes);
This is what we get:
OK! So we have our mask. The last thing we need to do is present the image so that you only show the deep purple colours from the original image, and nothing else. That can easily be achieved with bsxfun:
figure;
out = bsxfun(#times, im, uint8(final_noholes));
imshow(out);
The above operation takes your mask, and multiplies every pixel in your image by this mask. One small thing I'd like to point out is that the mask we found in the previous step needs to be cast to uint8, because bsxfun requires that the multiplication (or whatever operation you perform) need to be the same type. We replicate this mask in 3D so that you mask out the unwanted RGB pixels and only keep the ones you are looking for.
This is what we finally get:
As you can see, it isn't perfect, but it's certainly enough to get you started. Those thresholds are what are important, but with some very simple thresholding, I extracted most of the purple pixels out.
To make it easier for you, here's the code that I wrote above that can easily be copied and pasted into MATLAB for you to run:
clear all; close all; clc;
im = imread('https://www.cdc.gov/dpdx/images/malaria/ovale/Po_gametocyte_thickB.jpg');
hsv = rgb2hsv(im2double(im));
figure;
for idx = 1 : 3
subplot(1,3,idx);
imshow(hsv(:,:,idx));
end
sThresh = hsv(:,:,2) > 0.6 & hsv(:,:,2) < 0.9;
vThresh = hsv(:,:,3) > 0.4 & hsv(:,:,3) < 0.65;
figure;
result = sThresh | vThresh;
imshow(result);
figure;
se = strel('disk', 2, 0);
final = imopen(result, se);
imshow(final);
figure;
final_noholes = imfill(final, 'holes');
imshow(final_noholes);
figure;
out = bsxfun(#times, im, uint8(final_noholes));
imshow(out);
Good luck!
Try this:
function main
clc,clear
A = imread('https://www.cdc.gov/dpdx/images/malaria/ovale/Po_gametocyte_thickB.jpg');
subplot(1,2,1)
imshow(A)
RGB = [230 210 200]; % color you want
e = 40; % color shift
B = pix_in(A,RGB,e);
B = B + 255.*uint8(~B); % choosing white background
subplot(1,2,2)
imshow(B)
end
function B = pix_in(A,RGB,e)
% select specific pixels in image
% A - color image (3D matrix uint8)
% RGB - [R G B] - color to select
% e - color shift/deviation
A = double(A); % for same class operations (RGB - double)
[m, n, ~] = size(A);
RGB = reshape(RGB,1,1,3);
RGB = repmat(RGB,m,n,1); % creating 3D matrix
b = abs(A-RGB) < e; % logical 3D
b = sum(b,3) == 3; % if [R,G,B] of a pixel in range
B = A.*repmat(b,1,1,3); % selecting pixels those in range
B = uint8(B);
end