计算并绘制分割掩码像素
Calculate and plot segmentation mask pixels
我有以下图片:
下面是此图像中的分割蒙版:
从上图中,我试图计算非零像素坐标。也就是说,我试图获取上面蒙版中实际云的所有像素。当我绘制这些非零像素时,结果是这样的:
我的问题是:为什么上图中绘制的像素与分割蒙版中的像素不一样,我该如何解决?我想从分割蒙版中获取云的像素。
代码:
# create matrix
canvas = np.zeros((img_h, img_w))
# read in image, convert to grayscale, and create mask
im_color = cv2.imread(first_row.path.values[0], cv2.COLOR_BGR2RGB)
im_gray = cv2.cvtColor(im_color, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(im_gray, thresh=110, maxval=255, type=cv2.THRESH_BINARY)
# bounding box coordinates for segmentation mask
ymin, ymax, xmin, xmax = 2, 222, 42, 521
# assign mask to coordinates on canvas
canvas[ymin:ymax,xmin:xmax] = mask[ymin:ymax,xmin:xmax]
y_coords, x_coords = np.where(canvas == 255.0)
# get pixel coordinates of nonzero pixels
pts = np.array(list(zip(x_coords, y_coords)))
# plot original image
fig1 = plt.figure()
ax1 = fig1.add_axes([0,0,1,1])
ax1.set_title('Original image')
plt.imshow(im_color)
# plot segmentation mask on canvas
fig2 = plt.figure()
ax2 = fig2.add_axes([0,0,1,1])
ax2.set_title('Segmentation mask on canvas')
plt.imshow(canvas)
# plot segmentation mask pixels
fig3 = plt.figure()
ax3 = fig3.add_axes([0,0,1,1])
ax3.set_title('Segmentation mask pixel coordinates')
plt.imshow(im_color, interpolation='none')
poly = patches.Polygon(pts)
ax3.add_patch(poly)
plt.show()
您可能正在寻找 matplotlib.pyplot.scatter()
似乎与阈值图像匹配
import cv2
from matplotlib import pyplot as plt
import numpy as np
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 110, 255, cv2.THRESH_BINARY)[1]
x, y = np.where(thresh > 0)
plt.scatter(y[::-1], x)
plt.title('Plot segmentation mask pixels')
plt.show()
添加 @nathancy 的回答并明确回答问题:从分割掩码 计算的像素 确实准确。上面最后一张图中锯齿状的原因是因为掩码中的每个坐标都被绘制为一个(闭合的)多边形,并且所有这些点都是相连的。即多边形的定义:
- "A number of coplanar line segments, each connected end to end to form a closed shape." source
所以最后的图代表一个封闭的多边形,包含来自原始分割掩码的每个 pixel/coordinate。
要生成准确的多边形形状,您需要从蒙版中找到(任何可能的)轮廓的顶点。示例:
# set up canvas for mask
mask = np.zeros((img_h, img_w), dtype=np.uint8)
# assign specific region to mask
mask[ymin:ymax,xmin:xmax] = 1
# read in image
im_color = cv2.imread(path, cv2.IMREAD_COLOR)
# convert image to grayscale
im_gray = cv2.cvtColor(im_color, cv2.COLOR_BGR2GRAY)
# create threshold of image
_, thresh = cv2.threshold(im_gray, thresh=100, maxval=255, type=cv2.THRESH_BINARY)
# create segmentation mask of thresholded image
masked_gray = cv2.bitwise_and(thresh, thresh, mask = mask)
# calculate contours of segmentation mask
contours, hierarchy = cv2.findContours(masked_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# get largest contour
tc = max(contours, key=len)
# plot contours
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.set_title('Segmentation mask')
plt.imshow(masked_gray, interpolation='none')
poly = patches.Polygon(tc[:,0])
ax.add_patch(poly)
plt.show()
结果:
我有以下图片:
下面是此图像中的分割蒙版:
从上图中,我试图计算非零像素坐标。也就是说,我试图获取上面蒙版中实际云的所有像素。当我绘制这些非零像素时,结果是这样的:
我的问题是:为什么上图中绘制的像素与分割蒙版中的像素不一样,我该如何解决?我想从分割蒙版中获取云的像素。
代码:
# create matrix
canvas = np.zeros((img_h, img_w))
# read in image, convert to grayscale, and create mask
im_color = cv2.imread(first_row.path.values[0], cv2.COLOR_BGR2RGB)
im_gray = cv2.cvtColor(im_color, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(im_gray, thresh=110, maxval=255, type=cv2.THRESH_BINARY)
# bounding box coordinates for segmentation mask
ymin, ymax, xmin, xmax = 2, 222, 42, 521
# assign mask to coordinates on canvas
canvas[ymin:ymax,xmin:xmax] = mask[ymin:ymax,xmin:xmax]
y_coords, x_coords = np.where(canvas == 255.0)
# get pixel coordinates of nonzero pixels
pts = np.array(list(zip(x_coords, y_coords)))
# plot original image
fig1 = plt.figure()
ax1 = fig1.add_axes([0,0,1,1])
ax1.set_title('Original image')
plt.imshow(im_color)
# plot segmentation mask on canvas
fig2 = plt.figure()
ax2 = fig2.add_axes([0,0,1,1])
ax2.set_title('Segmentation mask on canvas')
plt.imshow(canvas)
# plot segmentation mask pixels
fig3 = plt.figure()
ax3 = fig3.add_axes([0,0,1,1])
ax3.set_title('Segmentation mask pixel coordinates')
plt.imshow(im_color, interpolation='none')
poly = patches.Polygon(pts)
ax3.add_patch(poly)
plt.show()
您可能正在寻找 matplotlib.pyplot.scatter()
似乎与阈值图像匹配
import cv2
from matplotlib import pyplot as plt
import numpy as np
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 110, 255, cv2.THRESH_BINARY)[1]
x, y = np.where(thresh > 0)
plt.scatter(y[::-1], x)
plt.title('Plot segmentation mask pixels')
plt.show()
添加 @nathancy 的回答并明确回答问题:从分割掩码 计算的像素 确实准确。上面最后一张图中锯齿状的原因是因为掩码中的每个坐标都被绘制为一个(闭合的)多边形,并且所有这些点都是相连的。即多边形的定义:
- "A number of coplanar line segments, each connected end to end to form a closed shape." source
所以最后的图代表一个封闭的多边形,包含来自原始分割掩码的每个 pixel/coordinate。
要生成准确的多边形形状,您需要从蒙版中找到(任何可能的)轮廓的顶点。示例:
# set up canvas for mask
mask = np.zeros((img_h, img_w), dtype=np.uint8)
# assign specific region to mask
mask[ymin:ymax,xmin:xmax] = 1
# read in image
im_color = cv2.imread(path, cv2.IMREAD_COLOR)
# convert image to grayscale
im_gray = cv2.cvtColor(im_color, cv2.COLOR_BGR2GRAY)
# create threshold of image
_, thresh = cv2.threshold(im_gray, thresh=100, maxval=255, type=cv2.THRESH_BINARY)
# create segmentation mask of thresholded image
masked_gray = cv2.bitwise_and(thresh, thresh, mask = mask)
# calculate contours of segmentation mask
contours, hierarchy = cv2.findContours(masked_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# get largest contour
tc = max(contours, key=len)
# plot contours
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.set_title('Segmentation mask')
plt.imshow(masked_gray, interpolation='none')
poly = patches.Polygon(tc[:,0])
ax.add_patch(poly)
plt.show()
结果: