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]);
Related
I have a set of 450 jpg images, each approximately 1200x1500 pixels. I want to apply a black border to every image to make them all 1500x1500 pixels.
Here is an example image: test01.jpg
And I want to turn it into as image that looks like this: 1500x1500 image with border
The way I have been trying to do it is by superimposing a png image of a black border on top of the original image. However, this hasn't worked very well :( Here's my code so far:
A = imread('test01.jpg'); %open image
A2 = imresize(A,[1500 1200]); %resize image to 1500 x 1200 just to make sure it is correct height
RA = imref2d(size(A2));
B = imread('cropper_and_outline_1500x1500.png'); %open cropper
RB = imref2d(size(B));
C = imfuse(A2,B,'blend','Scaling','joint'); %fuse images
imshow(C)
Here's my current output.
There are a few errors... a) the black border is not opaque, b) transparent colour is set to green not transparent, c) the two images are aligned at the top-left corner but I need them centre aligned.
I have been playing with the alpha level to try and fix the green but I didn't really understand what it meant so didn't get far! I also know this might not be the simplest way to do it so if anyone has any other ideas I would really love to hear them. I am trying to do this in MATLAB because I already have a script for renaming the files and I would ideally like to combine both into a single script.
Thanks a lot!
Why not just add black lines to the original image?
I = imread(yourfile);
expectedSize = [1500, 1500];
% Add horizontal lines of pixels (if needed)
line1 = zeros(1, size(I, 2));
Im = [repmat(line1, [(expectedSize(1) - size(I, 1))/2, 1, 3]); ... % add lines on top
I; ...
repmat(line1, [(expectedSize(1) - size(I, 1))/2, 1, 3])]; % add lines on the bottom
% Add vertical lines of pixels (if needed)
line2 = zeros(size(Im, 1), 1);
Im = [repmat(line2, [1, (expectedSize(2) - size(Im, 2))/2, 3]), ... % add lines to the left
Im, ....
repmat(line2, [1, (expectedSize(2) - size(I, 2))/2]), 3]; % add lines to the right
Well, this was done assuming that the result of expectedSize(i) - size(I, i) is divisible by 2, but you get the idea...
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');
I need to remove horizontal and vertical lines in a binary image. Is there any method for filtering these lines? bwareaopen() is not good method to remove these lines and also Dilation and Erosion are not good for these cases.
Does any one know a solution?
Example image:
EDIT:(added more example images:
http://s1.upload7.ir/downloads/pPqTDnmsmjHUGTEpbwnksf3uUkzncDwr/example%202.png
source file of images:
https://www.dropbox.com/sh/tamcdqk244ktoyp/AAAuxkmYgBkB8erNS9SajkGVa?dl=0
www.directexe.com/9cg/pics.rar
Use regionprops and remove regions with high eccentricity (meaning the region is long and thin) and orientation near 0 or near 90 degrees (regions which are vertical or horizontal).
Code:
img = im2double(rgb2gray(imread('removelines.jpg')));
mask = ~im2bw(img);
rp = regionprops(mask, 'PixelIdxList', 'Eccentricity', 'Orientation');
% Get high eccentricity and orientations at 90 and 0 degrees
rp = rp([rp.Eccentricity] > 0.95 & (abs([rp.Orientation]) < 2 | abs([rp.Orientation]) > 88));
mask(vertcat(rp.PixelIdxList)) = false;
imshow(mask);
Output:
If all of your images are the same where the horizontal and vertical lines are touching the border, a simple call to imclearborder will do the trick. imclearborder removes any object pixels that are touching the borders of the image. You'll need to invert the image so that the characters are white and the background is dark, then reinvert back, but I'm assuming that isn't an issue. However, to be sure that none of the actual characters get removed because they may also be touching the border, it may be prudent to artificially pad the top border of the image with a single pixel thickness, clear the border, then recrop.
im = imread('http://i.stack.imgur.com/L1hUa.jpg'); %// Read image directly from StackOverflow
im = ~im2bw(im); %// Convert to black and white and invert
im_pad = zeros(size(im,1)+1, size(im,2)) == 1; %// Pad the image too with a single pixel border
im_pad(2:end,:) = im;
out = ~imclearborder(im_pad); %// Clear border pixels then reinvert
out = out(2:end,:); %// Crop out padded pixels
imshow(out); %// Show image
We get this:
You can firstly find the horizontal and vertical lines. Since, the edge map will also be binary so you can perform a logical subtraction operation in between the images. To find vertical lines, you can use (in MATLAB)
BW = edge(I,'sobel','vertical');
For horizontal lines, you can use
% Generate horizontal edge emphasis kernel
h = fspecial('sobel');
% invert kernel to detect vertical edges
h = h';
J = imfilter(I,h);
This is the problem I have: I have an image as shown below. I want to detect the circular region which I have marked with a red line for display here (that particular bright ring).
Initially, this is what I do for now: (MATLAB)
binaryImage = imdilate(binaryImage,strel('disk',5));
binaryImage = imfill(binaryImage, 'holes'); % Fill holes.
binaryImage = bwareaopen(binaryImage, 20000); % Remove small blobs.
binaryImage = imerode(binaryImage,strel('disk',300));
out = binaryImage;
img_display = immultiply(binaryImage,rgb2gray(J1));
figure, imshow(img_display);
The output seems to be cut on one of the parts of the object (for a different image as input, not the one displayed above). I want an output in such a way that it is symmetric (its not always a perfect circle, when it is rotated).
I want to strictly avoid im2bw since as soon as I binarize, I lose a lot of information about the shape.
This is what I was thinking of:
I can detect the outer most circular (almost circular) contour of the image (shown in yellow). From this, I can find out the centroid and maybe find a circle which has a radius of 50% (to locate the region shown in red). But this won't be exactly symmetric since the object is slightly tilted. How can I tackle this issue?
I have attached another image where object is slightly tilted here
I'd try messing around with the 'log' filter. The region you want is essentially low values of the 2nd order derivative (i.e. where the slope is decreasing), and you can detect these regions by using a log filter and finding negative values. Here's a very basic outline of what you can do, and then tweak it to your needs.
img = im2double(rgb2gray(imread('wheel.png')));
img = imresize(img, 0.25, 'bicubic');
filt_img = imfilter(img, fspecial('log',31,5));
bin_img = filt_img < 0;
subplot(2,2,1);
imshow(filt_img,[]);
% Get regionprops
rp = regionprops(bin_img,'EulerNumber','Eccentricity','Area','PixelIdxList','PixelList');
rp = rp([rp.EulerNumber] == 0 & [rp.Eccentricity] < 0.5 & [rp.Area] > 2000);
bin_img(:) = false;
bin_img(vertcat(rp.PixelIdxList)) = true;
subplot(2,2,2);
imshow(bin_img,[]);
bin_img(:) = false;
bin_img(rp(1).PixelIdxList) = true;
bin_img = imfill(bin_img,'holes');
img_new = img;
img_new(~bin_img) = 0;
subplot(2,2,3);
imshow(img_new,[]);
bin_img(:) = false;
bin_img(rp(2).PixelIdxList) = true;
bin_img = imfill(bin_img,'holes');
img_new = img;
img_new(~bin_img) = 0;
subplot(2,2,4);
imshow(img_new,[]);
Output:
Is there any way to constraint the the imline to be always perpendicular to the other imline drawn on the same object. for ex. I draw a first line using "imline" now I want to draw second line across the first line to be perpendicular to it. if there is a way to force the second imline to be perpendicular to the first line keeping the flexibility of extending the length it will solve my problem some extent.
I want something like a flexible cross hair(which can rotate along the axis and have flexible sides) on my image to measure the height and width of the certain object.
Code:
function perpline()
imshow(rand(200),[]);
line1 = imline(gca,[50 50; 150 150]);
setColor(line1,'r');
line2 = imline(gca,[50 150; 150 50]);
setColor(line2,'g');
addNewPositionCallback(line2,#(pos)callback_line(pos));
function callback_line(pos)
% Must update line1 based on line2's position
pos_line1 = getPosition(line1);
pos_line2 = getPosition(line2);
% Get middle
pos_center = [(pos_line2(1,1)+pos_line2(2,1))/2 (pos_line2(1,2)+pos_line2(2,2))/2];
% Find displacement
vec_disp = [pos_line2(2,1)-pos_line2(1,1) pos_line2(2,2)-pos_line2(1,2)];
% Get normal unit vector
vec_perp = [-vec_disp(2) vec_disp(1)]/norm(vec_disp);
% Preserve length of line2
length_line1 = norm([pos_line1(2,1)-pos_line1(1,1) pos_line1(2,2)-pos_line1(1,2)]);
pos_line1_update = [-vec_perp*length_line1/2+pos_center;
vec_perp*length_line1/2+pos_center];
% Set position
setPosition(line1,pos_line1_update);
end
end
Save it as a function then call it. You can drag the green line around and the red line remains perpendicular. Note that you have to define how you want it to preserve the perpendicularity. I chose to preserve the length of the red line and keep it in the center of the green line.