How to set the linewidth for the subgraphs border - matlab

As shown in the figure, when I set the linewidth for these subgraphs border
set(gca,'linewidth',1.5)
The linewidth of the lines in the red circle is not consistent
The original code is as follows
clc;clear
nlon = [100:140];
nlat = [20:60];
data = ones(length(nlon),length(nlat));
figure
for k =1:4
subplot(2,2,k)
p=pcolor(nlon,nlat,data');hold on
set(p,'linestyle','none');
fun_fill_AA; % **mask**
axis equal
axis([110 135 30 55])
set(gca,'linewidth',1.5)
end
function fun_fill_AA()
data0=[50 10
140 10
140 60
50 60]
data_lon=data0(:,1);
data_lat=data0(:,2);
fil=fill(data_lon,data_lat,[1 1 1]);
hold on
fil=fill(data_lon,data_lat,[1 1 1]);
fil.EdgeColor='none';
end
How can I make the borders of each subgraph have the same linewidth?

It's better after saving the image to higher resolutions.
left:
saves(gcf,'*.png')
right:
print(gcf,'*.png','-dpng','-r600');%*//600 dpi

Related

Determine the proportion of specific colors in an image

Do you have any idea how can I determine the proportion of Yellow (or Yellowish), Brown, and Red colour in a specific image? I tried to use HSV, but I could not find any threshold for H, S, and V for the aforementioned colours.
I attached a sample image.
So, let's do this one step at a time.
First how to know which color is represented by what value? For that, I referred to this stackoverflow question, from where you can get this HSV color map,
If you DuckDuckGo/Google/search for "HSV or HSL color map", you could find many examples.
Now, we can pick a color from the along the horizontal axis. We can use a single value e.g. 120 for dark blue or we can use a range of values e.g. 45 to 80 for all hues of green.
What I wasn't sure about was, how to define the,
proportion of Yellow (or Yellowish), Brown, and Red colour in a specific image
as you ask in your question.
I thought of then two ways to represent the color proportion.
Proportion of pixels containing some portion of that hue.
Proportion of the specific hue relative to all the hues in the image.
Then using the following script, you could get some numbers:
NOTE: (This the Python script, I originally posted. The corresponding Matlab script is further down the post.)
import cv2
import numpy as np
img = cv2.imread("D:\\lenna.jpg")
height_img, width_img, channels_img = img.shape
# Converts images from RGB to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask1 = cv2.inRange(hsv, (150, 0, 0), (150, 255,255)) #150 seems like pinkish
mask2 = cv2.inRange(hsv, (1,0,0), (20, 255, 255)) #1 to 20 seems orangish
total_num_of_pixels = height_img * width_img
all_colors = np.sum(hsv[:,:,:] > 0)
num_of_pixels_with_pinkish_component = np.sum(mask1 > 0)
num_of_pixels_with_orangish_component = np.sum(mask2 > 0)
print("%age of pixels with pinkish component:", "{:.2f}".format(num_of_pixels_with_pinkish_component/total_num_of_pixels * 100))
print("%age of pixels with orangish component:", "{:.2f}".format(num_of_pixels_with_orangish_component/total_num_of_pixels * 100))
print("%age of pinkish component in the entire HSV image:", "{:.2f}".format(num_of_pixels_with_pinkish_component/all_colors * 100))
print("%age of orangish in the entire HSV image:", "{:.2f}".format(num_of_pixels_with_orangish_component/all_colors * 100))
# To visualize the results
res1 = cv2.bitwise_and(img, img, mask=mask1)
res2 = cv2.bitwise_and(img, img, mask=mask2)
cv2.imshow('img', img)
cv2.imshow('mask1', mask1)
cv2.imshow('mask2', mask2)
cv2.imshow('res1', res1)
cv2.imshow('res2', res2)
# To save the output
cv2.imwrite('D:\\mask1.png', mask1)
cv2.imwrite('D:\\mask2.png', mask2)
cv2.imwrite('D:\\res1.png', res1)
cv2.imwrite('D:\\res2.png', res2)
Output:
%age of pixels with pinkish component: 0.41
%age of pixels with orangish component: 35.58
%age of pinkish component in the entire HSV image: 0.15
%age of orangish in the entire HSV image: 13.27
Here is how the output looks then:
MASK1 (150 on the hue axis seems pinkish)
MASK2 (1 ~ 20 on the hue axis seems orange)
RES1
RES2
Here is the equivalent MATLAB script.
close all;
clear all;
clc;
img = imread("/home/junglefox/Downloads/lenna.png");
figure, imshow(img), title('original image (RGB)');
img_size = size(img);
hsv_img = rgb2hsv(img);
hsv_img = im2uint8(hsv_img);
figure, imshow(hsv_img), title('original image in HSV');
% Orange component between 1 and 20 on the HSV map
minval = [1 0 0]; %// Define three element vector here for each colour plane i.e. [0 128 128];
maxval = [20 255 255]; %// Define three element vector here for each colour plane i.e. [0 128 128];
out = true(img_size(1), img_size(2));
for p = 1 : 3
out = out & (hsv_img(:,:,p) >= minval(p) & hsv_img(:,:,p) <= maxval(p));
end
figure, imshow(out), title('image of orange component in image only');
total_num_of_pixels = img_size(1) * img_size(2);
all_colors = sum(hsv_img(:,:,:) > 0);
num_of_pixels_with_orangish_component = sum(sum(out > 0));
percentage_orange = num_of_pixels_with_orangish_component/total_num_of_pixels * 100;
printf("percentage of orange component in all pixels:%d\n", percentage_orange);

UI elements sometimes appear in the wrong place

I have the following MATLAB script:
fig = figure('Position', [150 30 900 600]);
%height = 2100; % Works as expected
height = 2400; % Elements appear in the wrong places
panel = uipanel(fig, 'Units', 'pixels', 'Position', [0 0 900 height]);
xs = linspace(-pi,pi,101);
ys = sin(xs);
width = 300;
height = 300;
yOffset = height*19;
for x = 1:3
for y = 1:2
a = axes(panel, 'Units', 'pixels');
a.Position = [(x-1) * width, (y-1) * height, width, height];
plot(a, xs, ys);
end
end
When run, I expect this to create a figure containing a panel and 6 tiled axes that should fill the entire figure window. Instead, the axes elements appear to be shifted up, and partially off, of the panel and figure. This looks like:
If I change height to a lower number, such as 2100, I get what I expect:
Since positions are relative to the bottom left corner, I don't see why changing the height would make the axes elements move like this. It isn't a smooth transition, if the height isn't too high, the axes are in the right place, but once the height is too high, further increases in height cause the axes to move further and further up the window.
I am using MATLAB R2017a. Am I doing something wrong? What is the cause of this?
Note: I am aware that my panel is much bigger than the figure, this is intentional and desired for my application.

Export/Rasterize alpha shape to bitmap

I build an alpha shape from some points (example given in code) and want to export the shape to a raster graphics format. I need the shape only, not the plot markings (axis, scales ect).
I need only the resulting triangle on white ground as a bitmap.
Scale needs to be 1 unit = 1 pixel.
x = [0 10 20 30 30 30 15];
y = [0 0 0 0 15 30 15];
shape = alphaShape (x',y');
plot (shape, 'FaceColor', 'black');
I have not found anything on how to export shapes or how to rasterize them. Is there any way to do that?
Run the following code after yours.
imgwidth = max(1, ceil(max(x) - min(x)));
imgheight = max(1, ceil(max(y) - min(y)));
ax = gca;
ax.Visible = 'off';
ax.XTickMode = 'manual';
ax.YTickMode = 'manual';
ax.ZTickMode = 'manual';
ax.XLimMode = 'manual';
ax.YLimMode = 'manual';
ax.ZLimMode = 'manual';
ax.Position = ax.OuterPosition;
af = gcf;
figpos = getpixelposition(af);
resolution=get(0, 'ScreenPixelsPerInch');
set(af, 'paperunits','inches', ....
'papersize',[imgwidth imgheight]/resolution, ....
'paperposition',[0 0 [imgwidth imgheight]/resolution]);
print(af,'out.png','-dpng',['-r',num2str(resolution)],'-opengl')
Things done:
Fetch data range and convert to image dimensions.
Turn off axes and ticks.
Minimize/remove padding space surrounding the actual content.
Map 1 unit in data into 1 pixel in output image.
Things not done:
Guarantee aspect ratio. (should work, though)
This screenshot shows non-unity aspect ratio output:
References
Mathworks - Save Figure at Specific Size and Resolution
MATLAB Central - saving a figure at a set resolution
Mathworks - print
Mathworks - Save Figure with Minimal White Space

Drawing circles around points in a plot

I have two matrices
timeline = [0.0008 0.0012 0.0016 0.0020 0.0024 0.0028];
Origdata =
79.8400 69.9390 50.0410 55.5082 34.5200 37.4486 31.4237 27.3532 23.2860 19.3039
79.7600 69.8193 49.8822 55.3115 34.2800 37.1730 31.1044 26.9942 22.8876 18.9061
79.6800 69.6996 49.7233 55.1148 34.0400 36.8975 30.7850 26.6352 22.4891 18.5084
79.6000 69.5799 49.5645 54.9181 33.8000 36.6221 30.4657 26.2762 22.0907 18.1108
79.5200 69.4602 49.4057 54.7215 33.5600 36.3467 30.1464 25.9173 21.6924 17.7133
79.4400 69.3405 49.2469 54.5249 33.3200 36.0714 29.8271 25.5584 21.2941 17.3159
When I plot them, I get a graph like below.
plot(timeline, Origdata, '.');
How can I draw a circle of radius 0.3524 value around each point? This radius should be relative to the y-axis only.
You can do this easily using viscircles (which requires the Image Processing Toolbox) however I don't think that the output is actually what you're expecting.
radius = 0.3524;
dots = plot(timeline, Origdata, '.');
hold on
for k = 1:numel(dots)
plotdata = get(dots(k));
centers = [plotdata.XData(:), plotdata.YData(:)];
% Ensure the the colors match the original plot
color = get(dots(k), 'Color');
viscircles(centers, radius * ones(size(centers(:,1))), 'Color', color);
end
The reason that it looks like this is because your X data is very close together relative to your y data and for circles to appear as circles, I have forced the x and y scaling of the axes to be equal (axis equal)
Edit
If you only want the radius to be relative to the y axis (distance) then we actually need to draw ellipses with an x and y radius. We want to scale the "x-radius" to make it appear as a circle regardless of your true axes aspect ratio, something like this can actually do that.
The trick to the code below is setting the data and plot aspect ratios (pbaspect and daspect) to manual. This ensures that the aspect ratio of the axes doesn't change during zoom, resizing, etc and makes sure that our "circles" remain circular-looking.
dots = plot(timeline, Origdata, '.');
drawnow
% Force the aspect ratio to not change (keep the circles, as circles)
pbaspect('manual')
daspect('manual')
hold on
aspectRatio = daspect;
t = linspace(0, 2*pi, 100);
t(end+1) = NaN;
radius = 4.3524;
% Scale the radii for each axis
yradius = radius;
xradius = radius * aspectRatio(1)/aspectRatio(2);
% Create a circle "template" with a trailing NaN to disconnect consecutive circles
t = linspace(0, 2*pi, 100);
t(end+1) = NaN;
circle = [xradius*cos(t(:)), yradius*sin(t(:))];
for k = 1:numel(dots)
x = get(dots(k), 'XData');
y = get(dots(k), 'YData');
color = get(dots(k), 'Color');
% Center circle template at all points
circles = arrayfun(#(x,y)bsxfun(#plus, [x,y], circle), x, y, 'uni', 0);
circles = cat(1, circles{:});
plot(circles(:,1), circles(:,2), 'Color', color)
end
Just to demonstrate, if we increase the circle radius to 4.3524 we can see the circles better.
And this works with all resizing etc.
To draw circles in MATLAB, you obviously have to use the rectangle function ;)
As mentioned in my comment, the size of 0.3524 does not match your axis, so I chose different sizes to have the circles actually visible, These are rx and ry
timeline = [0.0008 0.0012 0.0016 0.0020 0.0024 0.0028];
Orgidata =[79.8400 69.9390 50.0410 55.5082 34.5200 37.4486 31.4237 27.3532 23.2860 19.3039
79.7600 69.8193 49.8822 55.3115 34.2800 37.1730 31.1044 26.9942 22.8876 18.9061
79.6800 69.6996 49.7233 55.1148 34.0400 36.8975 30.7850 26.6352 22.4891 18.5084
79.6000 69.5799 49.5645 54.9181 33.8000 36.6221 30.4657 26.2762 22.0907 18.1108
79.5200 69.4602 49.4057 54.7215 33.5600 36.3467 30.1464 25.9173 21.6924 17.7133
79.4400 69.3405 49.2469 54.5249 33.3200 36.0714 29.8271 25.5584 21.2941 17.3159];
ry=1;
rx=0.0001;
dots=plot(timeline, Orgidata , '.');
hold on
for ix=1:size(Orgidata ,1)
for jx=1:size(Orgidata ,2)
rectangle('Position',[timeline(ix)-(rx/2),Orgidata(ix,jx)-(ry/2),rx,ry],'Curvature',[1,1],'EdgeColor',get(dots(jx), 'Color'));
end
end

extract colored region

I want to extract each colored region in MATLAB after applying SRM segmentation method on a particular image.
I tried the following, but it seems that it extracts regions with different color (not the same color degree only), and with the largest area.
I = imread('./img/bfly.jpg');
imshow(I)
bw = im2bw(I);
imshow(bw)
L = bwlabel(bw);
imshow(L == 0)
props = regionprops(L);
[~,ind] = max([props.Area]);
imshow(L == ind);
Is there a way to extract each color separately?
This is an example image. I want to extract the brown color alone, the green color alone, and so on ...
Since your image appears to have no smooth variations of color, it should be straightforward to separate the colors into different images with unique to convert the image to label matrix (you could do this with rgb2ind also) followed by accumarray:
[Iu,ia,iu] = unique(reshape(I,[],3),'rows');
counts = accumarray(iu,1);
[counts,sortinds] = sort(counts,'descend');
Now say you want the N largest components:
N = 10;
largestLabels = sortinds(1:N);
Then the image for color ii:
mapi = reshape(iu == largestLabels(ii),size(I,1),size(I,2));
numeli = counts(ii)
The corresponding RGB values and the number of pixels of each color:
>> colorRegionSummary = [uint32(Iu(largestLabels,:)) counts(1:N)]
colorRegionSummary =
89 120 23 8206 % green
73 59 42 4370 % dark brown (wing)
64 128 184 2723 % blue (right shade)
105 136 25 2143 % green (bottom right shade)
64 127 178 1667 % blue (top left shade)
170 151 191 1380 % purple
58 132 201 1372 % blue (left shade)
177 130 45 1242 % orange (bottom wing shade)
184 123 50 1193 % orange (top wing shade)
118 114 56 586 % tan (top right)
Note that these are not connected components, just components with the same color. For a given mapi, you can then apply bwlabel to get the connected components for that color.
You could start with encoding the three color arrays (RGB) in a way so that you can merge them into one, two-dimensional array, e.g.
2Dimage = I(:,:,1) + 1e3*I(:,:,2) + 1e6*I(:,:,3)
that way, you get a unique number for each color: R + 1e3*G + 1e6*B. Note that each channel is encoded with a number in the interval [0, 255].
Now you can go and extract the different color regions from the image using
C = unique(2Dimage)
to obtain the unique colors you need to look for and then
for idx = 1:length(C)
find(C(idx)==2Dimage)
end
to locate the different parts of the image. The color can be readily obtained from the original image I at the corresponding locations/indices.