1

I have a shape contour cnt, I need to find it inside a 2D array, I have a target_index variable, it is used to find the required zone, but I need to look for the cnt contour in it.

import numpy as np

x = np.linspace(0,1000, int(1000/50))
y = np.linspace(0,1000, int(1000/50))
X,Y = np.meshgrid(x,y)

source =  np.column_stack([X.ravel(), Y.ravel()]).astype(int)
destination = source.copy()

cnt = [[550,  42],     
       [600,  42],
       [690, 273],
       [640, 273]]

# Need to use cnt here
target_index = np.where(np.logical_and(destination[:,1]==789,destination[:,0]>=421))

destination[target_index]
scope = destination[target_index] 
scope[:,0] = scope[:,0] + 10
destination[target_index] = scope
destination[target_index]


# Remap
grid_x, grid_y = np.mgrid[0:800, 0:800]
grid_z = griddata(source, destination, (grid_x, grid_y), method='cubic')
map_x = np.append([], [ar[:,1] for ar in grid_z]).reshape(800,800).astype('float32')
map_y = np.append([], [ar[:,0] for ar in grid_z]).reshape(800,800).astype('float32')
warped_image = cv2.remap(img, map_x, map_y, cv2.INTER_CUBIC)

cv2.drawContours(warped_image,[cnt],0,(0,0,0),2)

Other methods can be used, but np.where is preferred.

  • `cnt` looks like 4 corner points, defining an obtuse trapezoid? What do you mean by 'find the shape contour inside a 2D array'? What would like you to get back? – Matt Hall Oct 11 '19 at 14:52
  • @kwinkunks I want to find all the points that are inside the contour – question_mark_77 Oct 11 '19 at 16:29
  • 1
    Ah, okay... I would use [`shapely`](https://shapely.readthedocs.io/en/stable/manual.html) or [`geopandas`](http://geopandas.org/). But it looks like there might be a way to do it with `matplotlib` too. E.g. check https://stackoverflow.com/questions/21339448/how-to-get-list-of-points-inside-a-polygon-in-python – Matt Hall Oct 11 '19 at 16:34
  • 1
    Possible duplicate of [How to get list of points inside a polygon in python?](https://stackoverflow.com/questions/21339448/how-to-get-list-of-points-inside-a-polygon-in-python) – Matt Hall Oct 11 '19 at 16:34
  • @kwinkunks There is no talk of two-dimensional arrays and np.where – question_mark_77 Oct 11 '19 at 23:30
  • No, that's right: I don't think you need `np.where`. Is there a reason why you prefer it? – Matt Hall Oct 12 '19 at 00:43
  • I just noticed that there is also a pure NumPy solution on that question > https://stackoverflow.com/a/44282743/3381305. I suspect it only works on certain polygons though. – Matt Hall Oct 12 '19 at 00:53

2 Answers2

1

Unless you limit yourself to certain polygons, I think it's going to be very hard to use np.where to do this.

Here's how to use matplotlib's Path object to solve the problem (adapting this solution):

import numpy as np
from matplotlib.path import Path

x = np.linspace(0,1000, int(1000/50))
y = np.linspace(0,1000, int(1000/50))
X,Y = np.meshgrid(x,y)
source =  np.column_stack([X.ravel(), Y.ravel()]).astype(int)

cnt = [[550,  42],     
       [600,  42],
       [690, 273],
       [640, 273]]

p = Path(cnt)
grid = p.contains_points(source)
mask = grid.reshape(20, 20)

Then look at the result:

import matplotlib.pyplot as plt
plt.imshow(mask)

Which gives:

mask plot in matplotlib

Use more points in the linspace to get a higher-resolution result.

Matt Hall
  • 7,614
  • 1
  • 23
  • 36
  • Hello, unfortunately this solution doesn’t work for me, since having indices, I can’t change the values in a 2D array – question_mark_77 Oct 13 '19 at 15:03
  • @question_mark_77 I don't understand. This is working on your data. What do you want to be the output of the whole operation? – Matt Hall Oct 13 '19 at 17:03
1

Judging by your questions, you are making an application for body deformation, as for me this option is the most convenient since you can create any contours for you.

    # Left hand contour
    pt1 = (int_12, int_13)
    pt2 = (int_17, int_16)
    pt3 = (int_18, int_19)
    pt4 = (int_14, int_15)
    lh_cnt = np.array([pt1, pt2, pt3, pt4])

    offset = int(hand_lenght / 28)

    for x in destination:
        inside_lh = cv2.pointPolygonTest(lh_cnt, (x[0], x[1]), False)
        elif inside_lh > 0:
            x[0] = x[0] - offset

    # Warping
    grid_x, grid_y = np.mgrid[0:self.width, 0:self.height]
    grid_z = griddata(source, destination, (grid_x, grid_y), method='cubic')
    map_x = np.append([], [ar[:,0] for ar in grid_z]).reshape(self.width, self.height).astype('float32')
    map_y = np.append([], [ar[:,1] for ar in grid_z]).reshape(self.width, self.height).astype('float32')
    warped_image = cv2.transpose(cv2.remap(img, map_x, map_y, cv2.INTER_LANCZOS4))
Alenorze
  • 111
  • 1
  • 8