i have the following problem: I would like to extract a 1D profile from a 2D array, which is relatively simple. And it is also easy to do this in an arbitrary direction (see here).
But i would like to give the profile a certain width, so that the values perpendicular to the profile are averaged. I managed to do this, but it is extremely slow. Does anyone have a good solution for that?
Thanks!
import numpy as np
import os
import math
import itertools
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
def 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_distances
def 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_points
def 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 data
from scipy.misc import face
img = face(gray=True)
profile = averaged_profile(img, 10, 10, 500, 500, 10)