public final class

CoordinateTransform

extends java.lang.Object

 java.lang.Object

↳androidx.camera.view.transform.CoordinateTransform

Gradle dependencies

compile group: 'androidx.camera', name: 'camera-view', version: '1.2.0-alpha01'

  • groupId: androidx.camera
  • artifactId: camera-view
  • version: 1.2.0-alpha01

Artifact androidx.camera:camera-view:1.2.0-alpha01 it located at Google repository (https://maven.google.com/)

Overview

This class represents the transform from one OutputTransform to another.

This class can be used to map the coordinates of one OutputTransform to another, given that they are associated with the same ViewPort. OutputTransform can represent the output of a UseCase or PreviewView. For example, mapping the coordinates of detected objects from ImageAnalysis output to the drawing location in PreviewView.


 // imageProxy the output of an ImageAnalysis.
 OutputTransform source = ImageProxyTransformFactory().getOutputTransform(imageProxy);
 OutputTransform target = previewView.getOutputTransform();

 // Build the transform from ImageAnalysis to PreviewView
 CoordinateTransform coordinateTransform = new CoordinateTransform(source, target);

 // Detect face in ImageProxy and transform the coordinates to PreviewView.
 // The value of faceBox can be used to highlight the face in PreviewView.
 RectF faceBox = detectFaceInImageProxy(imageProxy);
 coordinateTransform.mapRect(faceBox);

 

Summary

Constructors
publicCoordinateTransform(OutputTransform source, OutputTransform target)

Creates the transform between the source and the target.

Methods
public voidmapPoint(PointF point)

Apply this transform to the , and write the transformed points back into the array

public voidmapPoints(float[] points[])

Apply this transform to the array of 2D points, and write the transformed points back into the array

public voidmapRect(RectF rect)

Apply this transform to the rectangle, and write the transformed rectangle back into it.

public voidtransform(Matrix outMatrix)

Copies the current transform to the specified .

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public CoordinateTransform(OutputTransform source, OutputTransform target)

Creates the transform between the source and the target.

The source and the target must be associated with the same ViewPort.

Parameters:

source: the source

See also: UseCaseGroup, ViewPort

Methods

public void transform(Matrix outMatrix)

Copies the current transform to the specified .

Parameters:

outMatrix: a in which to copy the current transform.

public void mapPoints(float[] points[])

Apply this transform to the array of 2D points, and write the transformed points back into the array

Parameters:

points: The array [x0, y0, x1, y1, ...] of points to transform.

See also:

public void mapPoint(PointF point)

Apply this transform to the , and write the transformed points back into the array

Parameters:

point: The point to transform.

public void mapRect(RectF rect)

Apply this transform to the rectangle, and write the transformed rectangle back into it. This is accomplished by transforming the 4 corners of rect, and then setting it to the bounds of those points.

Parameters:

rect: The rectangle to transform.

Source

/*
 * Copyright 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.camera.view.transform;

import static androidx.camera.view.TransformUtils.isAspectRatioMatchingWithRoundingError;

import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.Logger;
import androidx.camera.core.UseCase;
import androidx.camera.core.UseCaseGroup;
import androidx.camera.core.ViewPort;
import androidx.camera.view.PreviewView;
import androidx.camera.view.TransformExperimental;
import androidx.core.util.Preconditions;

/**
 * This class represents the transform from one {@link OutputTransform} to another.
 *
 * <p> This class can be used to map the coordinates of one {@link OutputTransform} to another,
 * given that they are associated with the same {@link ViewPort}. {@link OutputTransform} can
 * represent the output of a {@link UseCase} or {@link PreviewView}. For example, mapping the
 * coordinates of detected objects from {@link ImageAnalysis} output to the drawing location in
 * {@link PreviewView}.
 *
 * <pre><code>
 * // imageProxy the output of an ImageAnalysis.
 * OutputTransform source = ImageProxyTransformFactory().getOutputTransform(imageProxy);
 * OutputTransform target = previewView.getOutputTransform();
 *
 * // Build the transform from ImageAnalysis to PreviewView
 * CoordinateTransform coordinateTransform = new CoordinateTransform(source, target);
 *
 * // Detect face in ImageProxy and transform the coordinates to PreviewView.
 * // The value of faceBox can be used to highlight the face in PreviewView.
 * RectF faceBox = detectFaceInImageProxy(imageProxy);
 * coordinateTransform.mapRect(faceBox);
 *
 * </code></pre>
 */
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
@TransformExperimental
public final class CoordinateTransform {

    private static final String TAG = "CoordinateTransform";
    private static final String MISMATCH_MSG = "The source viewport (%s) does not match the target "
            + "viewport (%s). Please make sure they are associated with the same Viewport.";

    private final Matrix mMatrix;

    /**
     * Creates the transform between the {@code source} and the {@code target}.
     *
     * <p> The source and the target must be associated with the same {@link ViewPort}.
     *
     * @param source the source
     * @see UseCaseGroup
     * @see ViewPort
     */
    public CoordinateTransform(@NonNull OutputTransform source,
            @NonNull OutputTransform target) {
        // TODO(b/137515129): This is a poor way to check if the two outputs are based on
        //  the same viewport. A better way is to add a matrix in use case output that represents
        //  the transform from sensor to surface. But it will require the view artifact to
        //  depend on a new internal API in the core artifact, which we can't do at the
        //  moment because of the version mismatch between view and core.
        if (!isAspectRatioMatchingWithRoundingError(
                source.getViewPortSize(), /* isAccurate1= */ false,
                target.getViewPortSize(), /* isAccurate2= */ false)) {
            // Mismatched aspect ratio means the outputs are not associated with the same Viewport.
            Logger.w(TAG, String.format(MISMATCH_MSG, source.getViewPortSize(),
                    target.getViewPortSize()));
        }

        // Concatenate the source transform with the target transform.
        mMatrix = new Matrix();
        Preconditions.checkState(source.getMatrix().invert(mMatrix),
                "The source transform cannot be inverted");
        mMatrix.postConcat(target.getMatrix());
    }

    /**
     * Copies the current transform to the specified {@link Matrix}.
     *
     * @param outMatrix a {@link android.graphics.Matrix} in which to copy the current transform.
     */
    public void transform(@NonNull Matrix outMatrix) {
        outMatrix.set(mMatrix);
    }

    /**
     * Apply this transform to the array of 2D points, and write the transformed points back into
     * the array
     *
     * @param points The array [x0, y0, x1, y1, ...] of points to transform.
     * @see Matrix#mapPoints(float[])
     */
    public void mapPoints(@NonNull float[] points) {
        mMatrix.mapPoints(points);
    }

    /**
     * Apply this transform to the {@link PointF}, and write the transformed points back into
     * the array
     *
     * @param point The point to transform.
     */
    public void mapPoint(@NonNull PointF point) {
        float[] pointArray = new float[]{point.x, point.y};
        mMatrix.mapPoints(pointArray);
        point.x = pointArray[0];
        point.y = pointArray[1];
    }

    /**
     * Apply this transform to the rectangle, and write the transformed rectangle back into it.
     * This is accomplished by transforming the 4 corners of rect, and then setting it to the
     * bounds of those points.
     *
     * @param rect The rectangle to transform.
     */
    public void mapRect(@NonNull RectF rect) {
        mMatrix.mapRect(rect);
    }
}