打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
python – 如何从任意方向的2D数组中提取1d轮廓(具有集成宽度)

我有以下问题:我想从2D数组中提取一维配置文件,这是相对简单的.并且在任意方向上也很容易做到这一点(见here).

但我想给轮廓一定的宽度,以便垂直于轮廓的值被平均.我设法做到了这一点,但速度非常慢.
有人有一个很好的解决方案吗?

谢谢!

import numpy as npimport osimport mathimport itertoolsimport matplotlib.pyplot as pltfrom matplotlib.patches import Polygondef closest_point(points, coords):    min_distances = []    coords = coords    for point in points:        distances = []        for coord in coords:            distances.append(np.sqrt((point[0]-coord[0])**2   (point[1]-coord[1])**2))        val, idx = min((val, idx) for (idx, val) in enumerate(distances))        min_distances.append(coords[idx])    return min_distancesdef rect_profile(x0, y0, x1, y1, width):    xd=x1-x0    yd=y1-y0    alpha = (np.angle(xd 1j*yd))    y00 = y0 - np.cos(math.pi - alpha)*width    x00 = x0 - np.sin(math.pi - alpha)*width    y01 = y0   np.cos(math.pi - alpha)*width    x01 = x0   np.sin(math.pi - alpha)*width    y10 = y1   np.cos(math.pi - alpha)*width    x10 = x1   np.sin(math.pi - alpha)*width    y11 = y1 - np.cos(math.pi - alpha)*width    x11 = x1 - np.sin(math.pi - alpha)*width    vertices = ((y00, x00), (y01, x01), (y10, x10), (y11, x11))    poly_points = [x00, x01, x10, x11], [y00, y01, y10, y11]    poly = Polygon(((y00, x00), (y01, x01), (y10, x10), (y11, x11)))    return poly, poly_pointsdef averaged_profile(image, x0, y0, x1, y1, width):    num = np.sqrt((x1-x0)**2   (y1-y0)**2)    x, y = np.linspace(x0, x1, num), np.linspace(y0, y1, num)    coords = list(zip(x, y))    # Get all points that are in Rectangle    poly, poly_points = rect_profile(x0, y0, x1, y1, width)    points_in_poly = []    for point in itertools.product(range(image.shape[0]), range(image.shape[1])):        if poly.get_path().contains_point(point, radius=1) == True:            points_in_poly.append((point[1], point[0]))    # Finds closest point on line for each point in poly    neighbour = closest_point(points_in_poly, coords)    # Add all phase values corresponding to closest point on line    data = []    for i in range(len(coords)):        data.append([])    for idx in enumerate(points_in_poly):        index = coords.index(neighbour[idx[0]])        data[index].append(image[idx[1][1], idx[1][0]])    # Average data perpendicular to profile    for i in enumerate(data):        data[i[0]] = np.nanmean(data[i[0]])    # Plot    fig, axes = plt.subplots(figsize=(10, 5), nrows=1, ncols=2)    axes[0].imshow(image)    axes[0].plot([poly_points[0][0], poly_points[0][1]], [poly_points[1][0], poly_points[1][1]], 'yellow')    axes[0].plot([poly_points[0][1], poly_points[0][2]], [poly_points[1][1], poly_points[1][2]], 'yellow')    axes[0].plot([poly_points[0][2], poly_points[0][3]], [poly_points[1][2], poly_points[1][3]], 'yellow')    axes[0].plot([poly_points[0][3], poly_points[0][0]], [poly_points[1][3], poly_points[1][0]], 'yellow')    axes[0].axis('image')    axes[1].plot(data)    return datafrom scipy.misc import faceimg = face(gray=True)profile = averaged_profile(img, 10, 10, 500, 500, 10)

解决方法:

主要的性能值是函数nearest_point.使用矩形中的所有点计算线上所有点之间的距离非常慢.

通过将所有矩形点投影到线上,可以大大加快功能.投影点是线上最近的点,因此无需计算所有距离.此外,通过正确地标准化和舍入投影(距线开始的距离),它可以直接用作索引.

def closest_point(points, x0, y0, x1, y1):    line_direction = np.array([x1 - x0, y1 - y0], dtype=float)    line_length = np.sqrt(line_direction[0]**2   line_direction[1]**2)    line_direction /= line_length    n_bins = int(np.ceil(line_length))    # project points on line    projections = np.array([(p[0] * line_direction[0]   p[1] * line_direction[1]) for p in points])    # normalize projections so that they can be directly used as indices    projections -= np.min(projections)    projections *= (n_bins - 1) / np.max(projections)    return np.floor(projections).astype(int), n_bins

如果你想知道括号内的奇怪 – 这些是list comprehensions.

在averaged_profile中使用这样的函数:

#...# Finds closest point on line for each point in polyneighbours, n_bins = closest_point(points_in_poly, x0, y0, x1, y1)# Add all phase values corresponding to closest point on linedata = [[] for _ in range(n_bins)]for idx in enumerate(points_in_poly):    index = neighbours[idx[0]]    data[index].append(image[idx[1][1], idx[1][0]])#...

这种优化将使计算速度明显加快.如果它对您来说仍然太慢,您还可以优化在多边形内找到点的方式.不是测试图像中的每个点是否在矩形内,您可以使用多边形光栅化算法直接生成坐标.有关详情,请参阅here.

最后,虽然它不是性能问题,但使用复数计算角度非常有创意:)
除了三角函数,您可以使用线的法线向量是[yd,-xd]除以线长度的事实:

def rect_profile(x0, y0, x1, y1, width):    xd = x1 - x0    yd = y1 - y0    length = np.sqrt(xd**2   yd**2)    y00 = y0   xd * width / length    x00 = x0 - xd * width / length    y01 = y0 - xd * width / length    x01 = x0   xd * width / length    y10 = y1 - xd * width / length    x10 = x1   xd * width / length    y11 = y1   xd * width / length    x11 = x1 - xd * width / length    poly_points = [x00, x01, x10, x11], [y00, y01, y10, y11]    poly = Polygon(((y00, x00), (y01, x01), (y10, x10), (y11, x11)))    return poly, poly_points
来源:https://www.icode9.com/content-1-303951.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
图像坐标空间变换:透视变换(Perspective Transformation),或称为单应性(Homography)变换
第92天:Python Matplotlib 进阶操作
用python搞点“心”东西
用动态存储分配代替大块静态存储分配 ————用指针代替大数组
图注意力网络入门:从数学理论到到NumPy实现
PVGeo-Examples 2.1 - Loading-Shapefiles-To-VTK
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服