Scale text to fit in a box - matlab

I'm working on a matlab GUI and I am trying to make the text font size resize to boxes. Currently I have a few solutions, but they aren't optimal. The fastest one is scaling the text by a goal/Extent factor:
goal = [0 0 .9 .9].*b.Position
fs = b.FontSize*min(goal./b.Extent)
b.FontSize = fs;
b is the uicontrol element. This works, but if the text is too long and needs to wrap it won't, and it will rather shrink the height until it fits on one line in the box.
I also have a while loop approach that * or /s by .99 until extent and goal are close enough.
What I've been looking for is an approach that will wrap the text so that I display the whole string but also take advantage of the whole space. I also had a recursive backtracking attempt that would try to find the best ratio the words would have to the ratio of the sides of the box, but that takes O(2^n) which is good to avoid.
Online I found the textwrap function, but I think that depends on font size, so it doesn't help me. Any ideas on how to do this?

maybe you can load your text as an image, instead of using labels use an axis and load the image o your desired text. Next time you wanted to resize your figure you won't be worry about it.

Related

Detecting text in image using MSER

I'm trying to follow this tutorial http://www.mathworks.com/help/vision/examples/automatically-detect-and-recognize-text-in-natural-images.html to detect text in image using Matlab.
As a first step, the tutorial uses detectMSERFeatures to detect textual regions in the image. However, when I use this step on my image, the textual regions aren't detected.
Here is the snippet I'm using:
colorImage = imread('demo.png');
I = rgb2gray(colorImage);
% Detect MSER regions.
[mserRegions] = detectMSERFeatures(I, ...
'RegionAreaRange',[200 8000],'ThresholdDelta',4);
figure
imshow(I)
hold on
plot(mserRegions, 'showPixelList', true,'showEllipses',false)
title('MSER regions')
hold off
And here is the original image
and here is the image after the first step
[![enter image description here][2]][2]
Update
I've played around with parameters but none seem to detect textual region perfectly. Is there a better way to accomplish this than tweaking numbers? Tweaking the parameters won't work for wide array of images I might have.
Some parameters I've tried and their results:
[mserRegions] = detectMSERFeatures(I, ...
'RegionAreaRange',[30 100],'ThresholdDelta',12);
[mserRegions] = detectMSERFeatures(I, ...
'RegionAreaRange',[30 600],'ThresholdDelta',12);
Disclaimer: completely untested.
Try reducing MaxAreaVariation, since your text & background have very little variation (reduce false positives). You should be able to crank this down pretty far since it looks like the text was digitally generated (wouldn't work as well if it was a picture of text).
Try reducing the minimum value for RegionAreaRange, since small characters may be smaller than 200 pixels (increase true positives). At 200, you're probably filtering out most of your text.
Try increasing ThresholdDelta, since you know there is stark contrast between the text and background (reduce false positives). This won't be quite as effective as MaxAreaVariation for filtering, but should help a bit.

Change legend line style

I am playing with the visual effect of plots, and a question came up while changing the style of a legend.
To be able to save the figure with legends big enough that can be seen usually one needs to change the FontSize property to e.g. 24. When you do that, the size of the font changes, however, the small line next to it has the same size than when it was small. The proportion between line/text seem quite appropriate to me with a FontSize of around 10, while I believe that with big font sizes bigger "eat" visually the line, which is the important part.
Example with fontsize 30 and 10 (please ignore how much I suck in mspaint and the low resolution of the zoomed legend). The proportion between line/text is nicer in the small one.
I was wondering if there is a way to modify that line. I have been checking the properties but I haven't found any relevant one.
NOTE: The LineWidth property does not change the width of the colour lines, but the width of the bounding box.
You could play with the outputs arguments of legend, especially the icons variable (check here).
According to the docs, they correspond to
Objects used to create the legend icons and descriptions, returned as
text, patch, and line object.
Therefore you might use something like this to modify the LineWidth property of any of your plot, or both of course:
clear
clc
close all
x = 1:10;
plot(x,rand(1,10));
hold on;
plot(x,x,'k');
[h,icons,plots,str] = legend('First plot','Second plot','Location','NorthWest');
set(h,'FontSize',30);
set(icons(:),'LineWidth',2); %// Or whatever
Which outputs:
Note that I used R2014a so it might be a bit different for R2014b.

How to determine a projected (if 3D) aspect ratio (if set) of a figure in Matlab to specify a proper paper size?

I saw many Q&A here about squeezing space out of Matlab figures. However I want to squeeze space resulted from a possibly fixed aspect, i.e. to choose proper paper size for figure printing when aspect is fixed.
Quite often I work with DEM/map/image thus I use axis image. Now if I want to produce a high resolution image I do something like
set(gcf,'PaperUnits','inches','PaperPosition',[0 0 4 3])
print('-dpng','-r300','somefile.png')
as described in Matlab KB.
The problem here is to determine a proper aspect such that I can specify proper paper size that would leave no white/background stripes on either sides.
Apparently if I have a map (let's say 1000x2000 cells) with aspect ratio of 0.5, and I'm printing it on 4"x3" paper, I'll get background stripes on the sides. This is quite annoying as I'd prefer 1.5"x3" paper + axes & labels or so. Right now I have to manually adjust paper size.
This is inconvenient as I'd like a universal solution. For instance I may print a plot into file that I expect to occupy 4"x3" as well that has no fixed aspect. Or I may want to print a 3D figure. I'm aware of daspect and pbaspect, but how can I know how it is currently drawn?
Perhaps I can derive current 2D aspect from get(gca,'Position') and then scale it to my maximum allowed desired size (e.g., 4"x3") while respecting whether DataAspectRatioMode (?) property is set to manual. Is it the way to proceed or is there a better way?
I am not exactly sure if I understand your problem exactly, but I have used the following commands to create pdf images that are sized exactly to the size of the figure. I have used this for both 2D and 3D figures. The "handle" variable is simply your figure handle.
set(handle,'Units','inches');
set(handle,'PaperUnits','Inches','PaperPositionMode','auto');
P = get(handle,'Position');
set(handle,'PaperSize', [P(3),P(4)]);

MATLAB: latex interpreter font spacing

The font spacing in TeX-typeset equations in MATLAB defaults to being highly compressed. Is there a way to increase the amount of spacing, so that, for example, the numerator and denominator of a fraction do not make contact with the line separating the two?
plot(1:10,rand(1,10));
set(gca,'FontSize',18);
legend('$\frac{xy}{\exp\left(\frac{x}{y}\right)}$');
set(legend(),'interpreter','latex');
I think the easiest way is to use some LaTeX trickery.
Long story short, in LaTeX $ ... $ is used for inline math, but for display math, you should either use \[ ... \] or the legacy way of doing the same $$ ... $$. For LaTeX documents, don't use the latter, but for MATLAB it should be enough.
The difference between inline math and display math, is like the difference between using backticks (``) and indentation in StackOverflow. The first will show your code in-between text, the latter in-between paragraphs. With math, only display mode math will have decent lay-out for larger formulas.
So the following code should fix your problem:
plot(1:10,rand(1,10));
set(gca,'FontSize',18);
legend('$$\frac{xy}{\exp\left(\frac{x}{y}\right)}$$');
set(legend(),'interpreter','latex');
If you want even more, you might want to consult the Not So Short Introduction To LaTeX2e which gets you started with a lot of the tricks of the LaTeX trade.
edit:
What I tend to use as a trick to improve spacing in formulae is using phantoms (\phantom, \vphantom, \hphantom), but \vspace or \vskip might be a little cleaner to use.
Looking through the list of properties for the legend, there doesn't seem to be any way of specifying a line spacing that is consistent with automatic positioning. You can fudge the line spacing by enlarging the box, however, by changing the final entry (height) in the OuterPosition property. It seems the placement of the box is based on its bottom-left corner, so if your legend box is in a North position then you will also need to reduce the second entry (y-position) by an equal amount.
In this example I increase the height of a North-positioned legend box by 25% (which I have found that gives nice results), which increases the line spacing.
h = legend(s1,s2,s3, 'location', 'northeast');
set(h, 'fontsize', 16, 'interpreter', 'latex')
outerposition = get(h, 'OuterPosition');
delta_h = 0.25*outerposition(4);
outerposition(2) = outerposition(2) - delta_h;
outerposition(4) = outerposition(4) + delta_h;
set(h, 'OuterPosition', outerposition)
You have to be wary about resizing the figure after running this code fragment, since changing the OuterPosition property clears the automatic placement of the box with respect to the plot axes. If you resize the figure the legend box will go walkabouts.

FreeType2: Get global font bounding box in pixels?

I'm using FreeType2 for font rendering, and I need to get a global bounding box for all fonts, so I can align them in a nice grid. I call FT_Set_Char_Size followed by extracting the global bounds using
int pixels_x = ::FT_MulFix((face->bbox.xMax - face->bbox.xMin), face->size->metrics.x_scale );
int pixels_y = ::FT_MulFix((face->bbox.yMax - face->bbOx.yMin), face->size->metrics.y_scale );
return Size (pixels_x / 64, pixels_y / 64);
which works, but it's quite a bit too large. I also tried to compute using doubles (as described in the FreeType2 tutorial), but the results are practically the same. Even using just face->bbox.xMax results in bounding boxes which are too wide. Am I doing the right thing, or is there simply some huge glyph in my font (Arial.ttf in this case?) Any way to check which glyph is supposedly that big?
Why not calculate the min/max from the characters that you are using in the string that you want to align? Just loop through the characters and store the maximum and minimum from the characters that you are using. You can store these values after you rendered them so you don't need to look it up every time you render the glyphs.
I have a similar problem using freetype to render a bunch of text elements that will appear in a grid. Not all of the text elements are the same size, and I need to prerender them before I know where they would be laid out. The different sizes were the biggest problem when the heights changed, such as for letters with descending portions (like "j" or "Q").
I ended up using the height that is on the face (kind of like you did with the bbox). But like you mentioned, that value was much to big. It's supposed to be the baseline to baseline distance, but it appeared to be about twice that distance. So, I took the easy way out and divided the reported height by 2 and used that as a general height value. Most likely, the height is too big because there are some characters in the font that go way high or way low.
I suppose a better way might be to loop through all the characters expected to be used, get their glyph metrics and store the largest height found. But that doesn't seem all that robust either.
Your code is right.
It's not too large.
Because there are so many special symbols that is vary large than ascii charater. . view special big symbol
it's easy to traverse all unicode charcode, to find those large symbol.
if you only need ascii, my hack method is
FT_MulFix(face_->units_per_EM, face_->size->metrics.x_scale ) >> 6
FT_MulFix(face_->units_per_EM, face_->size->metrics.y_scale ) >> 6