1

Using a joints array, like the following:

enter image description here

How can I fit the internal rectangles, so that no rectangles overlap and all points are used? Basically fitting table cells to the points.

I've tried grabbing the contours, works fine:

enter image description here

With 22 points found. How can I fit these points to internal polygons? E.g. find the 21 rectangles in this image.

rawsh
  • 395
  • 5
  • 21
  • Are the white pixels guaranteed to be perfectly at the grid intersections? Like if you draw a single pixel line between each of the points, it will always be perfectly horizontal or vertical? – alkasm Sep 14 '18 at 18:32
  • Yes, this grid is obtained by processing a image of a table and the dots are always at a cell intersection – rawsh Sep 14 '18 at 20:05
  • 1
    This is a good question, it's a relatively trivial task but I don't actually know of any functions to help with this at all. I mean, I can think of the brute force solution where for each white pixel, you look to the right and to the bottom until you hit another white pixel---if you do, make all the pixels between them white, otherwise don't draw anything. But that seems horribly inefficient. Are you using Python or C++? – alkasm Sep 14 '18 at 21:17
  • 1
    If you're using Python, something like this utilizing numpy may be a good solution for you: https://stackoverflow.com/questions/48251448/filling-zeros-in-numpy-array-that-are-between-non-zero-elements-with-the-same-va – alkasm Sep 14 '18 at 21:38
  • Thanks for the link, Alexander! I appreciate the help. I figured out a solution, going to post the answer – rawsh Sep 15 '18 at 22:10

1 Answers1

1

I found the joint array through this method, I guess this is a continuation.

I figured out a quick and dirty solution. This only works with perfectly horizontal/vertical alignment, and if there is a gap in the columns, it's not handled.

# First dilate the image
kernel = np.ones((5,5),np.uint8)
dilation = cv.dilate(img,kernel,iterations = 1)

# Find contours then points
(img, contours, hierarchy) = cv.findContours(dilation, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    points = []
    for con in contours:
        if (cv.contourArea(con)>0):
            M = cv.moments(con)
            cX = int(M["m10"] / M["m00"])
            cY = int(M["m01"] / M["m00"])
            points.append([cY, cX])

# attempt at finding rectangles
map = {}
for p in points:
    map[p[1]] = []

for p in points:
    map[p[1]].append(p[0])

# Check for rectangles
keys = sorted(map.keys(), key=int)
for i in range(len(keys)-1):
    one = np.array(map[keys[i]])
    two = np.array(map[keys[i+1]])
    intersect = np.in1d(one,two)
    intersect2 = np.in1d(two,one)

    # If two horizontal collections have an intersection it's likely a cell
    if (sum(intersect) >= 2):
        intersects = sorted(one[intersect], key=int)
        for x in range(len(intersects)-1):
            rect = [keys[i], intersects[x],keys[i+1], intersects[x+1]]
            showimg(rois[numimg][rect[1]:rect[3],rect[0]:rect[2]])
rawsh
  • 395
  • 5
  • 21
  • 1
    Looks like you have a little error in the indentation below `findContours()`. Also, you may want to show this working on your image. Otherwise, nice to see you found a solution and good on you to post the answer. I believe you can select your own response as an answer after 24 hours of posting it, so don't forget to do that tomorrow :) – alkasm Sep 16 '18 at 00:01