Skip to content

Instantly share code, notes, and snippets.

@Yu-AnChen
Last active April 17, 2021 00:20
Show Gist options
  • Save Yu-AnChen/df6fa2cb99fde8514f8e7cbe72e6296e to your computer and use it in GitHub Desktop.
Save Yu-AnChen/df6fa2cb99fde8514f8e7cbe72e6296e to your computer and use it in GitHub Desktop.
Approximate objects in a binary image with polygon outline using opencv
import cv2
import matplotlib.patches as mpatches
import copy
import numpy as np
import matplotlib.pyplot as plt
def binary_to_patches(binary_img):
assert np.unique(binary_img).shape[0] == 2, \
'Input image must be a binary image'
contours, _ = cv2.findContours(
binary_img.astype(np.uint8),
cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE
)
verts = [
c.reshape(c.shape[0], c.shape[-1])
for c in contours
]
patches = [
mpatches.Polygon(p, closed=True, facecolor='none')
for p in verts
]
return patches
test_img = np.zeros((200, 400))
test_img[0, 150] = 1
gradient_img = cv2.GaussianBlur(test_img, (0, 0), 50)
steps = np.linspace(gradient_img.min(), gradient_img.max(), num=10)
patches = []
masks = []
for low, high in zip(steps[:-1], steps[1:]):
mask = np.logical_and(gradient_img >= low, gradient_img < high)
masks.append(mask)
patch = binary_to_patches(mask)
patches.append(patch)
fig, axs = plt.subplots(2, 1)
axs[0].imshow(
np.sum([idx * m for idx, m in enumerate(masks)], axis=0)
)
axs[1].imshow(gradient_img)
for idx, level in enumerate(patches):
for p in level:
cp_p = copy.copy(p)
color_channel = 1 - (idx / len(patches))
cp_p.set_edgecolor((color_channel,)*3)
axs[1].add_patch(cp_p)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment