Sem*_*ken 7 python opencv numpy image-processing contour
VI 在图像上绘制了一组轮廓点,并将其存储为 2D numpy 数组。轮廓由 2 个 numpy 数组表示,每个数组的 x 和 y 坐标为浮点值。这些坐标不是整数,并且不能与像素完美对齐,但它们确实可以告诉您轮廓点相对于像素的位置。
我希望能够选择轮廓内的像素。我编写了一些与此处给出的答案几乎相同的代码:使用 Python 中的 OpenCV 在轮廓边界内访问像素值
temp_list = []
for a, b in zip(x_pixel_nos, y_pixel_nos):
    temp_list.append([[a, b]]) # 2D array of shape 1x2
temp_array = np.array(temp_list)
contour_array_list = []
contour_array_list.append(temp_array)
lst_intensities = []
# For each list of contour points...
for i in range(len(contour_array_list)):
    # Create a mask image that contains the contour filled in
    cimg = np.zeros_like(pixel_array)
    cv2.drawContours(cimg, contour_array_list, i, color=255, thickness=-1)
# Access the image pixels and create a 1D numpy array then add to list
pts = np.where(cimg == 255)
lst_intensities.append(pixel_array[pts[0], pts[1]])
Run Code Online (Sandbox Code Playgroud)
当我运行这个时,我收到一个错误error: OpenCV(3.4.1) /opt/conda/conda-bld/opencv-suite_1527005509093/work/modules/imgproc/src/drawing.cpp:2515: error: (-215) npoints > 0 in function drawContours
我猜测此时 openCV 对我不起作用,因为我的轮廓是浮点数,而不是整数,而 openCV 无法处理它drawContours。如果我将轮廓的坐标转换为整数,则会损失很多精度。
那么如何获取轮廓内的像素呢?
这应该是一项微不足道的任务,但到目前为止我还没有找到一种简单的方法来完成它。
我认为查找落在轮廓内的所有像素的最简单方法如下。
轮廓由一组非整数点描述。我们可以把这些点看成一个多边形的顶点,轮廓就是一个多边形。
我们首先找到多边形的边界框。此边界框外部的任何像素都不在多边形内部,因此不需要考虑。
对于边界框内的像素,我们使用经典测试来测试它们是否在多边形内部:从无穷远的某个点到该点追踪一条线,并计算穿过的多边形边(线段)的数量。如果这个数字是奇数,则该点位于多边形内部。事实证明,Matplotlib包含该算法的非常有效的实现。
我还在习惯 Python 和 Numpy,如果您是 Python 专家,这可能会有点尴尬。但我认为它的作用很简单。首先,它计算多边形的边界框,然后创建一个数组,其中points包含落在该边界框内的所有像素的坐标(我假设像素质心才是最重要的)。它将该matplotlib.path.contains_points方法应用于该数组,生成一个布尔数组mask。最后,它重塑该数组以匹配边界框。
import math
import matplotlib.path
import numpy as np
x_pixel_nos = [...]
y_pixel_nos = [...] # Data from https://gist.github.com/sdoken/173fae1f9d8673ffff5b481b3872a69d
temp_list = []
for a, b in zip(x_pixel_nos, y_pixel_nos):
   temp_list.append([a, b])
polygon = np.array(temp_list)
left = np.min(polygon, axis=0)
right = np.max(polygon, axis=0)
x = np.arange(math.ceil(left[0]), math.floor(right[0])+1)
y = np.arange(math.ceil(left[1]), math.floor(right[1])+1)
xv, yv = np.meshgrid(x, y, indexing='xy')
points = np.hstack((xv.reshape((-1,1)), yv.reshape((-1,1))))
path = matplotlib.path.Path(polygon)
mask = path.contains_points(points)
mask.shape = xv.shape
Run Code Online (Sandbox Code Playgroud)
在此代码之后,需要找到图像内的边界框,并为像素着色。left包含图像中与 的左上角像素相对应的像素mask。
可以提高该算法的性能。如果用于测试像素的光线追踪是水平的,您可以想象沿水平线的所有像素都可以从左侧像素所做的工作中受益。也就是说,可以比单个像素的成本多一点点来计算图像线上所有像素的输入/输出状态。
该matplotlib.path.contains_points算法比对所有点执行单点测试要高效得多,因为对多边形边和顶点进行适当排序使每次测试成本更低,并且在一次测试多个点时只需要进行一次排序。但这个算法没有考虑到我们想要测试同一条线上的许多点。
这些是我做事时看到的
pp.plot(x_pixel_nos, y_pixel_nos)
pp.imshow(mask)
Run Code Online (Sandbox Code Playgroud)
使用您的数据运行上面的代码后。请注意,y 轴与 反转imshow,因此形状呈垂直镜像。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           13795 次  |  
        
|   最近记录:  |