i am trying to extract outline path from given bitmap, i create a fast algorithm (for me) on as3 and that is:
//#v source bitmap's vector data
//#x x to starting extraction
//#y y to stating extraction
//#w extraction width
//#h extraction height
//#mw source bitmap width
//#mh source bitmap height
private function extractRects(v:Vector.<uint>, x:int, y:int,
w:int, h:int, mw:int, mh:int):Array
{
var ary:Array = [], yy:int=y, vStart:int, _xx:int, xx:int;
var lcold:int = 0, lc:int;
//first line to last line
while(yy < h)
{
//first index of current vector
vStart = yy * mw + x;
xx = x;
lc = 0;
//first vector to last on current scan
while(xx < w)
{
/*
if current vector value (color) is
empty (transparent) then
check next
*/
while(xx < w && !v[vStart])
{
vStart++;
xx++;
}
//it is not empty so copy first index
_xx = xx;
//check till value is not empty
while(xx < w && v[vStart])
{
xx++;
vStart++;
}
//create rectangle
var rr:Rectangle = new Rectangle(_xx, yy, (xx-_xx), 1);
//if previous line has the same rectangle index
if(lc < lcold)
{
var oldrr:Rectangle = ary[ary.length - lcold];
//if previous neighbour rect on top
//has same horizontal position then
//resize its height
if(oldrr.left == rr.left && oldrr.width == rr.width)
oldrr.height++;
else
ary.push(rr);
}
else
ary.push(rr);
lc++;
xx++;
}
lcold = lc;
yy++;
}
return ary;
}
With the above method, I extract the region and create shape by drawing rectangles..
Drawing rectangles does not seem to be a good solution because of non-smooth view.
In order to have a smoother view, I must use lines or curves but, using point neighbouring technique is really big headache for me right now.
Could anyone please recommend me any better solution?
as3, c++, c#, vb.net, vb6, delphi, java or similar languages will be fine for answers.
EDIT FOR CLEARIFICATION
I am trying to extract non-transparent pixels' x, y coordinates from a bitmap to draw on different path data. (32 bit ARGB) (creating shape)
For drawing, I could use lineTo, curveTo, moveTo operations.
moveTo(x, y)
lineTo(x, y)
curveTo(cx, cy, ax, ay)
in my code, I thought that I could extract the rectangles of current non-transparent blocks and I could use the same rectangles with moveTo and lineTo operations on further graphic methods
The problem is that this method gives non-smooth look on edges which is neither horizontal nor vertical.
So, the solution is creating a point map on edges, detecting the point neighborhood, using the lineTo operation (because it generates antialiased lines) between neighbour points on rows, or calculating the points placement on nearest circle area and using curveTo method..
Question Could anyone recommend me some algorithms or methods for extracting job?
Thanks in advance
What you're looking for is bitmap/raster image to vector software. To get a good quality result, there are many non-trivial steps that must be performed. There is an open source project called Potrace which does this - click here for a technical description of how it works. If you'd like to try its algorithm in an GUI program, you can use Inkscape with its Trace Bitmap function.
Related
I'm plotting a polygon made of edges and vertices. I'd like to plot these elements at a specific size or proportion: whether the polygon has 10 or 1000 vertices, I'd like the elements to be drawn at the same size. When zooming in and out of the vector image, element size would remain static.
For example, define a canvas of 100inx100in and draw lines .1in thick (and save to a pdf).
Currently, it seems impossible since, e.g., the LineWidth, MarkerSize, and FontSize are relative to the screen instead of the canvas. This means that when you zoom into the figure, the elements keep their size wrt screen. One option is to scale their size according to the zoom level. However, then the large polygon wouldn't necessarily fit the screen.
There are two ways that I see to resolve this, both seem impossible:
Define the size properties wrt the canvas and not the screen.
Go to the proper zoom level, and draw all elements even if they aren't in the figure clip region (save to a pdf).
Questions on the subject asked about specific elements such as lines or markers. The suggested solutions were to draw with alternative functions such as patch() and rectangle().
In that case, I'll forsake matlab's clunky drawing mechanism altogether, export the data, and draw in svg. But it would be a shame since matlab has powerful tools such as different marker shapes or a force graph.
Am I missing something fundamental or is this the worst design I've seen lately?
Duplicate:
www.mathworks.com/matlabcentral/answers/1569953-plot-elements-of-specific-size
Matt J. observed that, in fact, when saving a pdf, there's no resolution limit regardless of the figure limitation.
http://www.mathworks.com/matlabcentral/answers/1569953-plot-elements-of-specific-size
Then, we can do the following:
Draw a small proof-of-concept plot with the right proportion between elements (markers, edges, and fonts). Save the data-unit-to-point ratio (sc0 below). Alternatively, you can use the same constant for all your drawings, considering this matlab's default drawing ratio.
Draw a plot of any complexity with similar proportions.
Scale it to have the same ratio as the saved one.
Save to pdf.
For example:
% draw a vertical polyline with n vertices
n = 5; % polyline size
y = 0:n;
plot( zeros( size(y) ), y, '-o', 'LineWidth', 2, 'MarkerSize', 10 );
axis equal;
% scale
sc0 = 51; % ratio calculated by data_units_to_points_ratio() from the initial (designed) fig of a polyline of size 5
sc = data_unit_to_point_ratio() / sc0;
scale_fig_objects( sc );
% save
print( 'plot.pdf' );
If you change n=100, the figure would be a proportional mess (a thin line, markers not showing), but the pdf would be fine, having the same segment (vertex to edge) proportion.
Functions used:
% Based on Matt's suggestion
function conversionFactor = data_unit_to_point_ratio()
set( gcf, 'Units', 'points' );
DU = diff(xlim); % width of figure in data units
hfig = gcf;
P = hfig.Position(3); % width of figure in points
conversionFactor = P / DU; % conversion factor, data units to points
and
function scale_fig_objects( s )
hs = findobj;
for i = 1:length( hs )
h = hs(i);
t = h.Type;
if strcmpi( t, 'line' ) || strcmpi( t, 'GraphPlot' )
h.LineWidth = h.LineWidth * s;
h.MarkerSize = h.MarkerSize * s;
elseif strcmpi( t, 'scatter' )
h.SizeData = h.SizeData * s^2; % it's a squared factor!
elseif strcmpi( t, 'text' )
h.FontSize = h.FontSize * s;
end
end
This is about a project where I'm tracking people walking on a floor with an infrared camera mounted on the ceiling. I get 'blobs' as rectangles with x/y/w/h information.
Now essentially I need to allocate/assign these blobs to a grid respectively to the grid's cells in percent... so depending where the blobs are and which cells they overlap, the cells should get a percentage of 0% to 100%
Are there best practices on how to approach this? How to relate the blob position/size to the cells?
Image: The darker the cell, the more the blob (red) overlaps
The best way would be to calculate the overlapping area of the blob rectangle on the grid rectangle than divide that by the total area of the grid rectangle. A simple google search and reading should get you towards the right direction on implementing this or you could use some type of existing physics library if it has the method your looking for.
Basically loop through each pixel in your found object and bin it into your grid using the modulus of your grid spacing. There are probably faster/ more efficient ways to do what you need, but this will get the job done.
int[][] grid
int gridSpacing
int[][] objectPix
for(objectPix[][] "x")
for(objectPix[] "y")
gridSpacing[Math.Floor(x/gridSpacing)][Math.Floor(y/gridSpacing)]++
Then in a final step (if you want percentage) go through grid and divide its value by the total number op pixels in the object.
With more details/ effort, you could probably make a clever recursive solution which split the rectangle until it only resided in one grid (and tracked area on each split). But I will leave that solution to you if you need the efficiency.
Recursive method only using vertices (in c#):
public void splitRectangle(ref int[][] grid, int gridSpacing, rect curRect)
{
//if rectangle has verticies in different grid zones, split it
if(Math.Floor(curRect.pt.x / gridSpacing) != Math.Floor((curRect.pt.x + curRect.width) / gridSpacing))
{
int xDiv = gridSpacing*(Math.Floor(curRect.pt.x / gridSpacing) + 1) - curRect.pt.x;
rect split1 = new rect(curRect.pt, xDiv, curRect.height);
rect split2 = new rect(new point(curRect.pt.x + xDiv, curRect.pt.y), curRect.width - xDiv, curRect.height);
splitRectangle(grid, gridSpacing, split1);
splitRectangle(grid, gridSpacing, split2);
}
else if (Math.Floor(curRect.pt.y / gridSpacing) != Math.Floor((curRect.pt.y + curRect.height) / gridSpacing))
{
int yDiv = gridSpacing*(Math.Floor(curRect.pt.y / gridSpacing) + 1) - curRect.pt.y;
rect split1 = new rect(curRect.pt, curRect.width, yDiv);
rect split2 = new rect(new point(curRect.pt.x, curRect.pt.y+yDiv), curRect.width, curRect.height-yDiv);
splitRectangle(grid, gridSpacing, split1);
splitRectangle(grid, gridSpacing, split2);
}
//if rectangle is fully contained within 1 grid zone, then add its area to that gridZone
else
{
grid[Math.Floor(curRect.pt.x / gridSpacing)][Math.Floor(curRect.pt.y / gridSpacing)] += curRect.width * curRect.height;
}
}
I wrote this quickly and did not test it, but it conveys the method that I think will allow you to do what you want. Again, the last step will be going through grid and dividing all cells by original rectangle area to turn them into percent...
I'm coding a game using Box2D and SFML, and I'd like to let my users import their own textures to use as physics polygons. The polygons are created using the images' alpha layer. It doesn't need to be pixel perfect, and this is where my problem is. If it's pixel-perfect, it's going to be way too buggy when the player gets stuck between two rather complex shapes. I have a working edge-detection algorithm, and it produces something like this. It's pixel per pixel (and the shape it's tracing is simply a square with an dip). After that, I have a simplifying algorithm that produces this. It works fine to me, but if every single corner is traced like that, I'm going to have some problems. The code for the vector-simplifying is this:
//borders is a std::vector containing simple Box2D b2Vec2 (2D vector class containing an x and a y)
//vector shortener
for(unsigned int i = 0; i < borders.size(); i++)
{
int x = 0, y = 0;
int counter = 0;
//get the values for x and y that need to be added to check whether in a line or not
x = borders[i].x - borders[i-1].x;
y = borders[i].y - borders[i-1].y;
//while points are aligned..
while((borders[i].x + x*counter == borders[i + counter].x) && (borders[i].y + y*counter == borders[i+counter].y))
{
counter++;
}
if(counter-1 > i)
{
borders.erase(borders.begin() + i, borders.begin() + i + counter -1);
}
}
So my question is, how can I transform the previous set of vectors into something a bit less precise? Are there any rounding algorithms out there? If so, which is best? Any tips you can give me? It doesn't matter whether the resulting polygon is convex or concave, I'm triangulating it anyways.
Thanks,
AsterAlff
I get a logical riddle and I need an efficient algorithm to solve it.
I have large rectangle (box) with size w*h (width*height).
I have also x other rectangles with not size but with fixed proportions.
What is the fastest way to get the x that will let each of the X rectangle the maximum size to be inside the box(large rectangle)?
Example:
The box rectangle size is 150* 50 (width * height) and i have 25 small rectangles.
The fixed proportion of the small rectangle is 3 (if height =5 then width =5*3=15).
Lets call the height of the rectangle x.
I want to find that largest X that will let me to insert all the rectangle into the big rectangle (into the box).
(The small rectangles will be placed in rows and columns, for example 5 columns and 5 rows by the proportion and maximum height)
Does anyone know an efficient algorithm to solve this?
Um what?
Isn't it just (w*h)/75?
Yeah, brackets aren't needed... but isn't that what you want? Or am i totes missing something here?
Where w and h are the dimensions of the big or parent rectangle.
And 75 is 3*25.
I would attempt to solve this problem empirically (solve using backtracking) instead of analytically, i.e. find all possibilities* (I'll explain the *). Essentially we want to place every rectangle starting with as small as that rect can be to its maximum size (max size can be defined by largest the rectangle can be before bumping into the start point of its neighbors or growing to the container master rect). What this means is if we attempt to place every rect in its every possible size, one of those solutions will be the best solution. Also note that this really a one dimentional problem since the rects height and width is bound by a ratio; setting one implicitly sets the other.
* - When I said all possibilities, I really meant most reasonable possibilities. Since we are in floating point space we cannot test ALL possibilities. We can test for finer and finer precision, but will be unable to test all sizes. Due to this we define a step size to iterate through the size of the rects we will try.
const float STEP_SIZE = 0.0001;
float fLastTotalSize = 0;
int main()
{
PlaceRect(myRects.begin(), myRects.end());
}
void PlaceRect(Iterator currentRect, Iterator end)
{
if (currentRect == end)
{
return;
}
float fRectMaxSize = CalculateMaxPossibleRectSize(*currentRect);
// find the number of steps it will take to iterate from the smallest
// rect size to the largest
int nSteps = fRectMaxSize / STEP_SIZE;
for(int i = 0; i < nSteps; ++i)
{
// based on the step index scale the rect size
float fCurrentRectTestSize = i*STEP_SIZE;
currentRect->SetSize(fCurrentRectTestSize);
float fTotalSize = CalculateTotalSizesOfAllRects();
if (fTotalSize > fLastTotalSize)
{
fLastTotalSize = fTotalSize;
SaveRectConfiguration();
}
// Continue placing the rest of the rects assuming the size
// we just set for the current rect
PlaceRect(currentRect + 1, end);
// Once we return we can now reset the current rect size to
// something else and continue testing possibilities
}
}
Based on the step size and the number of rectangles this may run for a very long time, but will find you the empirical solution.
I'm stuck on some trivial question and, well, I guess I need help here.
I have two rectangles and it's guaranteed that they have one common point from their 4 base points (upper part of the picture). It's also guaranteed that they are axis-aligned.
I know this common point (which also can be easily deduced), dimensions and the coordinates of these rectangles.
Now, I need to retrieve the coordinates of the rectangles named 1 and 2 and I'm seeking for an easy way to do that (lower part of the picture).
My current implementation relies on many if statements and I suspect I'm too stupid to find a better way.
Thank you.
Update: My current implementation.
Point commonPoint = getCommonPoint(bigRectangle, smallRectangle);
rectangle2 = new Rectangle(smallRectangle.getAdjacentVerticalPoint(commonPoint),
bigRectangle.getOppositePoint(commonPoint));
rectangle1 = new Rectangle(smallRectangle.getAdjacentHorizontalPoint(commonPoint)
bigRectangle.getOppositePoint(commonPoint));
// Now simply adjust one of these rectangles to remove the overlap,
// it's trivial - we take the 'opposite' points for 'small' and 'big'
// rectangles and then use their absolute coordinate difference as
// a fix for either width of 'rectangle2' or height of 'rectangle1'
// (in this situation it's going to be width).
adjustRectangle(rectangle2);
This is refactored, but still methods getCommonPoint and getAdjacent... and getOpposite have many if statements and I thought if this can be done better.
The top and bottom values of Rectangle 1 are the same as the big rectangle. The left and right values of rectangle 2 are the same as the small rectangle. We only need to obtain the left and right values of rectangle 1, and the top and bottom values for rectangle 2. So we only have 2 simple if-statements:
if (bigRectangle.Left == smallRectangle.Left)
left = smallRectangle.Right
right = bigRectangle.Right
else
left = bigRectangle.Left
right = smallRectangle.Left
rectangle1 = new Rectangle(left, bigRectangle.Top, right - left, bigRectangle.Height)
if (bigRectangle.Top == smallRectangle.Top)
top = smallRectangle.Bottom
bottom = bigRectangle.Bottom
else
top = bigRectangle.Top
bottom = smallRectangle.Top
rectangle2 = new Rectangle(smallRectangle.Left, top, smallRectangle.Width, bottom - top)
In the above, the Rectangle constructors takes as inputs: left, top, width, height.
From what I understand, seems like you need to have an if (or switch) statement to determine the orientation of the rectangle, and from there it would just be some easy adding and subtracting:
If you know the coords of the inner blue rectangle (and the dimensions of the rect as a whole), then finding the others should be no problem. One of the R1 and R2 points will always be the same: equal to the adjacent blue rect point. and the others is just a lil math.
Doesn't seem like you can get away from the initial if/switch statement. If the rectangle could only be up or down, then you could just make the offset negative or positive, but it can also be left or right..so you might be stuck there. You can make a -/+ offset for a vertical or horizontal state,but then you'd have to do a check on each calculation
Assuming you had RA and RB as your inputs, and whatever language you're using has a Rectangle class, here's a way to do it with 4 ifs, Math.Min, Math.Max, and Math.Abs:
Rectangle r1, r2; // Note - Rectangle constructor: new Rectangle(X, Y, Width, Height)
if (RA.X = RB.X) {
r1 = new Rectangle(Math.Min(RA.Right, RB.Right), Math.Min(RA.Y, RB.Y), Math.Abs(RA.Width - RB.Width), Math.Max(RA.Height, RB.Height));
if (RA.Y = RB.Y) {
// Intersects Top Left
r2 = new Rectangle(RA.X, Math.Min(RA.Bottom, RB.Bottom), Math.Min(RA.Width, RB.Width), Math.Abs(RA.Height - RB.Height));
} else {
// Intersects Bottom Left
r2 = new Rectangle(RA.X, Math.Max(RA.Bottom, RB.Bottom), Math.Min(RA.Width, RB.Width), Math.Abs(RA.Height - RB.Height));
}
} else {
r1 = new Rectangle(Math.Min(RA.X, RB.X), Math.Min(RA.Y, RB.Y), Math.Abs(RA.Width - RB.Width), Math.Max(RA.Height, RB.Height));
if (RA.Y = RB.Y) {
// Intersects Top Right
r2 = new Rectangle(Math.Max(RA.X, RB.X), Math.Min(RA.Bottom, RB.Bottom), Math.Min(RA.Width, RB.Width), Math.Abs(RA.Height - RB.Height));
} else {
// Intersects Bottom Right
r2 = new Rectangle(Math.Max(RA.X, RB.X), Math.Min(RA.X, RA.Y), Math.Min(RA.Width, RB.Width), Math.Abs(RA.Height - RB.Height));
}
}
This code was written in Notepad so it might have a typo or two, but the logic is sound.