Prevent insertText from placing text on previously inserted text? - matlab

I have a picture, for which I have the x and y coordinates for multiple objects. Each object has a name. I wish to use insertText to place the name in the middle of the object. Considering the large amount of objects per image, sometimes the text overlaps.
Currently, i use this which writes the text exactly to the middle.
I = imread(some_image.jpg); % load image
for i = 1:length(object) % for each object
m = mean(object(i,1:2))); % get the middle
I = insertText(I,m,[name]); % and write label.
end
What I want is a new label to be moved slightly, so that the newest label does not overlap with an old label.

Related

remove some top, down rows and right, and left some columns of jpg image border using matlab

I have RGB museum JPG Images. most of them have image footnotes on one or more sides, and I'd like to remove them. I do that manually using paint software. now I applied the following matlab code to remove the image footnotes automatically. I get a good result for some images but for others it not remove any border. Please, can any one help me by update this code to apply it for all images?
'rgbIm = im2double(imread('A3.JPG'));
hsv=rgb2hsv(rgbIm);
m = hsv(:,:,2);
foreground = m > 0.06; % value of background
foreground = bwareaopen(foreground, 1000); % or whatever.
labeledImage = bwlabel(foreground);
measurements = regionprops(labeledImage, 'BoundingBox');
ww = measurements.BoundingBox;
croppedImage = imcrop(rgbImage, ww);'
In order to remove the boundaries you could use "imclearborder", where it checks for labelled components at boundaries and clears them. Caution! if the ROI touches the boundary, it may remove. To avoid such instance you can use "imerode" with desired "strel" -( a line or disc) before clearing the borders. The accuracy or generalizing the method to work for all images depends entirely on "threshold" which separates the foreground and background.
More generic method could be - try to extract the properties of footnotes. For instance, If they are just some texts, you can easily remove them by using a edge detection and morphology opening with line structuring element along the cols. (basic property for text detection)
Hope it helps.
I could give you a clear idea or method if you upload the image.

matlab: having a good control of MyBox, box with text

my problem is I want to have a box for additional bigger comments to the graph.
How can I create this box, so that it will be always on the right bottom side outside of my graph, and it will be automatically adjusting its size to the amount of text inside? Also, if I will have longer text, I need it to be split into more lines, not just one line extremely long.
I use it like that, however I have a poor control over what is happening, this just creates a certain size in a certain place, text is cut.. please help :)
x = rand(110)*100;
y = x;
plot(x,y)
MyBox = uicontrol('style','text')
set(MyBox,'String','optional longer information to be put into diagram')
set(MyBox,'Position',[10,0,40,10])
I am afraid you can not do that automatically - Text boxes do not use callbacks. From the documentation:
Users cannot change static text interactively. Static text controls do not activate callback routines when clicked.
What you can do is call textwrap function, which will automatically wrap the text you pass to it and return new Text box position:
MyBox = uicontrol('style','text');
% set initial position - first three values are kept constant after wrap, the hight can be changed
set(MyBox,'Position',[10,10,30,10])
% adjust the height of your Text box and wrap the text
[outstring,newpos] = textwrap(MyBox,{'optional longer information to be put into diagram'});
% set new position and text
set(MyBox,'Position',newpos, 'String', outstring)
You will have to call textwrap and set(...) yourself whenever you change the string in the text box.

Determine/Save the position of text in matlab

I plotted few points using scatter and then label them using text. The position of these labels are same as the position of the points + some offset. Some of these text label overlap with each other and hence I moved them interactively (using mouse). I can check the new position of each of these text individually using property editor. However this is very time-consuming. Is there a better way to get the coordinates of all these text-label?
You can use findobj to get handles to text objects that are children of the current axes (or another handle... your choice):
text_handles = findobj('parent',gca,'type','text');
Then you can get the positions of these text objects:
positions = get(text_handles,'position');
You may need to do a bit more work to associate each text object with its data point - I suggest taking advantage of the property system, perhaps via the UserData field, for this, though there are many options.
If you want to do it easily later do this in your plots, for example:
h=text(2.9,7.5,'MyText');
This will put "MyText" at position 2.9, and 7.5.
Then to change the position use:
set(h,'Position',[2.5 7]);
This will change the position to 2.5 and 7.
Later if you need to see tthe position of text again use:
get(h);
Hope this helps.

Using handles returned with findobj [duplicate]

I already have the functions required to drag and drop a single box in a figure in MATLAB. The code I wrote fills the figure with several boxes. With another loop I filled the figure with more boxes (which hold different information in string form).
These two sets of boxes are related by the numbers I placed in their UserData (corresponding numbers; for each box, there's another with the same UserData content). By finding boxes containing the same UserData (and thus relating them) I want to be able to relocate a member of the first set of boxes to the same position relative to the corresponding member of the second set of boxes, by means of right clicking on the box I just dragged (uicontextmenu).
function recallfcn(hObject,eventdata)
for ydx=1:2
diag_detail=get(gco,'UserData'); % This line should be in the drag fcn
diag_pos=get(gco,'Position'); % So should this one (for current objects)
xvar=diag_pos(1,1);
yvar=diag_pos(1,2);
detail=[diag_detail ydx];
set(findobj('UserData',detail),'Position',[xvar+(ydx-1.5) yvar+0.5 0.8 0.8]);
end
end
% ydx is only there to add another level of detail as I'm actually looking to move
% two boxes of the 'first kind', each of which have 2 numbers in user data, the first
% number being the same, and the second number distinguishing the first box from the
% second. The premise is the same.
I usually use findall instead of findobj, in case the handles of the objects are not visible from the outside. Other than that I don't see why your code wouldn't work.
Here's an example:
%# make a figure with two buttons, same userData
fh=figure,
uicontrol('userdata',[2 3],'parent',fh)
uicontrol('userData',[2 3],'units','normalized','position',[0.5 0.5,0.1 0.1],'parent',fh)
%# change color to red
set(findall(fh,'userData',[2 3]),'backgroundcolor','r')
%# move to the same position
set(findall(fh,'userData',[2 3]),'position',[0.3,0.3,0.1,0.1])
As Jonas alludes to, the 'HandleVisibility' property of an object will determine if the object shows up in its parent's list of children, and thus if it will be returned by functions like FINDOBJ. The standard fix is to use the function FINDALL instead.
However, the 'HandleVisibility' property also comes into play in determining whether or not an object can become the current object (i.e. returnable by the function GCO). If it is set to 'off', then that object can't become the current object. Additionally, if the 'HandleVisibility' property of the parent figure of an object is set to 'off' then none of its children (including said object) can become the current object.
If 'HandleVisibility' is set to 'on' or 'callback' for all your objects and figures, then I think everything should work fine.
you should inverse the ordre of x and y vector, and you can use just one loop, the changment in your code is :
x2=x(end:-1:1); % invers the ordre
y2=y(end:-1:1);
for i=1:length(x)
set(hLine,'xdata',x(i),'ydata',y(i)); % move the point using set
% to change the cooridinates.
set(hLine2,'xdata',x2(i),'ydata',y2(i));
M(i)=getframe(gcf);
end

Moving multiple boxes in figure?

I already have the functions required to drag and drop a single box in a figure in MATLAB. The code I wrote fills the figure with several boxes. With another loop I filled the figure with more boxes (which hold different information in string form).
These two sets of boxes are related by the numbers I placed in their UserData (corresponding numbers; for each box, there's another with the same UserData content). By finding boxes containing the same UserData (and thus relating them) I want to be able to relocate a member of the first set of boxes to the same position relative to the corresponding member of the second set of boxes, by means of right clicking on the box I just dragged (uicontextmenu).
function recallfcn(hObject,eventdata)
for ydx=1:2
diag_detail=get(gco,'UserData'); % This line should be in the drag fcn
diag_pos=get(gco,'Position'); % So should this one (for current objects)
xvar=diag_pos(1,1);
yvar=diag_pos(1,2);
detail=[diag_detail ydx];
set(findobj('UserData',detail),'Position',[xvar+(ydx-1.5) yvar+0.5 0.8 0.8]);
end
end
% ydx is only there to add another level of detail as I'm actually looking to move
% two boxes of the 'first kind', each of which have 2 numbers in user data, the first
% number being the same, and the second number distinguishing the first box from the
% second. The premise is the same.
I usually use findall instead of findobj, in case the handles of the objects are not visible from the outside. Other than that I don't see why your code wouldn't work.
Here's an example:
%# make a figure with two buttons, same userData
fh=figure,
uicontrol('userdata',[2 3],'parent',fh)
uicontrol('userData',[2 3],'units','normalized','position',[0.5 0.5,0.1 0.1],'parent',fh)
%# change color to red
set(findall(fh,'userData',[2 3]),'backgroundcolor','r')
%# move to the same position
set(findall(fh,'userData',[2 3]),'position',[0.3,0.3,0.1,0.1])
As Jonas alludes to, the 'HandleVisibility' property of an object will determine if the object shows up in its parent's list of children, and thus if it will be returned by functions like FINDOBJ. The standard fix is to use the function FINDALL instead.
However, the 'HandleVisibility' property also comes into play in determining whether or not an object can become the current object (i.e. returnable by the function GCO). If it is set to 'off', then that object can't become the current object. Additionally, if the 'HandleVisibility' property of the parent figure of an object is set to 'off' then none of its children (including said object) can become the current object.
If 'HandleVisibility' is set to 'on' or 'callback' for all your objects and figures, then I think everything should work fine.
you should inverse the ordre of x and y vector, and you can use just one loop, the changment in your code is :
x2=x(end:-1:1); % invers the ordre
y2=y(end:-1:1);
for i=1:length(x)
set(hLine,'xdata',x(i),'ydata',y(i)); % move the point using set
% to change the cooridinates.
set(hLine2,'xdata',x2(i),'ydata',y2(i));
M(i)=getframe(gcf);
end