Welcome, Guest. Please login or register.

Author Topic: Help needed with a very silly idea...  (Read 8423 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Help needed with a very silly idea...
« on: January 20, 2005, 01:56:58 AM »
Hi,

I'm looking for an algorithm that can look at a bitmap image and find bounding rectangles for any closed sets (eg a solid blob, of arbitary shape) of pixels that match a particular criteria, such as colour etc. I don't need to find the exact shape, just the bounding rectangle.

For example, suppose we had an image containing 3 non overlapping ovals of a particular colour we are interested in. The algorithm needs to return the 3 rectangles that contain the oval shapes.

I do have an algorithm already that needs to make a pair of line by line scans across the bitmap (first vertically, then horizontally, finally correlating the two scans) but it is a bit slow, even with the various early-out optimisations you can make to the line-scanning.

Any takers?
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #1 on: January 20, 2005, 03:40:52 PM »
Hi,

First of all, I should point out that this would be a pre-processing step, so it isn't critical speed wise. I just don't like slowness in general.

What is important is that the rectangles generated are as tight fitting as possible, as their content is used for a realtime application.

Quote

FluffyMcDeath wrote:
Thinks a bit more...

Are these areas allowed to be "hollow" e.i. can they enclose a set of out of range pixels?


It's not that complex. Consider the letter C - the algorithm would return the smallest rectangle that the complete letter fits into. A letter O of the same basic size would return the same rectangle.

The shapes are allowed to be hollow, just like the letter O in the above example. As long as the outer boundary is enclosed in the box, that is all that matters.

Quote

And how do you start looking? Do you start in the shape, as if you were doing a paint fill, or are you just looking for pixels that satisfy the criteria within the entire pixmap?
(So, could there be more than one match.)


What the existing algorithm does is to first scan down vertically a line at a time. It starts out witth the assumption that we haven't hit an area.

The moment we find a pixel along the current scanline that matches our criteria, the y coord is noted as a 'starting Y ordinate' (yMin), and the method of scanning now changes to look for the next scanline line that doesn't contain a pixel matching our requirements. When one of those is found, the y value is noted as a 'terminating Y ordinate' (yMax).

If we get to the end of the bitmap, it is always terminated as a yMax if we happen to be in an area of "the good stuff".

And so the scan proeeds. At the end, we have a set of yMin/yMax pairs.

We then do a horizontal scan in the same way to locate the corresponding xMin / xMax pairs.

We can correlate these to get a list of rectangles. It isn't perfect in that suppose we had two circles - one large and one small, with their y centres the same but at non-overlapping values of X.

The bounding rectangle for the larger one will be perfect, but the bounding rectangle for the smaller one will be as tall as the larger one. However, this is really a trifling inconvenience for what I have in mind.


Quote

And, if you scan one way, haven't you already scanned the other? Really?
Like if you walk the Ys and you know the x where you hit the good stuff and the x where you left.


This is what I was thinking, in a way.

Quote

And you could get faster if you took those start and ends and went straight down from there to the next Y
and if you are on the right side (for e.g.) and you go down and your pixel is in range, then go right further to find the edge, else go left.
For the other side, vice versa. If your left and right get to be the same, you've closed out the bottom.
Then from your starting Y go back up the same way to close your top.


Hmm. So you are saying we could basically floodfill the areas when we find them and keep track of the xMin/xMax and yMin/yMax during the fill. That might be a good solution.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #2 on: January 20, 2005, 03:42:23 PM »
Quote

FluffyMcDeath wrote:
By the way, I should thank you for helping me boost my post count which has been languishing of late.


My pleasure :-D
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #3 on: January 20, 2005, 04:50:55 PM »
Quote

bloodline wrote:

I had to make something similar when I was trying to make GUI in SDL.

I had to look for all the areas where the "windows" over lapped and then make sure those areas were not updated.

I had to do it Vertically and then Horizontally (For every window, starting at the one below the top most one) too, I thought it would be slow, but it's not... on any of my PC's... I wouldn't want to run it on my 68K's or even my PPC :-/


You did this for rectangular windows? How come you never used a straightforward layered rectangle clipping approach for that? It would be orders of magnitude more efficient than scanning pixels.

My problem is that I'm dealing with irregular blobs so I have to do this.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #4 on: January 20, 2005, 05:48:22 PM »
The background colour is not really known.

All you really know, is that within the image, there will be irregular splodges that have a value within your target tolerance. All around them are pixels simply outside your tolerance. There are no areas of flat colour for the background.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #5 on: January 20, 2005, 08:07:20 PM »
@Minator

When I said "scanning vertically" I meant scanning lines in the Y direction, rather than actually scanning reading down a column of 1-pixel. I guess that isnt very obvious :lol:

To be clear, I read successive scanlines (each one at am increasing y) first, to determine the yMin / yMax boundaries. This amounts to reading along a horizontal line until we first hit something. This is our first yMin.

The thing is, due to the irregularity of the shapes, you can't say "this is also your x-min" because it simply isn't possible to know - unless it occurs at x=0, that is. The next scanline might have a pixel of the same criteria some pixels to the left of the one on the previous line. You would need a quite sophisticated mechanism for tracking all the x values you uncovered in the previous scanline and working out which ones correspond to the equivalent x values on the current scanline.

By using 2 scans, we can concentrate on resolving only one set of extrema for each pass. The idea works but it's just trying to find a more optimal approach. As you say, it's scanning the successive vertical lines (each one at an increasing value of x) that takes a hit.

Of course, a single scan of the entire thing does uncover all the information but it is not easy to resolve it without using a memory of some kind. The two scan approach basically forgoes this.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #6 on: January 24, 2005, 08:50:13 PM »
Hi Jose,

Yes. It's basically the case that there will be several such shapes in any given 2D area. The idea is to find the smallest bounding boxes around them, within a tolerance threshold.

The problem is still open ended, but I'm also looking into another solution which may be more useful, especially for awkward shapes.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #7 on: January 24, 2005, 11:52:34 PM »
Here's an image to make the problem more visual:



The blue areas are outside our tolerance, the grey areas inside. The white rectangles are the areas I wish to find. Note from the diagram that:

A bounding rectangle may contain more than one 'blob', provided it properly fits the largest one.

A blob may be 'hollow' - I am only interested in the box around the outer extent.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #8 on: January 27, 2005, 07:33:11 PM »
@Jose

Are your pixels arranged as 8-bit bytes? If your data reside in copyback memory, you will find that on 040+ bytewise comparison is not such a big issue. It is still slower but, not as bad as you might expect.

However, you can compare 2 sets of 4x8-bit pixels or 2 sets of 2x15/16-bit pixels using longwords.

If you exclusively or the two longwords together, you will highlight any bits that are different in each set of pixels. All the bits which are the same in both sets of pixels will be zero. Depending on what you intend to do with the data, I'm not sure if this will help you or not.

Oh - if you need to know which pixels are different, there are a couple of ways of working it out. Probably the easiest is to take the result of the 32-bit xor operation and mask it with four succesive 32-bit masks that each isolate a byte in the long word. Anything coming up as non zero is a difference.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #9 on: January 27, 2005, 09:51:55 PM »
@woof

That's interesting to know - pity I dont have altivec :-(

Well, not yet ;-)

As it goes, this doesn't help my immediate problem - which is better explained by the image than anything I can easily write :-)

Mind you, course all I am looking for is to speed up something that isn't really time critical (or at least not yet anyway - that might change).
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #10 on: January 27, 2005, 10:28:54 PM »
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #11 on: January 28, 2005, 12:12:49 PM »
@Waccoon

I'm using C. Well, I'm really using C++, but the code might be used in a related C project so it might as well be just C.

@Minator

I could tell you, but then I'd have to kill you :lol:

Nah, it isn't for anything important, it was just a small problem that cropped up in a recent project that I suddenly found interesting in it's own right.

Basically I am determining some bounding-box extents based on the opacity of an image for some processing I need to do. As it goes, contrary to what you might expect, I need the actual bounding box and not the pixel-exact 'mask' of the area.

That said, even if one does find the pixel exact mask, one can easily determine the bounding box, but I thought there might be a quicker way that takes advantage of not needing the exact mask...
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #12 on: January 28, 2005, 03:04:37 PM »
bleh, you lazy, unoptimizing git :lol:
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #13 on: January 28, 2005, 03:14:58 PM »
You know, it's an interesting in point.

I know a few people who write the most atrocious code imaginable, simply because they are spoiled by the performance of their hardware. People who should not be let anywhere near a compiler, for that matter. Their only skill is in the application of brute force to solve any problem. Then they use some convenience-oriented, high-level language/design tools with which to write their ill thought out code.

I worry that the arts of problem analysis, algorithm design and implementation efficiency are fast dying.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Help needed with a very silly idea...
« Reply #14 on: January 28, 2005, 03:24:26 PM »
Quote

bloodline wrote:

Well, I would suggest the shift is from a problem oriented view of program design to a solution one.
Err... We don't need to worry about the implementation of the problem, and instead worry more abotu the outcome of the solution... or something...


Which is a completely bollox approach for this situation. And indeed most of the things I work on.

I guess I like the mental challenges of actually doing something well.
int p; // A