How to identify and store center locations of dots in grid?

Viewed 84

Ok for this I am somewhat looking for suggestions on what the next step should be and how to implement the one I am currently on.

First here is the context: I am working on a project that involves finding the center of circles that have been put in a grid. The original image was 1260x683px and had 27x15 dots in a grid inside the image. The image is stored as a text file. In the text file a 0 represents a pixel that is not part of any dot, and a 1 represents a pixel that is part of a dot.

I want to figure out a way to identify the center coordinate of each dot. Below I made a few diagrams to show what I want to do.

  • Fig 1. shows what the array looks like before any manipulation.
  • Fig 2. shows how I want to identify all the non zero elements.
  • Fig 3. Shows that I want to then narrow the identified elements to just the middle element of reach row and the middle column.
  • Finally Fig 4. Shows the desired end goal to identify the center of each dot. From there once the center is identified. I want to be able to store its position as a tuple in a 27x15 array that will be used later to identify the center points.

Its worth noting that if there is a row with an even number of 1s I want to identify the right one of the two center values (Fig 0a.) and for the columns if there is an even number of 1s I want to identify the bottom one as the center (Fig 0b.)

Fig 0a.
0001111000
..........^.......

Fig 0b.
0
0
0
1
1
1 <--
1
0
0
0

Fig 1.
00011111100000000111111000...
00111111110000001111111100...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
00111111110000001111111100...
00011111100000000111111000...

Fig 2.
00011111100000000111111000...
00111111110000001111111100...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
00111111110000001111111100...
00011111100000000111111000...

Fig 3.
00011111100000000111111000...
00111111110000001111111100...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
00111111110000001111111100...
00011111100000000111111000...

Fig 4.
00011111100000000111111000...
00111111110000001111111100...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
01111111111000011111111110...
00111111110000001111111100...
00011111100000000111111000...

Overall the tldr is that I need to find a way to determine the centers of each dot in a 27x15 grid, then store the coordinates of those centers into a separate array. I hope this makes sense, but I am happy to answer any questions to specify what I meant.

1 Answers

I went another route, convoluting the image by summing the pixel values and re-normalising until the picture doesn't change. My bold hypothesis is that you're left with the candidates for centre points:

from numpy import array, max, where

img = """00011111100000000111111000
00111111110000001111111100
01111111111000011111111110
01111111111000011111111110
01111111111000011111111110
01111111111000011111111110
01111111111000011111111110
01111111111000011111111110
00111111110000001111111100
00011111100000000111111000"""

img = array([[int(i) for i in row] for row in img.split("\n")], int)

print(img)
print()

def convolute(img):
    s_x, s_y = img.shape
    result = array(img)
    for dx in (-1, 0, 1):
        for dy in (-1, 0, 1):
            result[1:s_x - 2, 1:s_y - 2] += img[1 + dx: s_x - 2 + dx,
                                                1 + dy: s_y - 2 + dy]

    # focus on the centers
    result[result<max(result)] = 0
    result[result > 0] = 1
    return result
    
while True:
    img2 = convolute(img)
    if (img2 == img).all():
        break
    img = img2
    print(img)
    print()
    
indices = where(img)
for x, y in zip(indices[0], indices[1]):
    print(x, y)

In this case, you'll end up with a list of coordinates:

4 5
4 6
4 19
4 20
5 5
5 6
5 19
5 20

The first four are for the left dot, the second four for the right dot.

Edit: Assuming there are only spots of maximal 2x2 left, this should work now:

# now filter out all but bottom right corners
img[:-1,:-1] &= 1 - (img[1:,:-1] | img[:-1, 1:])

A pixel only survives if not the bottom or right neighbour is on.

Related