How to detect a point above and below a region? - image

I have this image:
Where the red dots are coordinates that divide the different letters of this Arabic word segment.
I want to detect the dots above or below the areas between the dots.
The dots are (from left to right) = [81,183;80,217;83,275;83,314]
Now there is a dot above the letter between [81,183] and [80,217]. Similarly there are dots above section between [80,217] and [83,275] and dots below region [83,275] and [83,314].
What I want to do is suppose a dot is detected above a coordinate then that coordinate must be deleted.
Would it be possible to detect these in Matlab?
edit: Here is the original image
The first image is just a crop showing my region of interest

You can extract the coordinates of the individual objects with regionprops
Here is an example implementation:
im=rgb2gray(imread('http://i.stack.imgur.com/jic1X.jpg'));
P=regionprops(~im2bw(im), 'All');
Areas=cell2mat({P.Area});
Centroids=cell2mat({P.Centroid}');
Select only the points that have an area larger that 10 but smaller than 100:
Coord=Centroids(Areas< 100 & Areas > 10,:);
Monitor the dots found:
imshow(im);
hold on
for k=1:length(Coord)
plot(Coord(k,1), Coord(k,2), 'ro');
hold on
end
Result:
You can then sort the points with something like:
Aboves=Coord(Coord(:,2) < 80,:);
Belows=Coord(Coord(:,2) > 80,:);
From here, there are many ways of solving your problem, one option is the following:
dots=[81,183;80,217;83,275;83,314];
DetectDots=zeros(length(dots)-1, 1); % Creating a vector of zeros corresponding to the gaps between the elements in 'dots'
for k=1:size(dots,1)-1
if ~isempty(find((Aboves(:,1) > dots(k,2) & Aboves(:,1) < dots(k+1,2)))) %*
DetectDots(k)=1;
elseif ~isempty(find((Belows(:,1) > dots(k,2) & Belows(:,1) < dots(k+1,2))))
DetectDots(k)=-1;
else
DetectDots(k)=0;
end
end
The result is a vector DetectDots with value [1,1,-1] in this case that indicates that there are dots above between the two first point, and between the second and third point, and dots below between the third and last point of the vector dots.
*find returns a logical array with ones where the condition is met. isempty checks if the output of find has at least one element. As a result the condition is one if there is at least one element in the array Aboves or Belows that meets the criteria. ~ is the logical NOT, hence ~= means not equal. & is the logical AND. Note also that the coordinates between images and arrays are inverted in matlab.

Related

How can you iterate linearly through a 3D grid?

Assume we have a 3D grid that spans some 3D space. This grid is made out of cubes, the cubes need not have integer length, they can have any possible floating point length.
Our goal is, given a point and a direction, to check linearly each cube in our path once and exactly once.
So if this was just a regular 3D array and the direction is say in the X direction, starting at position (1,2,0) the algorithm would be:
for(i in number of cubes)
{
grid[1+i][2][0]
}
But of course the origin and the direction are arbitrary and floating point numbers, so it's not as easy as iterating through only one dimension of a 3D array. And the fact the side lengths of the cubes are also arbitrary floats makes it slightly harder as well.
Assume that your cube side lengths are s = (sx, sy, sz), your ray direction is d = (dx, dy, dz), and your starting point is p = (px, py, pz). Then, the ray that you want to traverse is r(t) = p + t * d, where t is an arbitrary positive number.
Let's focus on a single dimension. If you are currently at the lower boundary of a cube, then the step length dt that you need to make on your ray in order to get to the upper boundary of the cube is: dt = s / d. And we can calculate this step length for each of the three dimensions, i.e. dt is also a 3D vector.
Now, the idea is as follows: Find the cell where the ray's starting point lies in and find the parameter values t where the first intersection with the grid occurs per dimension. Then, you can incrementally find the parameter values where you switch from one cube to the next for each dimension. Sort the changes by the respective t value and just iterate.
Some more details:
cell = floor(p - gridLowerBound) / s <-- the / is component-wise division
I will only cover the case where the direction is positive. There are some minor changes if you go in the negative direction but I am sure that you can do these.
Find the first intersections per dimension (nextIntersection is a 3D vector):
nextIntersection = ((cell + (1, 1, 1)) * s - p) / d
And calculate the step length:
dt = s / d
Now, just iterate:
if(nextIntersection.x < nextIntersection.y && nextIntersection.x < nextIntersection.z)
cell.x++
nextIntersection.x += dt.x
else if(nextIntersection.y < nextIntersection.z)
cell.y++
nextIntersection.y += dt.y
else
cell.z++
nextIntersection.z += dt.z
end if
if cell is outside of grid
terminate
I have omitted the case where two or three cells are changed at the same time. The above code will only change one at a time. If you need this, feel free to adapt the code accordingly.
Well if you are working with floats, you can make the equation for the line in direction specifiedd. Which is parameterized by t. Because in between any two floats there is a finite number of points, you can simply check each of these points which cube they are in easily cause you have point (x,y,z) whose components should be in, a respective interval defining a cube.
The issue gets a little bit harder if you consider intervals that are, dense.
The key here is even with floats this is a discrete problem of searching. The fact that the equation of a line between any two points is a discrete set of points means you merely need to check them all to the cube intervals. What's better is there is a symmetry (a line) allowing you to enumerate each point easily with arithmetic expression, one after another for checking.
Also perhaps consider integer case first as it is same but slightly simpler in determining the discrete points as it is a line in Z_2^8?

How to detect a portion of an image based upon the matrix values?

I have a simple pcolor plot in Matlab (Version R 2016b) which I have uploaded as shown in the image below. I need to get only the blue sloped line which extends from the middle of the leftmost corner to the rightmost corner without hard-coding the matrix values.
For instance: One can see that the desired slope line has values somewhere approximately between 20 to 45 from the pcolor plot. (From a rough guess just by looking at the graph)
I'm applying the following code on the matrix named Slant which contains the plotted values.
load('Slant.mat');
Slant(Slant<20|Slant>50)=0;
pcolor(Slant); colormap(jet); shading interp; colorbar;
As one can see I hard-coded the values which I don't want to. Is there any method of detecting certain matrix values while making the rest equal to zero?
I used an other small algorithm of taking half the maximum value from the matrix and setting it to zero. But this doesn't work for other images.
[maxvalue, row] = max(Slant);
max_m=max(maxvalue);
Slant(Slant>max_m/2)=0;
pcolor(Slant); colormap(jet); shading interp; colorbar;
Here is another suggestion:
Remove all the background.
Assuming this "line" results in a Bimodal distribution of the data (after removing the zeros), find the lower mode.
Assuming the values of the line are always lower than the background, apply a logic mask that set to zeros all values above the minimum + 2nd_mode, as demonstrated in the figure below (in red circle):
Here is how it works:
A = Slant(any(Slant,2),:); % save in A only the nonzero data
Now we have A that looks like this:
[y,x] = findpeaks(histcounts(A)); % find all the mode in the histogram of A
sorted_x = sortrows([x.' y.'],-2); % sort them by their hight in decendet order
mA = A<min(A(:))+sorted_x(2,1); % mask all values above the second mode
result = A.*mA; % apply the mask on A
And we get the result:
The resulted line has some holes within it, so you might want to interpolate the whole line from the result. This can be done with simple math on the indices:
[y1,x1] = find(mA,1); % find the first nonzero row
[y2,x2] = find(mA,1,'last'); % find the last nonzero row
m = (y1-y2)/(x1-x2); % the line slope
n = y1-m*x1; % the intercept
f_line = #(x) m.*x+n; % the line function
So we get a line function f_line like this (in red below):
Now we want to make this line thicker, like the line in the data, so we take the mode of the thickness (by counting the values in each column, you might want to take max instead), and 'expand' the line by half of this factor to both sides:
thick = mode(sum(mA)); % mode thickness of the line
tmp = (1:thick)-ceil(thick/2); % helper vector for expanding
rows = bsxfun(#plus,tmp.',floor(f_line(1:size(A,2)))); % all the rows for each coloumn
rows(rows<1) = 1; % make sure to not get out of range
rows(rows>size(A,1)) = size(A,1); % make sure to not get out of range
inds = sub2ind(size(A),rows,repmat(1:size(A,2),thick,1)); % convert to linear indecies
mA(inds) = 1; % add the interpolation to the mask
result = A.*mA; % apply the mask on A
And now result looks like this:
Idea: Use the Hough transform:
First of all it is best to create a new matrix with only the rows and columns we are interested in.
In order to apply matlab's built in hough we have to create a binary image: As the line always has lower values than the rest, we could e.g. determine the lowest quartile of the brightnesses present in the picture (using quantile, and set these to white, everything else to black.
Then to find the line, we can use hough directly on that BW image.

Detect a rectangle bound of an character or object in black/white or binary image

I'm developing a handwriting recognition project. one of the requirements of this project is getting an image input, this image only contains some character object in a random location, and firstly I must extract this characters to process in next step.
Now I'm confusing a hard problem like that: how to extract one character from black/white (binary)image or how to draw a bound rectangle of a character in black - white (binary) image?
Thanks very much!
If you are using MATLAB (which I hope you are, since it it awesome for tasks like these), I suggest you look into the built in function bwlabel() and regionprops(). These should be enough to segment out all the characters and get their bounding box information.
Some sample code is given below:
%Read image
Im = imread('im1.jpg');
%Make binary
Im(Im < 128) = 1;
Im(Im >= 128) = 0;
%Segment out all connected regions
ImL = bwlabel(Im);
%Get labels for all distinct regions
labels = unique(ImL);
%Remove label 0, corresponding to background
labels(labels==0) = [];
%Get bounding box for each segmentation
Character = struct('BoundingBox',zeros(1,4));
nrValidDetections = 0;
for i=1:length(labels)
D = regionprops(ImL==labels(i));
if D.Area > 10
nrValidDetections = nrValidDetections + 1;
Character(nrValidDetections).BoundingBox = D.BoundingBox;
end
end
%Visualize results
figure(1);
imagesc(ImL);
xlim([0 200]);
for i=1:nrValidDetections
rectangle('Position',[Character(i).BoundingBox(1) ...
Character(i).BoundingBox(2) ...
Character(i).BoundingBox(3) ...
Character(i).BoundingBox(4)]);
end
The image I read in here are from 0-255, so I have to threshold it to make it binary. As dots above i and j can be a problem, I also threshold on the number of pixels which make up the distinct region.
The result can be seen here:
https://www.sugarsync.com/pf/D775999_6750989_128710
The better way to extract the character in my case was the segmentation for histogram i only can share with you some papers.
http://cut.by/j7LE8
http://cut.by/PWJf1
may be this can help you
One simple option is to use an exhaustive search, like (assuming text is black and background is white):
Starting from the leftmost column, step through all the rows checking for a black pixel.
When you encounter your first black pixel, save your current column index as left.
Continue traversing the columns until you encounter a column with no black pixels in it, save this column index as right.
Now traverse the rows in a similar fashion, starting from the topmost row and stepping through each column in that row.
When you encounter your first black pixel, save your current row index as top.
Continue traversing the rows until you find one with no black pixels in it, and save this row as `bottom.
You character will be contained within the box defined by (left - 1, top - 1) as the top-left corner and (right, bottom) as the bottom-right corner.

Displaying a subset of longitude/latitude points?

I have an array of coordinates (latitude and longitude) maded in this way:
[0] = "45.01234,9.12345"
[1] = "46.11111,9.12345"
[2] = "47.22222,9.98765"
[...] etc
In a loop, convert these coordinates in meters (UTM northing / UTM easting) and after that I convert these coords in pixel (X / Y) on screen (the output device is an iPhone) to draw a route line on a custom map.
[0] = "512335.00000,502333.666666"
[...] etc
The returning pixel are passed to a method that draw a line on screen (simulating a route calculation).
[0] = "20,30"
[1] = "21,31"
[2] = "25,40"
[...] etc
As coordinate (lat/lon) are too many, I need to truncate lat/lon array eliminating the values that doesn't fill in the map bound (the visible part of map on screen).
Map bounds are 2 couple of coords lat/lon, upper left, and lower right.
Now, what is the best way to loop on this array (NOT SORTED) and check if a value is or not in bound and after remove the value that is outside?
To return a clean array that contains only the coords visible on screen?
Note: the coords array is a very big array. 4000/5000 Couple of items.
This is a method that should be looped every drag or zoom.
How can I optimize search and controls in this array?
I'd suggest breaking this into several steps:
Convert each longitude/latitude pair into a pair of meters in your new coordinate system.
Create a kd-tree data structure holding all the points in the set. This allows you to efficiently query which points lie in a given rectangular range very efficiently.
Whenever the viewport changes, find all points in the kd-tree that will be displayed in that rectangle.
To display the points, iterate over the set of points that will be displayed and display each of them.

Finding which region contains a point based on coordinates

I have 4 points that form some quadrilateral. The lines can't cross or anything like that, it should be a square, rectangle, rhombus, parallelogram, etc.
The lines that connect them break the field into 9 regions. With a square, it would look like a tic-tac-toe board (#), but with other shapes the lines will be at angles.
A point falls randomly into this 9-region field. I know the coordinates of the random point, as well as the coordinates of the quadrilateral's 4 corners.
Is there any way I can find which field contains the point without using the equations of the lines?
I'm basically looking for something like
if(p.x > q1.x && p.x < q4.x && p.y < q3.y) {
//It's in the top left region
}
etc
I'm thinking that this isn't possible when using sloped lines (rather than a square/rectangle) without solving the line equations. But I thought I'd run it by the math guys first. THANKS!
It may be equivalent to 'using the equations of the lines', but the obvious thing to do is to compute the affine transformation that takes your four points to the unit square (0,0), (0,1), (1,0), (1,1). To decide the location of a point, apply the transform to the point and compare the result against the unit square.
Anything you do is effectively "using the equations of the lines", so I'm not sure what to make of that condition. I assume you just want easy inequalities to check which region the random point (x,y) is in, so that's what I'll show you how to do.
From your question, it sounds like you always have a parallelogram, so let's assume that the points are (0,0), (a,b), (c,d), and (a+c,b+d), which makes the explanation a little easier to follow. To fix your mental picture, imagine that (a,b) is roughly "to the right" of (0,0) and (c,d) is roughly "above" (0,0). Then the equations for the "horizontal" lines are -bx+ay=0 and -bx+ay=-bc+ad, so you get three possibilities, depending on how -bx+cy compares to 0 and -bc+ad:
// Assuming -bc+ad is positive
-bx+ay < 0 // it's in the "bottom row"
0 < -bx+ay < -bc+ad // it's in the "middle row"
-bc+ad < -bx+ay // it's in the "top row"
Similarly, the equations for the "vertical" lines are dx-cy=0 and dx-cy=da-bc, so the three possibilities, depending on how dx-cy compares to 0 and to da-cb:
// Still assuming ad-bc is positive
dx-cy < 0 // it's in the "left column"
0 < dx-cy < da-cb // it's in the "middle column"
da-cb < dx-cy // it's in the "right column"
Of course, if da-cb is negative, then the three possibilities in each case are "less than da-cb", "between da-cb and 0", and "greater than 0" instead. Finally, if equality ever holds, then the point (x,y) is actually on one of the lines rather than in one of the regions.
The lines that connect them break the field into 9 regions. With a square, it would look like a tic-tac-toe board (#), but with other shapes the lines will be at angles.
What if your points make up a trapezium (or trapezoid)?
For example, if the points are (-2, 0), (2, 0), (-1, 1), (1, 1), then the 'lines ... at angles' will intersect and it's not clear which of the '9 regions' you would want, say, (0, 10) to be in:
(please excuse my Paint skills...)
Unless of course by 'The lines can't cross or anything like that' you mean that the quadrilateral is always a parallelogram?

Resources