Вырежьте ограничивающую рамку, используя питон с сетчатой ​​сеткой - PullRequest
0 голосов
/ 11 мая 2018

Я хочу создать ограничивающий прямоугольник из следующих измерений, используя сетку, но просто не могу получить правильный прямоугольник.

Мои родительские размеры x = 0 to 19541 и y = 0 to 14394. Из этого я хочу сократить поле с x '= 4692 до 12720 и y' = 4273 to 10117.

Однако я не получаю правильных границ. Может ли кто-нибудь помочь мне здесь?

from matplotlib.path import Path

        xmin, xmax = 4692, 12720
        ymin, ymax = 4273, 10117
        sar_ver = [(4692, 10117), (12720, 10117), (12658, 4274), (4769, 4273), (4692, 10117)]

        x, y = np.meshgrid(np.arange(xmin, xmax + 1), np.arange(ymin, ymax + 1))
        shx = x
        x, y = x.flatten(), y.flatten()
        points = np.vstack((x, y)).T

        path = Path(sar_ver)
        grid = path.contains_points(points)

        grid.shape = shx.shape # 5845 X 8029

        print grid

ОБНОВЛЕНИЕ: Это то, что я пытался, и я близок к тому, что я хочу, но не совсем. Я хочу изменить исходное происхождение с 0 на окружающее изображение поле, как показано в ожидаемом выводе.

Обновленный код, который я использую, это

from matplotlib.path import Path
    nx, ny = 16886, 10079
    sar_ver = [(16886, 1085), (15139, 2122), (14475, 5226), (8419, 5601), (14046, 6876), (14147, 10079), (16816, 3748), (16886, 1085)]
    x, y = np.meshgrid(np.arange(nx), np.arange(ny))
    x, y = x.flatten(), y.flatten()
    points = np.vstack((x,y)).T
    path = Path(sar_ver)
    grid = path.contains_points(points)

    grid.shape = (10079, 16886)
    grid = np.multiply(grid,255)
    int_grid = grid.astype(np.uint8)
    grid_img = Image.fromarray(int_grid)
    grid_img.save('grid_image.png')  # ACTUAL OUTPUT IMAGE WITH ORIGIN NOT SHIFTED

Входной геом: enter image description here

Ожидаемый результат такой: не имеет значения, будет ли изображение повернуто в другую сторону, но будет ли вишня сверху, если оно выровнено правильно. enter image description here

Однако я сейчас получаю это, так что мой АКТУАЛЬНЫЙ ВЫХОД из обновленного кода выложен так:

enter image description here

Итак, я хочу сместить источник вокруг рамки.

ДЕТАЛИ ПРОБЛЕМЫ С ГРАНИЦЕЙ ПОСЛЕ ПОЛУЧЕНИЯ МАСКИ: Этот код следует после строки, размещенной во втором обновлении grid_img.save('grid_image.png') # ACTUAL OUTPUT IMAGE WITH ORIGIN NOT SHIFTED

Здесь im - матрица фактического изображения. Что должно быть x-y min, максимум im, чтобы иметь ту же форму, что и маска, и умножить их оба, чтобы получить значения в пикселях, а остальные обнулить с 0.

        img_x = 19541 # 0 - 19541
        img_y = 14394 # 0 - 14394
        im = np.fromfile(binary_file_path, dtype='>f4')
        im = np.reshape(im.astype(np.float32), (img_x, img_y))
        im = im[:10079, :16886]
        bb_list = np.multiply(grid, im)
        # slice and dice
        slice_rows = np.any(bb_list, axis=1)
        slice_cols = np.any(bb_list, axis=0)
        ymin, ymax = np.where(slice_rows)[0][[0, -1]]
        xmin, xmax = np.where(slice_cols)[0][[0, -1]]
        answer = bb_list[ymin:ymax + 1, xmin:xmax + 1]
        # convert to unit8
        int_ans = answer.astype(np.uint8)
        fin_img = Image.fromarray(int_ans)
        fin_img.save('test_this.jpeg')

Моя цель состоит в том, чтобы вырезать многоугольник заданного геома из заданного изображения. Поэтому я вынимаю маску из этого многоугольника и затем использую эту маску, чтобы вырезать ее из исходного изображения. Таким образом, умножая 1 и 0 маски на значения пикселей на изображении, получим только 1 * значения пикселей.

Я попробовал следующее, чтобы вырезать фактическое изображение, чтобы оно имело те же размеры, чтобы я мог умножить np.multiply(im, mask), но это не сработало, так как форма изображения не обрезалась по форме маски. Я попробовал ваши мин и макс ниже, но не сработало!

im = im[xmin:xmax, ymin:ymax]
ipdb> im.shape
(5975, 8994)
ipdb> mask.shape
(8994, 8467) 

Очевидно, что я не могу сделать несколько масок, и я сейчас.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Я попробовал открыть библиотеку cv2, и на больших изображениях она работает быстрее, чем meshgrid или mgrid. Публикация решения opencv2:

import numpy as np
import cv2
import matplotlib.pyplot as plt
from matplotlib.path import Path

sar_ver = np.array([[[1688, 108], [1513, 212], [1447, 522], [841, 560], [1404, 687], [1414, 1007], [1681, 374], [1688, 108]]] , 'int32')
print sar_ver.shape
mask=np.zeros((1439, 1954))
cv2.fillPoly(mask, sar_ver, 255)

sar_ver = np.asarray([(1688, 108), (1513, 212), (1447, 522), (841, 560), (1404, 687), (1414, 1007), (1681, 374), (1688, 108)])
path = Path(sar_ver)
xmin, ymin, xmax, ymax = np.asarray(path.get_extents(), dtype=int).ravel()

plt.imshow(mask[ymin:ymax+1, xmin:xmax+1])
plt.show()

Кроме того, размещение решения mgrid, которое помогал Филиппо выше, и в онлайн-чате:

import cv2
from matplotlib.path import Path
from PIL import Image
import numpy as np
sar_ver = np.asarray([(1518, 2024), (2018, 2024), (1518, 2524), (1518, 2024)])

imag = cv2.imread('test_image.jpg')
img = cv2.cvtColor(imag, cv2.COLOR_BGR2GRAY)
h, w = img.shape

path = Path(sar_ver)
xmin, ymin, xmax, ymax = np.asarray(path.get_extents(), dtype=int).ravel()

# create a mesh grid of the shape of the final mask
x, y = np.mgrid[:w, :h]
# mesh grid to points
points = np.vstack((x.ravel(), y.ravel())).T

# mask for the point included in the path
mask = path.contains_points(points)
mask = mask.reshape(x.shape).T

im = np.array(img)
bb = np.multiply(im, mask)[ymin:ymax+1, xmin:xmax+1]
# saving image or we can do  plt.show
int_ans = bb.astype(np.uint8)
fin = Image.fromarray(int_ans)
fin.save('crop_test.png')
0 голосов
/ 13 мая 2018

Я думаю, что вы сделали это почти правильно с первой попытки, во второй вы строите meshgrid для полного изображения, в то время как вы просто хотите маску формы, не так ли?

import numpy as np
import matplotlib as mpl
from matplotlib.path import Path
from matplotlib import patches
import matplotlib.pyplot as plt

from PIL import Image

sar_ver = [(16886, 1085), (15139, 2122), (14475, 5226), (8419, 5601),
           (14046, 6876), (14147, 10079), (16816, 3748), (16886, 1085)]

path = Path(sar_ver)
xmin, ymin, xmax, ymax = np.asarray(path.get_extents(), dtype=int).ravel()

x, y = np.mgrid[xmin:xmax, ymin:ymax]
points = np.transpose((x.ravel(), y.ravel()))

mask = path.contains_points(points)
mask = mask.reshape(x.shape).T

img = Image.fromarray((mask * 255).astype(np.uint8))
img.save('mask.png')


# plot shape and mask for debug purposes
fig = plt.figure(figsize=(8,4))

gs = mpl.gridspec.GridSpec(1,2)
gs.update(wspace=0.2, hspace= 0.01)

ax = plt.subplot(gs[0])
patch = patches.PathPatch(path, facecolor='orange', lw=2)
ax.add_patch(patch)

ax.set_xlim(xmin, xmax)
ax.set_ylim(ymin, ymax)

ax = plt.subplot(gs[1])
ax.imshow(mask, origin='lower')

plt.savefig("shapes.png", bbox_inches="tight", pad_inches=0)

Создает маску:

mask

А также отображает маску и путь для целей отладки:

shapes

Различная ориентация проистекает из разного исходного положения на matplotlib графиках и изображениях, но это должно быть достаточно тривиально, чтобы изменить его так, как вы хотите.

РЕДАКТИРОВАТЬ после последнего редактирования вопроса

Вот обновленный скрипт, который берет изображение, генерирует маску для вашего пути и вырезает его.Я использую фиктивное изображение и немного уменьшаю формы, чтобы с ними было легче работать.

import numpy as np
import matplotlib as mpl
from matplotlib.path import Path
from matplotlib import patches
import matplotlib.pyplot as plt

import skimage.transform
import skimage.data

from PIL import Image

sar_ver = np.asarray([(16886, 1085), (15139, 2122), (14475, 5226), (8419, 5601),
           (14046, 6876), (14147, 10079), (16816, 3748), (16886, 1085)])

# reshape into smaller path for faster debugging
sar_ver = sar_ver // 20

# create dummy image
img = skimage.data.chelsea()
img = skimage.transform.rescale(img, 2)

# matplotlib path
path = Path(sar_ver)
xmin, ymin, xmax, ymax = np.asarray(path.get_extents(), dtype=int).ravel()

# create a mesh grid of the shape of the final mask
x, y = np.mgrid[:img.shape[1], :img.shape[0]]
# mesh grid to points
points = np.vstack((x.ravel(), y.ravel())).T

# mask for the point included in the path
mask = path.contains_points(points)
mask = mask.reshape(x.shape).T

# plots
fig = plt.figure(figsize=(8,6))
gs = mpl.gridspec.GridSpec(2,2)
gs.update(wspace=0.2, hspace= 0.2)

# image + patch
ax = plt.subplot(gs[0])
ax.imshow(img)
patch = patches.PathPatch(path, facecolor="None", edgecolor="cyan", lw=3)
ax.add_patch(patch)

# mask
ax = plt.subplot(gs[1])
ax.imshow(mask)

# filter image with mask
ax = plt.subplot(gs[2])
ax.imshow(img * mask[..., np.newaxis])

# remove mask from image
ax = plt.subplot(gs[3])
ax.imshow(img * ~mask[..., np.newaxis])

# plt.show()
plt.savefig("shapes.png", bbox_inches="tight", pad_inches=0)

cat

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...