Text position based on another Text - matlab

I need to plot a vertical text (text 2) next to a horizontal text (text 1), if I use the the same position that I used to plot text1 they become superimposed.
I've tried to infer the second position based on the Extent property of text1, but I can't get the units right:
rec = txt.Extent;
pos_x = rec(1) + rec(3);
pos_y = rec(2);
text(pos_x,pos_y,txt2,'HorizontalAlignment','center','FontSize',sz,'Rotation',90,'Units','normalized');
I've tried also with units in pixels but that didn't worked either.
The figure is a time series, I couldn't find any convertion function.
From the documentation it seems to me that the Extent values are normalized but I dont know if anything else is needed to display the second position on those coordinates.

Does this look like what you want to do
plot with rotated text
Here is the code to make the above plot
plot(1:1.2)
h1 = text(1,1, 'Text String 1', 'verticalalignment', 'bottom');
rec = h1.Extent;
pos_x = rec(1) + rec(3);
pos_y = rec(2) + rec(4);
text(pos_x,pos_y,'Text String 2','HorizontalAlignment','left','FontSize',10,'Rotation',90,'verticalalignment', 'bottom');

Related

Pupil detection with hough transform

so I am working for my disertation thesis and I have to detect the pupil from images using Hough Transform. So far I wrote a code that identifies 2 circles on my image, but right now I have to keep the black circle from the pupil.
When I run the code, it identifies me the pupil, but also a random circle on the cheek. My professor said that I should calculate the pixels mean and, considering the fact that the pupil is black, to keep the pixels from only that region. I don't know how to do this.
I will let my code here to have a look and if someone has an ideea on how should I write this and keep only the black pixels would be great. I also attached to this the final image to see what I obtained.
close all
clear all
path='C:\Users\Ioana PMEC\OneDrive\Ioana personal\Disertatie\test.jpg';
%Citire imagine initiala
xx = imread(path);
figure
imshow(xx)
title('Imagine initiala');% Binarizarea imaginii initiale
yy = rgb2gray(xx);
figure
imshow(yy);
title('Imagine binarizata');
e = edge(yy, 'canny');
imshow(e);
radii = 11:1:30;
h = circle_hough(e, radii, 'same', 'normalise');
peaks = circle_houghpeaks(h, radii, 'nhoodxy', 15, 'nhoodr', 21, 'npeaks', 2);
imshow(yy);
hold on;
for peak = peaks
[x, y]=circlepoints(peak(3));
plot(x+peak(1), y+peak(2), 'r-');
end
hold off
testimage
finalimage
I implemented something which should get the task done for you. The example is done with the image you provided.
Step 1: Read the file(s) and convert them to grayscale.
path = %user input;
RGB = imread(path);
lab = rgb2lab(RGB);
grayscale_image = rgb2gray(RGB);
Step 2: Do the Hough transformation with given parameters.
These, and also the sensitivity can be adapted according to your task. Hint: Play around in the Image Segmenter toolbox for fast parameter finding. Next, the inferred circles are converted to integer values, since these are required for indexing.
min_radius = 10;
max_radius = 50;
% Find circles
[centers,radii,~] = imfindcircles(RGB,[min_radius max_radius],'ObjectPolarity','dark','Sensitivity',0.95);
centers = uint16(centers);
radii = uint16(radii);
The annotated image appears as follows:
Step 3: Get the brightness values of the circles.
From the circle center and radius values, we infer their respective brightness. It is sufficient to only check for the x and y pixel values left/right and above/below the center. (-1 is just a safety margin to completely stay within the circles.)
brightness_checker = zeros(2, max(radii), 2);
for i=1:size(centers,1)
current_radii = radii(i)-1;
for j=1:current_radii
% X-center minus radius, step along x-axis
brightness_checker(i, j, 1) = grayscale_image((centers(i,2) - current_radii/2) + j,...
(centers(i,1) - radii(i)/2) + j);
% Y-center minus radius, step along y-axis
brightness_checker(i, j, 2) = grayscale_image((centers(i,2) - current_radii/2) + j,...
(centers(i,1) - current_radii/2) + j);
end
end
Step 4: Check which circle is a pupil.
The determined value of 30 could potentially be enhanced.
median_x = median(brightness_checker(:,:,1),2);
median_y = median(brightness_checker(:,:,2),2);
is_pupil = (median_x<30)&(median_y<30);
pupils_center = centers(is_pupil == true,:);
Step 5: Draw the pupils.
The marker can be changed. Refer to:
https://de.mathworks.com/help/matlab/ref/matlab.graphics.chart.primitive.line-properties.html
figure
imshow(grayscale_image);
hold on
plot(centers(:,1), centers(:,2), 'r+', 'MarkerSize', 20, 'LineWidth', 2);
hold on
plot(pupils_center(:,1), pupils_center(:,2), 'b+', 'MarkerSize', 20, 'LineWidth', 2);
This is the final output:

How to label ('vertically') points in graph

I would like to add labels to some points plotted using the command scatter. For the sake of simplicity, let's say I have only one point:
x = 10;
pointSize = 100;
fontSize = 20;
P = scatter(x, 0, pointSize, [0,0,0], 'filled');
text(x, 0, 'pointLabel',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'bottom',...
'FontSize', fontSize);
The problem with the previous commands is that the text pointLabel overlaps with the point P depending on the values assigned to the properties pointsize and fontSize.
I have read the documentation of the text command, but the examples only show how to put a label horizontally aligned with a specific point in the diagram. If the alignment needs to be horizontal it is easy, but I could not find a general way to compute the y coordinate of the label pointLabel from the values of the other dimensions.
Clearly I can reach a good alignment by testing various combinations of values, but I am looking for a general solution.
Is there anyone who can help me?
This assumes you are using >=R2014b, though it can also be accomplished in older versions using set and get commands.
When a text object is created, its default units are data coordinates, but those can be changed. In your case, I'd go with points.
x = 10;
pointSize = 100;
fontSize = 20;
P = scatter(x, 0, pointSize, [0,0,0], 'filled');
t = text(x, 0, 'pointLabel',...
'HorizontalAlignment', 'center',...
'VerticalAlignment', 'bottom',...
'FontSize', fontSize);
% It's always a good idea to switch back to the default units, so remember them.
originalUnits = t.Units;
t.Units = 'points';
% Shift the text up by the sqrt(pi)/2 times the radius of the point
t.Position(2) = t.Position(2) + sqrt(pointSize)/2;
t.Units = originalUnits;
Check out Text Properties for more info. If you want to get really sophisticated, you can use the read-only property Extent and your known marker size and position to calculate when a label is overlapping one of your points. Since the default unit is in data space, no conversions are necessary.
If you're working with an older version of MATLAB, all of these options and properties are still available, you just have to work a little harder to use them. For instance, you can't direction set the position as above, but you would instead use get to assign it to a temporary variable, change it, and then use set to update. More lines of code, but ultimately the same effect.

How to create a bounding box around objects selected by ismember?

By following this post Using ismember with the output of regionprops I am able to selectively isolate the connected component I want. For example using my code below:
img = rgb2gray(imread('W1\Writer1_01_02.jpg'));
bw_normal2 = im2bw(img, graythresh(img));
bw22 = imcomplement(bw_normal2);
bw3 = bwmorph(bw22, 'dilate');
[label2,n2] = bwlabel(bw3);
stats2 = regionprops(label2, {'Area', 'BoundingBox'});
area2 = [stats2.Area];
idx = find((28 <= area2) & (area2 <= 40));
BW2 = ismember(label2,idx);
figure, imshow(BW2)
I can easily display the output that contains ONLY the connected component whose area is between 28 and 40. As so
But instead can I make a bounding box around this connected component in the original image. I mean if this is the original image:
Can I make a bounding box around my desired component on the original image? I know that this is the code for making a bounding box around all of my connected components
imshow(img);
for j=1:n2
hold on
rectangle('Position',[stats(j).BoundingBox(1),stats(j).BoundingBox(2),stats(j).BoundingBox(3),stats(j).BoundingBox(4)],...
'EdgeColor','r','LineWidth',2 );
end
But how do I only make a bounding box only around the element having area between 28 and 40? Rather than producing a completely different image as shown above.
Keep a if condition in your second half of the code...
imshow(img);
for j=1:n2
hold on
area2 = stats2(j).Area;
if((28 <= area2) & (area2 <= 40))
rectangle('Position',[stats2(j).BoundingBox(1),stats2(j).BoundingBox(2),stats2(j).BoundingBox(3),stats2(j).BoundingBox(4)],...'EdgeColor','r','LineWidth',2 );
end
end

How to center text on a line

I would like to have a string of text that's centered on a line. I've tried this:
figure
axis([0,10,0,10])
d = 2.81;
center = 5;
line([center - d,center + d],[5,5])
th = text(center,4.9,'mmmmmmmmmmmmmmmmmmmmmm');
set(th,'HorizontalAlignment','center')
The text is aligned with the line on the right but not on the left. The above image is a screen shot. I did not consistently have this problem in saved versions of the figure.
Is there a way to center text on a line? I am not concerned about resizing the figure right now, but I would like to use the default font.
It seems that it's not possible to position text arbitrarily precise. I tried getting size of text and drawing line and re-positioning text accordingly. More about text properties here.
str1 = 'mmmmmmmmmmmmmmmmmmmmmm';
center = 5;
text_line_spacing = 0.2;
figure
axis([0,10,0,10])
% Set text initialy
th = text(0,0,str1);
% Get size of text
ext = get(th, 'Extent');
% text_width = ext(3);
% text_height = ext(4);
% Draw appropriate line
left = center - ext(3)/2;
right = center + ext(3)/2;
line([left right], [5 5])
% Reposition original text
set(th, 'Position', [left 5+text_line_spacing]);

RTL msgbox in Matlab

I'm trying to present a msgbox in MATLAB which uses horizontal text alignment 'right'.
Problem is when I'm changing the text alignment, the message text appears out of the box.
h = msgbox('Sample Text');
th = findall(0, 'Tag','MessageBox' );
set(th, 'HorizontalAlignment', 'right');
Does anyone know to present the user with right-to-left message from Matlab?
The message string in the message box is actually created using the text function, i.e., it is positioned by two coordinates (neglecting the z-coordinate). To position it with the alignment right, you'll need to get the position of the message box and use its width argument to define the x position of the message text:
h = msgbox('Sample Text');
th = findall(0, 'Tag','MessageBox' );
boxPosition = get(h,'position');
textPosition = get(th, 'position');
set(th, 'position', [boxPosition(3) textPosition(2) textPosition(3)]);
set(th, 'HorizontalAlignment', 'right');
Since this puts your text exactly to the right border of the box, you'll need to adjust the text slightly to the left:
set(th, 'position', [boxPosition(3).*0.95 textPosition(2) textPosition(3)]);