如何使用 python 在 opencv 中包围不规则图形轮廓并用 5px 点填充它?
How to enclose the irregular figure contour and fill it with with 5px dots in opencv using python?
这是我的
我想要这个
但问题是我无法包围轮廓,我应该如何添加这些点?
Open cv 有没有这样的功能来处理这个?
所以基本上,
第一个问题是如何封装这个图像
二、如何加点。
谢谢
这是 Python/OpenCV 中的一种方法。但是,如果不连接单独的区域,我无法关闭您的虚线轮廓。但它会给你一些想法如何继续你想做的大部分事情。
如果您在输入图像中有较大间隙的地方手动添加更多的点,则形态内核可以变小,这样它就可以连接区域而不合并应该保持隔离的单独部分。
- 读取输入
- 转换为灰度
- 二进制的阈值
- 应用形态学关闭来尝试关闭虚线轮廓。不幸的是,它连接了不同的区域。
- 获取外部轮廓
- 在黑色背景上绘制白色填充轮廓作为蒙版
- 在白色背景上画一个黑色圆圈
- 将圆形图像平铺到输入的大小
- 用填充的轮廓图像遮盖平铺的圆形图像
- 保存结果
输入:
import cv2
import numpy as np
import math
# read input image
img = cv2.imread('island.png')
hh, ww = img.shape[:2]
# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
# use morphology to close figure
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (35,35))
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, )
# find contours and bounding boxes
mask = np.zeros_like(thresh)
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:
cv2.drawContours(mask, [cntr], 0, 255, -1)
# create a single tile as black circle on white background
circle = np.full((11,11), 255, dtype=np.uint8)
circle = cv2.circle(circle, (7,7), 3, 0, -1)
# tile out the tile pattern to the size of the input
numht = math.ceil(hh / 11)
numwd = math.ceil(ww / 11)
tiled_circle = np.tile(circle, (numht,numwd))
tiled_circle = tiled_circle[0:hh, 0:ww]
# composite tiled_circle with mask
result = cv2.bitwise_and(tiled_circle, tiled_circle, mask=mask)
# save result
cv2.imwrite("island_morph.jpg", morph)
cv2.imwrite("island_mask.jpg", mask)
cv2.imwrite("tiled_circle.jpg", tiled_circle)
cv2.imwrite("island_result.jpg", result)
# show images
cv2.imshow("morph", morph)
cv2.imshow("mask", mask)
cv2.imshow("tiled_circle", tiled_circle)
cv2.imshow("result", result)
cv2.waitKey(0)
形态学连接图像:
轮廓蒙版图像:
平铺圆圈:
结果:
这是我的
我想要这个
但问题是我无法包围轮廓,我应该如何添加这些点? Open cv 有没有这样的功能来处理这个? 所以基本上, 第一个问题是如何封装这个图像 二、如何加点。
谢谢
这是 Python/OpenCV 中的一种方法。但是,如果不连接单独的区域,我无法关闭您的虚线轮廓。但它会给你一些想法如何继续你想做的大部分事情。
如果您在输入图像中有较大间隙的地方手动添加更多的点,则形态内核可以变小,这样它就可以连接区域而不合并应该保持隔离的单独部分。
- 读取输入
- 转换为灰度
- 二进制的阈值
- 应用形态学关闭来尝试关闭虚线轮廓。不幸的是,它连接了不同的区域。
- 获取外部轮廓
- 在黑色背景上绘制白色填充轮廓作为蒙版
- 在白色背景上画一个黑色圆圈
- 将圆形图像平铺到输入的大小
- 用填充的轮廓图像遮盖平铺的圆形图像
- 保存结果
输入:
import cv2
import numpy as np
import math
# read input image
img = cv2.imread('island.png')
hh, ww = img.shape[:2]
# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
# use morphology to close figure
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (35,35))
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, )
# find contours and bounding boxes
mask = np.zeros_like(thresh)
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:
cv2.drawContours(mask, [cntr], 0, 255, -1)
# create a single tile as black circle on white background
circle = np.full((11,11), 255, dtype=np.uint8)
circle = cv2.circle(circle, (7,7), 3, 0, -1)
# tile out the tile pattern to the size of the input
numht = math.ceil(hh / 11)
numwd = math.ceil(ww / 11)
tiled_circle = np.tile(circle, (numht,numwd))
tiled_circle = tiled_circle[0:hh, 0:ww]
# composite tiled_circle with mask
result = cv2.bitwise_and(tiled_circle, tiled_circle, mask=mask)
# save result
cv2.imwrite("island_morph.jpg", morph)
cv2.imwrite("island_mask.jpg", mask)
cv2.imwrite("tiled_circle.jpg", tiled_circle)
cv2.imwrite("island_result.jpg", result)
# show images
cv2.imshow("morph", morph)
cv2.imshow("mask", mask)
cv2.imshow("tiled_circle", tiled_circle)
cv2.imshow("result", result)
cv2.waitKey(0)
形态学连接图像:
轮廓蒙版图像:
平铺圆圈:
结果: