Home > database >  How to find lines in a 2d numpy array?
How to find lines in a 2d numpy array?

Time:06-20

I have a 2D numpy array and I want to find boundary points of both horizontal and vertical lines.

gray_img = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 255, 255, 255, 255, 255, 0],
                     [0, 255, 255, 255, 255, 255, 255, 255, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 255, 255, 255, 255],
                     [0, 255, 255, 0, 0, 255, 255, 255, 255],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0, 0]])

desired_outcome = [ [[1,1],[10,1]],
                    [[1,2],[10,2]],
                    [[1,3],[2,3]], ...]

Here are the lines I want to find:

enter image description here enter image description here

Later, I want to remove the smaller lines to keep only those with more than 2 points distance.

CodePudding user response:

Here's an algorithm for horizontal lines based on prefix sums:

# Do a prefix sum to get the lengths of each line.
gray_cumsum = np.cumsum(gray_img / 255, axis=1)
gray_cumsum[:, 1:] = gray_cumsum[:, 1:] * (gray_cumsum[:, 1:] != gray_cumsum[:, :-1])
# Reindex all the points so each line starts at 1.
start_num = gray_cumsum.copy()
a = start_num[:,1:-1] != 0
b = start_num[:,:-2] == 0
c = start_num[:,2:] != 0
start_num[:,1:-1] = start_num[:,1:-1] * np.logical_and(np.logical_and(a, b), c)
start_num[:, -1] = 0
start_num = np.maximum.accumulate(start_num, axis=1)
gray_cumsum = np.maximum(gray_cumsum - start_num, 0)
# Detect only the ends of each line.
gray_cumsum[:,:-1] = gray_cumsum[:,:-1] * (gray_cumsum[:,1:] == 0)
# Get the starting and endings points of each line.
end_points = np.stack(gray_cumsum.nonzero(), axis=-1)
lengths = gray_cumsum[gray_cumsum.nonzero()]
start_points = end_points.copy()
start_points[:, 1] = start_points[:, 1] - lengths
print(start_points)
print(end_points)

Just change the indexing to get vertical lines. You can use the lengths array to filter out which lines you want.

CodePudding user response:

Is this what you want?

import pandas as pd
import numpy as np

a = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 255, 255, 255, 255, 255, 0],
                     [0, 255, 255, 255, 255, 255, 255, 255, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 255, 255, 255, 255],
                     [0, 255, 255, 0, 0, 255, 255, 255, 255],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 255, 255, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0, 0],
                     [0, 0, 0, 0, 0, 0, 0, 0, 0]])

a = a[a != 0]
list = a.tolist()
print(list)
  • Related