pysdic.compute_optical_flow#
- compute_optical_flow(image1, image2, channel=0, estimate_flow_x=None, estimate_flow_y=None, region=None, disflow_params=None)[source]#
Compute the optical flow between two images using the DIS method of
OpenCV.The optical flow is computed between two images using the Dense Inverse Search (DIS) algorithm implemented in OpenCV. The function allows selecting a specific channel from multi-channel images and provides options to customize the DIS algorithm through a parameters dictionary.
Lets consider two images \(I_1\) and \(I_2\) of shape \((H, W)\). The optical flow is represented as two 2D arrays \(F_x\) and \(F_y\), each of shape \((H, W)\), where \(F_x[i, j]\) and \(F_y[i, j]\) denote the horizontal and vertical displacements (in pixels) of the pixel located at \((i, j)\) in the first image to its corresponding position in the second image.
\[I_2(i + F_y[i, j], j + F_x[i, j]) \approx I_1(i, j)\]With image array indices \(i\) and \(j\) representing the row (vertical) and column (horizontal) indices, respectively.
Note
The method convert the images data to uint8 before processing, as required by OpenCV’s DIS optical flow implementation.
The method convert the estimated flow to float32, as required by OpenCV’s DIS optical flow implementation.
The
disflow_paramsdictionary can contain the following keys:"FinestScale":int(default:0) - The finest scale to use in the image pyramid."VariationalRefinementAlpha":float(default:1) - Weight for the smoothness term in the variational refinement."VariationalRefinementDelta":float(default:1) - Weight for the data term in the variational refinement."VariationalRefinementGamma":float(default:1) - Weight for the gradient constancy term in the variational refinement."VariationalRefinementEpsilon":float(default:0.02) – Small constant to avoid division by zero in the variational refinement."VariationalRefinementIterations":int(default:10) - Number of iterations for the variational refinement."UseMeanNormalization":bool(default:True) - Whether to use mean normalization."GradientDescentIterations":int(default:500) - Number of gradient descent iterations."UseSpatialPropagation":bool(default:True) - Whether to use spatial propagation."PatchSize":int(default:50) - Size of the patches."PatchStride":int(default:10) - Stride between patches.
Warning
xandycomponents of the optical flow are defined in image coordinates and not in array indices. This means that the x-component corresponds to the horizontal displacement (columns) and the y-component corresponds to the vertical displacement (rows).The optical flow is compute with
numpy.uint8images, so the input images will be scaled to fit into the range ofnumpy.uint8if they are of a different unsigned integer type. The output flow will be in pixels and can be positive or negative depending on the direction of motion.
- Parameters:
image1 (ArrayLike) – The first image with shape \((H, W)\) or \((H, W, C)\) where \(C\) is the number of channels. The image must be unsigned integer type.
image2 (ArrayLike) – The second image with shape \((H, W)\) or \((H, W, C)\) where \(C\) is the number of channels. The image must be unsigned integer type.
channel (Integral, optional) – The channel of the images to use for optical flow computation. Default is 0.
estimate_flow_x (Optional[ArrayLike], optional) – An initial estimate for the x-component of the optical flow with shape \((H, W)\). Default is None.
estimate_flow_y (Optional[ArrayLike], optional) – An initial estimate for the y-component of the optical flow with shape \((H, W)\). Default is None.
region (Optional[Tuple[Integral, Integral, Integral, Integral]], optional) – A tuple specifying the region of interest in the format (x, y, width, height). If None, the entire image is computed. Default is None.
disflow_params (Optional[Dict[str, Any]], optional) – Parameters for the DIS optical flow algorithm. See above for details. Default is None.
- Returns:
flow_x (
numpy.ndarray) – The x-component of the optical flow (horizontal displacement) in pixels with shape \((H, W)\). The pixels outside the specified region (if any) will be set tonumpy.nan.flow_y (
numpy.ndarray) – The y-component of the optical flow (vertical displacement) in pixels with shape \((H, W)\). The pixels outside the specified region (if any) will be set tonumpy.nan.
- Raises:
ValueError – If the input images do not have the same shape or if the specified channel is out of bounds. If the input images are not 2D or 3D arrays or not unsigned integer type.
TypeError – If the input images are not of type
numpy.ndarrayor if the specified channel is not an integer. If the disflow_params is not a dictionary.
- Return type:
See also
display_optical_flow()Display the optical flow overlaid on the given image using Matplotlib.
Examples
Create two example images and compute the optical flow between them.
Lena texture image used for the example.#
1import numpy 2from pysdic import compute_optical_flow 3from pysdic import get_lena_texture 4 5# Create two example images 6image1 = get_lena_texture() # numpy array of shape (474, 474) 7 8# Shift the image to create a second image 9image2 = numpy.roll(image1, shift=5, axis=1) # Shift right by 5 pixels 10image2 = numpy.roll(image2, shift=3, axis=0) # Shift down by 3 pixels 11 12# Compute optical flow 13flow_x, flow_y = compute_optical_flow(image1, image2) 14 15# Check if all flow values in the center of the image are approximately (5, 3) 16valid_x = numpy.isclose(flow_x[100:300, 100:300], 5, atol=0.5) 17valid_y = numpy.isclose(flow_y[100:300, 100:300], 3, atol=0.5) 18valid = valid_x & valid_y 19assert valid.all(), "Flow values in the center of the image should be approximately (5, 3)"