Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the surrounding rectangular region given a line inside it

My Question is related to OpenCV / Matplotlib only. However, to understand the problem bear with me for a few lines of ML / Computer vision side of stuff :

I am working on a Image segmentation problem on floor plan dataset. I would be using Fully Convolutional Networks (FCN) for the same.

Now, FCNs require for an image, a corresponding segmented image. For example :

image and its groundtruth

The image on the left is actual image, while image on the right is the proper "ANNOTATION" of the image. Essentially, every object (class) is completely filled with its own colour - car, road, buildings, etc.

Now, in my case, I'm working with floor plan data. An example floorplan image looks like this :

Example floorplan image

The relevant entities in such images are walls, doors, etc.

Problem I have gotten data annotated for a HUGE bunch of such images, however it is not annotated in the above form. Walls are annotated as simple lines --- which means they're 1px thick only and do not actually fill the area/thickness of the walls in actual image. See the following example :

Annotated Data I have

See the 2 lines representing walls on top left in above image. While wall is thick, what I have as annotated data is just those pink 1px thick lines.

However, what I would require is actually filled region of walls completely. For example :

Ground truth I want

What I want to do now is, programmatically, convert these lines to filled regions, i.e., based on having data about lines for every wall, I wish to create a filled version of walls inside which these lines reside.

So, essentially the question is this : If I have a thin line inside a rectangular region, can I somehow get the whole rectangular region that it is representing? If I can I could fill it with its colour and I can annotate the way it's needed.

Some assumptions we can make : - Lines will always be representing the walls inside which they are - Walls would usually be thicker lines only having some dark colour compared to rest of the image

It would be very difficult and expensive to get data annotated again, hence I'm asking this in case this could be programmatically achieved.

I have very thin knowledge of opencv and matplotlib and hence this could be a newbie question. It might be a very very simple thing to do. In such a case, please let me know the algorithm, or function I need to read up on.

Thanks.

like image 525
Bhavul Avatar asked Apr 08 '26 21:04

Bhavul


2 Answers

Editing my answer to cover @Prune condition. I would probably try some logic such as:

  1. Find pink lines. In order to do that, you can take a look at: how to detect lines in opencv. The result of this part is an array containing endpoints of detected line segments.
  2. Find each line orientation. Consider the endpoints of one line: [x1;y1] and [x2;y2]. If (x2-x1)>(y2-y1), the line is horizontal. Else, the line is vertical.
  3. Find new endpoints. If line is horizontal, move left from your "leftiest" (smaller x) endpoint, until you find the dark gray pixel. It will be your new left endpoint (x1') once you find it. Do the same for the "rightiest" (larger x) endpoint, this time moving right, so you find x2'. If line is vertical, move down from your lower (smaller y) endpoint, until you find the dark gray pixel. It will be your new lower endpoint (y1') once you find it. Do the same for the upper (larger y) endpoint, this time moving up, so you find y2'.
  4. Draw a rectangle, in order to paint your new wall. If the wall width is constant and the pink line is centralized, from here you can simply draw a rectangle. If the line is horizontal, the top-left coordinate of the rectangle is [x1';y1+half of wall width] and the bottom-right coordinate is [x2'; y2-half of wall width]. If the line is vertical, the top-left coordinate of the rectangle is [x1-half of wall width;y1'] and the bottom-right coordinate is [x2; y2'-half of wall width].

Let me know if the 4th condition is not met. In this case, for horizontal lines, for example, we would need to iterate up/down along the horizontal line, looking for the smaller distance between the dark pixels, and then get this y-coordinates to help draw the rectangle.

like image 102
Mariana Mascarenhas de Carvalh Avatar answered Apr 10 '26 10:04

Mariana Mascarenhas de Carvalh


Normally, you could use a simple "fill" algorithm for this, as suggest in Mariana's answer. However, you need to extend only so far as the given line -- you cannot continue down the west wall of that office area. I'm assuming that each end result will be a rectangle aligned to the drawing axes.

Instead, you need a "wave-front" fill: extend the entire line north and south (the line dimension that is more than a single pixel) so far as all of the adjacent pixels are gray. Then do the same with the east-west direction. You could perform the extension by replicating the line to the adjacent pixel row/column.

I don't know of a package that will support this directly, but most will do a vectorized copy-paste or equivalent change.

like image 35
Prune Avatar answered Apr 10 '26 11:04

Prune