how to fill gradient color from light yellow to dark yellow? - matlab

With matlab, I don't know how patch can make gradient color vertically in this picture. Here I just want a simple color gradient. I have used bwboundaries to catch the edge function and fill pure color just like this:
for i=1:4
input=imread(['heartspline2_4_',num2str(i)],'bmp');
figure,imshow(input);
BW=im2bw(input,graythresh(input));
[B,L]=bwboundaries(BW,'noholes');
for k=1:length(B)
boundary=B{k};
plot(boundary(:,2),boundary(:,1),'k','LineWidth',2);
fvc=[1 1 0;1 0 0;0 0 1];
hold on;
axis off;
if (k==1)
patch(boundary(:,2),boundary(:,1),'w');
else
p=patch(boundary(:,2),boundary(:,1),'y');
end
end
saveas(gca,['y_','heartspline2_4_',num2str(i)],'bmp')
close(gcf)
end

Following Shai's code in his answer in your other question:
%% Load image %%
close all; clear all; clc;
img = imread('https://i.stack.imgur.com/yO8Nd.jpg'); %// read image
bw = img(:,:,1) > 128; %// convert to binary mask
lb = bwlabel(bw,4); %// extract distinct regions
%%
%% Create as many colors as needed
% example: 2
cmap=rand(2,3); % make this yellow if needed
% lets convert to HSV, we can tune the intesity of the image better here
cmap=rgb2hsv(cmap);
% for each color, lets crate a set of colors.
for ii=1:size(cmap,1);
colors{ii}= [cmap(ii,1)*ones(1,size(img,2)); cmap(ii,2)*ones(1,size(img,2)); linspace(0.3,1,size(img,2))].';
% Modify the limits of linspace
% to achieve control over the limits
end
% Now we have the colors, lets create an image of vertical colors and mask
% it
cimage=zeros(size(img,1),size(img,2),3); % empthy color image
finalimage=cimage;
for ii=1:size(colors,2)
colors{ii}=hsv2rgb(colors{ii});
cimage=permute(reshape(repmat(colors{ii},[size(img,1),1,1]),[size(img,2),size(img,1),3]),[2,1,3]); % there is probably a simpler way
finalimage=finalimage+cimage.*repmat((lb==ii),[1 1 3]);
end
figure; imshow(finalimage, [], 'border', 'tight');
If you understand the code properly, you will be able to do it for vertical gradient. I accidentally did horizontal, but should be alright. The code is commented, but do not hesitate to ask. The steps are the following
Create random colors, as many as desired. In this case 2
convert to HSV
Create a range of V values, that represent "light"
Repeat that list of colors for every row on the image
mask it with the labels to just add it to the areas of that label

Related

Matlab overlay imagesc on binary image

I am trying to overlay an imagesc image on top of a binary image. I searched for it online, but no luck. Below is my code:
figure;
imshow(BW4);
hold on
imagesc(image2,'AlphaData',0.5); axis equal; axis tight; axis off;
myColorMap = jet(256);
myColorMap(1,:) = 0;
colormap(myColorMap); colorbar;
hold off
The output what I am getting looks like below image on right, instead of the jet colormap lines on top of white color. Can someone help me to fix this issue? I appreciate your time and effort.
Thanks,
Binary image
Jet image
Result what I am getting which I do not want
So we first read your bw data a and create some jet image b which is some nxm matrix of intensities:
a=rgb2gray(imread('fFIG2.png'));
a=a==max(a(:));
a=a>0; % now it is binary
% make jet data with 0 being it's minimal value
b=(imresize(peaks(100),size(a))).*a ;
b=b.*(b>0);
Now we normalize the data in b between 0 and 1 and make an RGB array out of it. The we'll create a mask and assign white to it...
cmap=[0,0,0;jet(255)]; % set the colormap to be always black and jet
% normalize from nxm matrix to nxmx3 rgb values
c=b;
c=round( ((c-min(c(:)) )/(max(c(:))-min(c(:))))*(length(cmap)-1)+1);
im=reshape(cmap(c(:),:),[size(c),3]);
% get the mask for all pixels that are in a but are zero in b
bw2=repmat( (a>0 & b==0),[1 1 3]);
im(bw2)=1; % assign this pixels with rgb=white
imagesc(im)

How can I convert an RGB histogram into a color spectrum?

How can I convert an RGB histogram of an image to create a histogram showing the combined colors along with correct color wavelength range?
Example code:
pkg load image
f=imread('/tmp/marbles.jpg');
f=uint8(f); %need to convert back to uint8 to show picture
%Split into RGB Channels
f_red = f(:,:,1);
f_green = f(:,:,2);
f_blue = f(:,:,3);
%Get histValues for each channel
[y_f_red, x] = imhist(f_red);
[y_f_green, x] = imhist(f_green);
[y_f_blue, x] = imhist(f_blue);
subplot (2,1,1); imshow(f);
subplot (2,1,2); plot(x, y_f_red, 'r', x, y_f_green, 'g', x, y_f_blue, 'b');
Example image along with separate RGB histogram the code produces:
I'm trying to get the histogram to look like the image below but have the colors go from red to blue:
Another image example:
PS: I'm using Octave 4.0 which is very similar to MATLAB.
There's a huge hurdle to converting between standard color representations (like RGB or HSV) and spectral wavelength: many colors can't be represented by a single wavelength of light. Colors such as magenta, pink, brown, or any grayscale color represent mixtures of different wavelengths. Generating an equivalent spectral wavelength is therefore a much more complicated endeavor (you may find some useful ideas and links here and here).
Creating histograms of the colors themselves may be a better way to go (illustrated in one of my other answers), but if you really want to relate color to wavelength in a simple fashion you can try the following...
A first step will be to convert RGB values to HSV values, then create a histogram of the hue channel. I'll adapt part of my answer from here to do that. The next step will be to map hues to wavelengths of light, using some rather gross approximations adapted from this answer:
rgbImage = imread('test_image.png'); % Load image
hsvImage = rgb2hsv(rgbImage); % Convert the image to HSV space
hPlane = 360.*hsvImage(:, :, 1); % Get the hue plane scaled from 0 to 360
binEdges = 0:270; % Edges of histogram bins
N = histc(hPlane(:), binEdges); % Bin the pixel hues from above
wavelength = 620-(170/270).*(0:269); % Approximate wavelength
hBar = bar(wavelength, N(1:end-1), 'histc'); % Plot the histogram
set(hBar, 'CData', 270:-1:1, ... % Change the color of the bars using
'CDataMapping', 'direct', ... % indexed color mapping (360 colors)
'EdgeColor', 'none'); % and remove edge coloring
colormap(hsv(360)); % Change to an HSV color map with 360 points
axis([450 620 0 max(N)]); % Change the axes limits
set(gca, 'Color', 'k'); % Change the axes background color
set(gcf, 'Pos', [50 400 560 200]); % Change the figure size
xlabel('Wavelength (nm)'); % Add an x label
ylabel('Bin counts'); % Add a y label
NOTE: For the above to work properly in Octave, it may be necessary to change the set(hBar, ... line to the following:
set(hBar, 'FaceColor', 'flat', 'EdgeColor', 'none');
set(get(hBar, 'Children'), 'CData', 270:-1:1, 'CDataMapping', 'direct');
And here's the histogram:
There is, however, one issue with this. If we instead use the code exactly as it is in my other answer to plot the histogram of all the hue values, we would get this:
Note that there is a big cluster of magenta, pink, and reddish pixels that gets excluded when we toss out part of the hue range to convert to wavelengths (they don't correspond to a single wavelength in the light spectrum). Incorporating these into the results would require a more complicated conversion from hue to wavelength.
you can not convert RGB to wavelength unless some physical properties of the image and light is met. Anyway you can fake this by inversing:
RGB values of visible spectrum
if you do not know how look at:
Reverse complex 2D lookup table
But the result will not be the same as physical wavelengths histogram ... For that you would need multi-band image acquisition either by rotating prism optics or by set of bandpass filters ...
PS. HSV is far from accurate ...
Btw. the easiest way to do this is create palette from the spectral colors and convert your input image to it (indexed colors) and then just create histogram sorted by wavelength (and or color index)...
Based on gnovices answer but with an image instead of bar (take 0.12s on my system):
rgbImage = imread ("17S9PUK.jpg");
hsvImage = rgb2hsv(rgbImage);
hPlane = 360 .* hsvImage(:, :, 1);
binEdges = 1:360;
N = histc (hPlane(:), binEdges);
cm = permute (hsv (360), [3 1 2]);
img = repmat (cm, max(N), 1);
row_index = max(N) - N';
sp = sparse (row_index(row_index>0), (1:360)(row_index>0), true);
mask = flipud (cumsum (sp));
img(repmat (logical(1 - full(mask)), [1 1 3])) = 0;
image (img)
set (gca, "ydir", "normal");
xlabel('hue');
ylabel('Bin counts');

"Transition-FaceColor" in Matlab

I want to color a rectangle in Matlab with a "transition facecolor" (I do not know the right term) meaning for instance a transition from hell blue to dark blue; you could also interpret it as a shadowing (here you can see an example:
http://il1.picdn.net/shutterstock/videos/620653/thumb/1.jpg?i10c=img.resize(height:160)
I could imagine to achieve it by using a colormap, but I do not know how to apply it on a text annotation like a rectangle.
Is it possible to modify Matlab's standard (monochromatic) colors in such a way? And if so, does someone have a basic framework for it?
You can create the rectangle using a patch which allows having interpolated face colors.
Then, in order to have the face color ranging from dark blue to bright blue you have to define your own "blue" colormap.
The colormap should be defined as a (N x 3) RGB array: in your case you have to set to 0 the first two columns (corresponding to red and green and have the values of the third column (the blue) ranging from (start_blue,end_blue) where start_blue is the darkest blue level you want, end_blue the brightest (both have to be between 0 and 1).
% Define the rectangle: lower left x, lower left y, width, height
x_rect=1;
y_rect=1;
width=10;
height=5;
% Define the patch vertices and faces
verts=[x_rect y_rect;x_rect y_rect+height; ...
x_rect+width y_rect+height;x_rect+width y_rect];
faces=[1 2 3 4];
% Define the color: the higher the brighter
col=[0; 0; 4; 4];
figure
% Create the new blue colormap
b=0.7:.01:1;
cm1=[zeros(length(b),2) b']
% Set the new colormap
colormap(cm1)
% Plot the patch
patch('Faces',faces,'Vertices',verts,'FaceVertexCData',col,'FaceColor','interp');
As an alternative, you can create the rectangle as a surf, then, define your own colormap as above.
% Define the rectangle:
x_rect=1;
y_rect=1;
width=10;
height=5;
% Build a patch
xp=[x_rect:x_rect+width];
yp=[y_rect:y_rect+height];
% Get the number of points
n_xp=length(xp);
n_yp=length(yp);
% Create the grid
[X,Y]=meshgrid(xp,yp);
% Define the z values
Z=ones(size(X));
% Create the color matrix as uniformly increasing
C=repmat(linspace(1,10,n_xp),n_yp,1)
% Create the new blue colormap
start_blue=0.5;
end_blue=1;
b=start_blue:.01:end_blue;
cm1=[zeros(length(b),2) b']
% Set the new colormap
colormap(cm1)
% Plot the rectangle as a "surf"
surf(X,Y,Z,C)
shading interp
xlabel('X Axis')
ylabel('Y Axis')
view([0 90])
xlim([0 13])
ylim([0 9])
daspect([1 1 1])
Hope this helps.
Qapla'

How To Label Colormaps in MATLAB?

I have the following image derived from imagesc(some matrix whose entries correspond to those colors). The Cyan and the Yellow both mean different things. I would like to either:
Add a legend where I can fill in what each color means
Segregate parts of the X-axis to where I can type "cyan" on the x region below the cyan part, and "yellow" on the x region below the yellow part.
Either or would be fine, and which ever one is easier would be appropriate for me.
CYAN YELLOW
Do you want something like this? It's very basic haha.
clc
clear
close all
%// Dummy array
A = repmat([0 0 0 1 1 1],6,1);
imagesc(A)
hold on
%// Dummy data to add legend
scatter(0,0,1,'b','filled')
scatter(0,0,1,'r','filled')
axis off
colorbar
%// Get axis coordinates (x first and then y)
ax = axis;
%// Add text. You can easily adjust the x-offset depending on how many colors you have.
text(ax(2)/4+ax(1),ax(4)+.2,'Blue','Color','b','FontSize',20,'HorizontalAlignment','Center')
text(3*ax(2)/4+.2,ax(4)+.2,'Red','Color','r','FontSize',20,'HorizontalAlignment','Center')
%// Add legend
legend({'Blue';'Red'})
Output:
Here's another option, which happens to be matlab-hg2 friendly:
%% // Initialization
clear variables; close all force; clc;
%% // Generate some data
fakeData = magic(3)-0.5;
fakeData_horz = fakeData(:)'; %//'
fakeNames = cellstr(strcat('color',num2str((1:9)'))); %//'
fakeNameMapping = fakeNames(randperm(numel(fakeData)));
%% // Create figure
hFig = figure('Position',[680,488,758,610],'Resize','off');
%% // Top left example
cLims = [0 numel(fakeData)+1];
hSp = subplot(2,2,1);
imagesc(fakeData); axis image; set(hSp,'XTick',[],'YTick',[]);
colorbar; caxis(cLims);
[XX,YY] = meshgrid(1:size(fakeData,1),1:size(fakeData,2));
text(XX(:),YY(:),fakeNameMapping,'HorizontalAlignment','center');
%% // Bottom example
hSp = subplot(2,2,3:4);
cLims = [0 numel(fakeData)+1]; %Not required here since unchanged
imagesc(fakeData_horz); axis image; set(hSp,'XTick',[],'YTick',[]);
colorbar; caxis(cLims);
drawnow; %// This command will allow the annotations to be positioned properly
for ind1=1:numel(fakeData_horz)
newPos = [hSp.Position(1)+hSp.Position(3)/numel(fakeData_horz) * (ind1-1),...
hSp.Position(2)*1.6,... %1.6 is chosen for the demo
hSp.Position(3)/numel(fakeData_horz),...
0.05]; % 0.05 is chosen for the demo; play around with it
h= annotation('textbox',newPos,'String',fakeNameMapping{ind1},...
'LineStyle','none','HorizontalAlignment','center');
end
%% // Top right example
hSp = subplot(2,2,2);
cLims = [0 numel(fakeData)]; %// cLims is a bit different here!
imagesc(fakeData); axis image; set(hSp,'XTick',[],'YTick',[]);
caxis(hSp,cLims); colormap(hSp,parula(numel(fakeData)));
cb = colorbar; %// This time we need a handle to the colorbar
cb.Ticks = (hSp.CLim(1):hSp.CLim(2))+0.5; %// Set the tick positions
cb.TickLabels = fakeNames; %// Set the tick strings
Which results in:
Note: unless using a more intelligent text positioning computation, the figure's size should not be changed after it was plotted (in the 2nd example), because then the text no longer remains where it should be.
Edit: added another option where only the colorbar is labeled.

Surface plot with highligheted cut

I would like to plot a 3D surface using the Matlab surf function. The whole surface should be in gray scale, then I need to highlight a specific cut of the surface using a different color.
I thought this code would've worked but it doesn't.
Mat = randi(100); % Matrix to be plotted in gray scale
ind_highlight = 10; % Row of the matrix to be highlighted
Mat2 = Mat;
Mat2([1:ind_highlight-1, ind_highlight+1:end] ,:) = NaN;
figure
surf(X,Y,Mat)
colormap gray
hold on
% Highlight the ind_highlight row
surf(X,Y,Mat2)
colormap hsv
Any help would be highly appreciated!
It seems there is no way to use different colormap to obtain the desired effect since the colormap "belongs" to the figure.
I've found a possible solution which does not use colormap.
It is based on the specifying the color matrix in the call to surf, one for the whole matrix, one for the section to be highlighted, then superimposing the second one to the first one.
Unfortunately, I've not been able to set the first ad gray.
I've used the peaks matrix instead of your "randi" in order to have a more smooth surface to work with and inserted the script in a for loop to highlight different section of the matrix
% Mat = randi(100,100,100); % Matrix to be plotted in gray scale
% Alternative definition of the Matrix to be displayed
n_pt=50;
Mat=peaks(n_pt);
% Generate meshgrid
x=1:n_pt;
y=1:n_pt;
[X,Y]=meshgrid(x,y);
ind_highlight_2 = 5; % Number of rows of the matrix to be highlighted
% Generate two set of color matrix
% The first on for the whole surf
% The second one for the section to be highlighted
a=randi(2,n_pt,n_pt);
b=randi(10,n_pt,n_pt);
for i=1:n_pt-ind_highlight_2
ind_highlight_1 = i; % Starting row of the matrix to be highlighted
Mat2 = Mat;
% Modified set of data (in the original just one row was left
% Mat2([1:ind_highlight-1, ind_highlight+1:end] ,:) = NaN
Mat2(ind_highlight_1:ind_highlight_1+ind_highlight_2,:) = NaN;
COL=a;
COL(ind_highlight_1:ind_highlight_1+ind_highlight_2,:)=b(ind_highlight_1:ind_highlight_1+ind_highlight_2,:);
% Plot the surf specifying the color
s_h=surf(X,Y,Mat,COL);
shading interp
% view([0 90])
% f_name=['jpg_name_' num2str(i)]
% print('-djpeg75',f_name)
pause(.1);
end
Hope this helps.