如何使用实时贴纸制作自定义相机

Posted

技术标签:

【中文标题】如何使用实时贴纸制作自定义相机【英文标题】:How to make a custom Camera with live Stickers 【发布时间】:2017-03-20 10:20:01 【问题描述】:

我正在制作一个带有人脸检测功能的自定义相机,效果很好。

但我想在录制/预览的面孔上添加贴纸。 眼睛的位置用于在预览中正确调整和放置帽子、眼镜和领带等。

使用 FaceOverlayView 进行人脸检测

public class FaceOverlayView extends View 
    private Paint mPaint;
    private Paint mTextPaint;
    private int mDisplayOrientation;
    private int mOrientation;
    private Face[] mFaces;

    public FaceOverlayView(Context context) 
        super(context);
        initialize();
    

    private void initialize() 
        // We want a green box around the face:
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.GREEN);
        mPaint.setAlpha(128);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setDither(true);
        mTextPaint.setTextSize(20);
        mTextPaint.setColor(Color.GREEN);
        mTextPaint.setStyle(Paint.Style.FILL);
    

    public void setFaces(Face[] faces) 
        mFaces = faces;
        invalidate();
    

    public void setOrientation(int orientation) 
        mOrientation = orientation;
    

    public void setDisplayOrientation(int displayOrientation) 
        mDisplayOrientation = displayOrientation;
        invalidate();
    

    @Override
    protected void onDraw(Canvas canvas) 
        super.onDraw(canvas);
        if (mFaces != null && mFaces.length > 0) 
            Matrix matrix = new Matrix();
            Util.prepareMatrix(matrix, false, mDisplayOrientation, getWidth(), getHeight());
            canvas.save();
            matrix.postRotate(mOrientation);
            canvas.rotate(-mOrientation);
            RectF rectF = new RectF();
            for (Face face : mFaces) 
                rectF.set(face.rect);
                matrix.mapRect(rectF);
                canvas.drawRect(rectF, mPaint);
                canvas.drawText("Score " + face.score, rectF.right, rectF.top, mTextPaint);
            
            canvas.restore();
        
    

我想在预览中添加帽子和太阳镜,就像在 Play 商店中一样,Face 28:


更多信息。

我正在使用MoodMeSDK to detect the eyes and mouth

结果是 66 分:

我想在脸上戴上太阳镜、帽子、嘴唇等。在 Face28 APK 中使用 SVG 文件制作面部贴纸。

【问题讨论】:

多么酷的应用程序!没有简单的方法可以在这样的级别上完成这项任务。我相信这个团队使用了比内置的更先进的人脸检测库。 @AlexCohn 谢谢你看那个......我正在搜索那个图书馆或其他一些,但这项任务对我来说并不容易。 显而易见的起点是 OpenCV 项目。 是的@AlexCohn 我正在做这样的事情...... SDK 提供者有官方论坛支持,one related topic already posted。检测到的“地标”点已编号(SDK 为您提供了一个浮点数组)。创建一个顶点(使用 3d 的)覆盖地标的网格,对其应用纹理并将其渲染为 openGL 纹理是微不足道的。 【参考方案1】:

我以前做过类似的事情。所以你需要这样做:首先你需要定位相对于View的Rectangle的点,例如如果你想放置一个帽子,首先根据CameraView定位帽子的头部和相对矩形,然后放置那个坐标上的帽子。这是简单的部分。困难的部分是保存图像。为此,您需要保存 CameraView 的宽度和长度以及其上的贴纸及其在 CameraView 上的位置。然后你捕捉图像并获得一个位图/绘图。对于生成的位图,您很可能会得到与 CameraView 不同的大小,因此您需要根据它与 CameraView 的 w/h 重新计算该位图上贴纸的坐标,并在新坐标上合并贴纸,然后保存。这并不容易,但我做到了。

这是我的代码(在我的例子中,贴纸被放置在图片的中心):

/**
 * Created by Mohammad Erfan Molaei on 9/26/16.
 */
public class CaptureActivity extends AppCompatActivity implements
        ActivityCompat.OnRequestPermissionsResultCallback 
private static final String TAG = "CaptureActivity";


private FloatingActionButton takePicture;

private int mCurrentFlash;

private CameraView mCameraView;

private int cameraWidth;

private int cameraHeight;

private int drawableWidth;

private int drawableHeight;

private Handler mBackgroundHandler;

private boolean selectedBrand;
@Override
public void setTheme(int resId) 
    selectedBrand = getSharedPreferences(getString(R.string.brand_pref), MODE_PRIVATE)
            .getBoolean(getString(R.string.selected_brand), true);
    super.setTheme(selectedBrand ? R.style.AppTheme_CaptureTheme : R.style.AppTheme_CaptureTheme2);


private String itemID = null;

private View.OnClickListener mOnClickListener = new View.OnClickListener() 
    @Override
    public void onClick(View v) 
        switch (v.getId()) 
            case R.id.take_picture:
                if (mCameraView != null) 
                    mCameraView.takePicture();
                    takePicture.setEnabled(false);
                
                break;

            case R.id.scale_up_btn:
                scaleUpImage();
                break;

            case R.id.scale_down_btn:
                scaleDownImage();
                break;
        
    
;

private void scaleUpImage() 
    if (mCameraView != null) 
        SizeAwareImageView imageView = (SizeAwareImageView) mCameraView.findViewById(R.id.mImageView);

        /*Log.e(TAG, "scaleDownImage: oldWidth: " + imageView.getLayoutParams().width +
                ", oldHeight: " + imageView.getLayoutParams().height);
        Log.e(TAG, "scaleDownImage: newWidth2B: " + (imageView.getLayoutParams().width * 1.1f) +
                ", newHeight2B: " + ((1.1f * imageView.getLayoutParams().width) *
                imageView.getLayoutParams().height /
                imageView.getLayoutParams().width));
        Log.e(TAG, "cameraWidth: " + mCameraView.getLayoutParams().width );
sdasd*/
            if (imageView.getWidth() * 1.1f > mCameraView.getWidth() ||
                    ((1.1f * imageView.getWidth()) *
                            imageView.getHeight() /
                            imageView.getWidth()) > mCameraView.getHeight())
                return;



        imageView.getLayoutParams().height = (int) ((1.1f * imageView.getWidth()) *
                imageView.getHeight() /
                imageView.getWidth());
        imageView.getLayoutParams().width = (int) (imageView.getWidth() * 1.1f);

        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.requestLayout();
        /*drawableWidth = dp2px(imageView.getWidth());
        drawableHeight = dp2px(imageView.getHeight());*/

    


private void scaleDownImage() 
    if (mCameraView != null) 
        SizeAwareImageView imageView = (SizeAwareImageView) mCameraView.findViewById(R.id.mImageView);

        if (imageView.getWidth() * 0.9f > mCameraView.getWidth() ||
                ((0.9f * imageView.getWidth()) *
                        imageView.getHeight() /
                        imageView.getWidth()) > mCameraView.getHeight())
            return;



        imageView.getLayoutParams().height = (int) ((0.9f * imageView.getWidth()) *
                imageView.getHeight() /
                imageView.getWidth());
        imageView.getLayoutParams().width = (int) (imageView.getWidth() * 0.9f);

        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.requestLayout();
        /*drawableWidth = dp2px(imageView.getWidth());
        drawableHeight = dp2px(imageView.getHeight());*/

    



private void rotateImage() 
    if (mCameraView != null) 
        SizeAwareImageView imageView = (SizeAwareImageView) mCameraView.findViewById(R.id.mImageView);
        /*Drawable mDrawable = imageView.getDrawable();
        int mDrawableWidth = mDrawable.getBounds().width();
        int mDrawableHeight = mDrawable.getBounds().height();*/

        int newWidth = imageView.getHeight();
        int newHeight = imageView.getWidth();
        float scaleFactor = 1;
        /*Log.e(TAG, "rotateImage: prevWidth: " + newHeight + ", prevHeight: " + newWidth);
        Log.e(TAG, "rotateImage: cameraWidth: " + mCameraView.getWidth() );*/
        if (newWidth > mCameraView.getWidth() ) 
            scaleFactor = (float)newWidth / (float)mCameraView.getWidth();

            newWidth = mCameraView.getWidth();
            newHeight *= scaleFactor;

         else if (newHeight > mCameraView.getHeight() ) 
            scaleFactor = (float)newHeight / (float)mCameraView.getHeight();
            newHeight = mCameraView.getHeight();
            newWidth *= scaleFactor;
        
        Log.e(TAG, "rotateImage: scaleFactor: " + scaleFactor);



        imageView.setRotation(imageView.getRotation() + 90);
        imageView.getLayoutParams().height = newHeight;
        imageView.getLayoutParams().width = newWidth;
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        imageView.requestLayout();
        /*drawableWidth = dp2px(imageView.getWidth());
        drawableHeight = dp2px(imageView.getHeight());*/
        //imageView.setImageDrawable(getRotatedDrawable(imageView));


        /*Bitmap bitmapOrg = drawableToBitmap(imageView.getDrawable());
        // createa matrix for the manipulation
        Matrix matrix = imageView.getImageMatrix();

        int width = bitmapOrg.getWidth();
        int height = bitmapOrg.getHeight();



        // rotate the Bitmap
        matrix.postRotate(90);

        // recreate the new Bitmap
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
                width, height, matrix, true);

        // make a Drawable from Bitmap to allow to set the BitMap
        // to the ImageView, ImageButton or what ever
        BitmapDrawable bmd = new BitmapDrawable(getResources(), resizedBitmap);

        // set the Drawable on the ImageView
        imageView.setImageDrawable(bmd);*/

    


@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_capture);
    mCameraView = (CameraView) findViewById(R.id.camera);
    if (mCameraView != null) 
        mCameraView.addCallback(mCallback);
    
    takePicture = (FloatingActionButton) findViewById(R.id.take_picture);
    if (takePicture != null) 
        takePicture.setOnClickListener(mOnClickListener);
    
    /*if (selectedBrand) 
        assert takePicture != null;
        takePicture.setBackgroundColor(ContextCompat.getColor(getBaseContext(),R.color.colorAccent));
        findViewById(R.id.control).setBackgroundColor(ContextCompat.getColor(getBaseContext(),R.color.colorPrimary));
     else 
        assert takePicture != null;
        takePicture.setBackgroundColor(ContextCompat.getColor(getBaseContext(),R.color.colorAccent2));
        findViewById(R.id.control).setBackgroundColor(ContextCompat.getColor(getBaseContext(),R.color.colorPrimary2));
    */
    findViewById(R.id.scale_up_btn).setOnClickListener(mOnClickListener);
    findViewById(R.id.scale_down_btn).setOnClickListener(mOnClickListener);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) 
        actionBar.setDisplayShowTitleEnabled(false);
    

    if (savedInstanceState == null) 
        Bundle extras = getIntent().getExtras();
        if(extras != null) 
            itemID = extras.getString("id", null);
        
     else 
        itemID = (String) savedInstanceState.getSerializable("id");
    

    if( itemID != null ) 
        new AsyncImageLoader().execute(itemID);

     else 
        this.finish();
        return;
    

    ViewTreeObserver viewTreeObserver = mCameraView.getViewTreeObserver();
    if (viewTreeObserver.isAlive()) 
        viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() 
            @Override
            public void onGlobalLayout() 
                /*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) 
                    mCameraView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                 else 
                    mCameraView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                */
                cameraWidth = dp2px(mCameraView.getWidth());
                cameraHeight = dp2px(mCameraView.getHeight());

                Log.e("camB4Action", "" + cameraWidth + ", " + cameraHeight);
            
        );
    




@Override
protected void onResume() 
    super.onResume();
    mCameraView.start();


@Override
protected void onPause() 
    mCameraView.stop();
    super.onPause();


@Override
protected void onDestroy() 
    super.onDestroy();
    if (mBackgroundHandler != null) 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) 
            mBackgroundHandler.getLooper().quitSafely();
         else 
            mBackgroundHandler.getLooper().quit();
        
        mBackgroundHandler = null;
    


private Drawable getFlippedDrawable(final Drawable d) 
    final Drawable[] arD =  d ;
    return new LayerDrawable(arD) 
        @Override
        public void draw(final Canvas canvas) 
            canvas.save();
            canvas.scale(-1, 1, d.getBounds().width() / 2, d.getBounds().height() / 2);
            super.draw(canvas);
            canvas.restore();
        
    ;


@Override
public boolean onCreateOptionsMenu(Menu menu) 
    getMenuInflater().inflate(R.menu.camera, menu);
    return true;


@Override
public boolean onOptionsItemSelected(MenuItem item) 
    switch (item.getItemId()) 
        case R.id.switch_flash:
            if (mCameraView != null) 
                mCurrentFlash = (mCurrentFlash + 1) % FLASH_OPTIONS.length;
                item.setTitle(FLASH_TITLES[mCurrentFlash]);
                item.setIcon(FLASH_ICONS[mCurrentFlash]);
                mCameraView.setFlash(FLASH_OPTIONS[mCurrentFlash]);
            
            break;
        case R.id.switch_camera:
            if (mCameraView != null) 
                int facing = mCameraView.getFacing();
                mCameraView.setFacing(facing == CameraView.FACING_FRONT ?
                        CameraView.FACING_BACK : CameraView.FACING_FRONT);
            
            break;
        case R.id.mirror_image:
            if (mCameraView != null) 
                SizeAwareImageView imageView = (SizeAwareImageView) mCameraView.findViewById(R.id.mImageView);
                imageView.setImageDrawable(getFlippedDrawable(imageView.getDrawable()));
                imageView.requestLayout();
            
            break;
        case R.id.rotate_image:
            if (mCameraView != null) 
                rotateImage();
            
            break;
    
    return false;


  private Handler getBackgroundHandler() 
    if (mBackgroundHandler == null) 
        HandlerThread thread = new HandlerThread("background");
        thread.setPriority(Thread.MAX_PRIORITY);
        thread.start();
        mBackgroundHandler = new Handler(thread.getLooper());
    
    return mBackgroundHandler;


public static Bitmap scaleBitmap(Bitmap bitmap, int wantedWidth, int wantedHeight, float rotation) 
    Log.e(TAG, "scaleBitmap: bitmapWidth: " + bitmap.getWidth() + ", bitmapHeight: " + bitmap.getHeight() );
    Log.e(TAG, "scaleBitmap: wantedWidth: " +
            ((rotation % 180 == 90) ? wantedHeight : wantedWidth) +
            ", wantedHeight: " + ((rotation % 180 == 90) ? wantedWidth : wantedHeight) );
    Bitmap output = Bitmap.createBitmap(
            (rotation % 180 == 90) ? wantedHeight : wantedWidth,
            (rotation % 180 == 90) ? wantedWidth : wantedHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    Matrix m = new Matrix();
    m.setScale((float)
            ((rotation % 180 == 90) ? wantedHeight : wantedWidth) / bitmap.getWidth(),
            (float) ((rotation % 180 == 90) ? wantedWidth : wantedHeight) / bitmap.getHeight());

    canvas.drawBitmap(bitmap, m, new Paint());
    return output;
    /*Matrix m = new Matrix();

    m.setRectToRect(new RectF(0, 0, b.getWidth(), b.getHeight()),
            new RectF(0, 0, (rotation % 180 == 90) ? wantedHeight : wantedWidth,
                    (rotation % 180 == 90) ? wantedWidth : wantedHeight), Matrix.ScaleToFit.CENTER);
    return Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, true);*/


private CameraView.Callback mCallback
        = new CameraView.Callback() 
    ProgressiveToast progressiveToast;

    @Override
    public void onCameraOpened(CameraView cameraView) 
        Log.d(TAG, "onCameraOpened");
    

    @Override
    public void onCameraClosed(CameraView cameraView) 
        Log.d(TAG, "onCameraClosed");
    

    @Override
    public void onPictureTaken(CameraView cameraView, final byte[] data) 
        Log.d(TAG, "onPictureTaken " + data.length);
        /*TastyToast.makeText(cameraView.getContext(), getString(R.string.pic_being_saved),
                TastyToast.LENGTH_LONG, TastyToast.INFO);*/
        progressiveToast = ProgressiveToast.getInstance();
        progressiveToast.show(CaptureActivity.this, getString(R.string.in_action_be_patient), -1);
        getBackgroundHandler().post(new Runnable() 
            @Override
            public void run() 
                mCameraView.stop();
                // This demo app saves the taken picture to a constant file.
                // $ adb pull /sdcard/android/data/com.google.android.cameraview.demo/files/Pictures/picture.jpg
                SizeAwareImageView imageView = ((SizeAwareImageView) mCameraView.findViewById(R.id.mImageView));
                Bitmap imageBitmap =
                        drawableToBitmap(imageView.getDrawable());
                Matrix matrix = new Matrix();
                float rotation = mCameraView.findViewById(R.id.mImageView).getRotation();
                matrix.postRotate(rotation);
                //matrix.postScale(drawableWidth, drawableHeight);

/*
                    matrix.setScale((float)
                            ((rotation% 180 == 90) ? drawableWidth : drawableHeight) / imageBitmap.getWidth(),
                            (float) ((rotation% 180 == 90) ? drawableWidth : drawableHeight) / imageBitmap.getHeight());*/
                    Log.e(TAG, "rotation: " + rotation);

                imageBitmap = Bitmap.createBitmap(imageBitmap , 0, 0,
                        imageBitmap.getWidth(), imageBitmap.getHeight(), matrix, true);
                imageBitmap = scaleBitmap(imageBitmap, drawableWidth, drawableHeight, rotation);


                Bitmap cameraBmp = BitmapFactory.decodeByteArray(data, 0, data.length);
                cameraBmp = fixOrientation(cameraBmp);
                File dir = new File (Environment.getExternalStorageDirectory().getAbsolutePath()
                        + File.separator + getString(R.string.gallery_folder_name) +
                        (selectedBrand ? getString(R.string.ibr_eng) :
                        getString(R.string.tiyaco_eng)));
                dir.mkdirs();
                File file = new File(dir.getAbsolutePath() ,
                        Long.toString(Calendar.getInstance().getTimeInMillis()) + ".jpg");
                try 
                    file.createNewFile();
                 catch (IOException e) 
                    e.printStackTrace();
                
                OutputStream os = null;
                InputStream is = overlayBitmapToCenter(cameraBmp, imageBitmap, rotation);
                byte[] buffer = new byte[10 * 1024];
                int n = 0;
                try 
                    os = new FileOutputStream(file);
                    while (-1 != (n = is.read(buffer))) 
                        os.write(buffer, 0, n);
                    
                 catch (IOException e) 
                    Log.w(TAG, "Cannot write to " + file, e);
                 finally 
                    if (os != null) 
                        try 
                            os.close();
                         catch (IOException e) 
                            // Ignore
                        
                        runOnUiThread(new Runnable() 
                            @Override
                            public void run() 
                                if (mCameraView != null)
                                    try 
                                        mCameraView.start();
                                     catch (Exception ignored)
                                if (takePicture != null) 
                                    takePicture.setEnabled(true);
                                
                                progressiveToast.dismiss();
                                TastyToast.makeText(getApplicationContext(), getString(R.string.picture_taken),
                                        TastyToast.LENGTH_LONG, TastyToast.SUCCESS);
                            
                        );
                    
                
            
        );
    

;


public Bitmap fixOrientation(Bitmap mBitmap) 
    if (mBitmap.getWidth() > mBitmap.getHeight()) 
        Matrix matrix = new Matrix();
        matrix.postRotate(90);
        return Bitmap.createBitmap(mBitmap , 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
    
    return mBitmap;


private int dp2px(int dp) 
    return (int)((dp * getResources().getDisplayMetrics().density) + 0.5);


public static Bitmap drawableToBitmap (Drawable drawable) 
    Bitmap bitmap = null;

    if (drawable instanceof BitmapDrawable) 
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if(bitmapDrawable.getBitmap() != null) 
            return bitmapDrawable.getBitmap();
        
    

    if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) 
        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
     else 
        bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    

    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;




public ByteArrayInputStream overlayBitmapToCenter(Bitmap bitmap1, Bitmap bitmap2, float rotation) 
    float alpha = (float)cameraWidth / (float)((rotation % 180 == 90) ? drawableHeight : drawableWidth);
    float beta = (float)((rotation % 180 == 90) ? drawableHeight : drawableWidth) /
            (float)((rotation % 180 == 90) ? drawableWidth : drawableHeight);
    int bitmap1Width = bitmap1.getWidth();
    int bitmap1Height = bitmap1.getHeight();

    Bitmap scaledImg = Bitmap.createScaledBitmap(bitmap2, (int)((float)bitmap1Width / alpha),
            (int)(((float)bitmap1Width / alpha) / beta), false);


    int bitmap2Width = scaledImg.getWidth();
    int bitmap2Height = scaledImg.getHeight();

    /*Log.e("cam", "" + bitmap1Width + ", " + bitmap1Height );
    Log.e("img", "" + bitmap2Width + ", " + bitmap2Height );
    Log.e("alpha", "" + alpha );
    Log.e("beta", "" + beta );*/

    float marginLeft = (float) (bitmap1Width * 0.5 - bitmap2Width * 0.5);
    float marginTop = (float) (bitmap1Height * 0.5 - bitmap2Height * 0.5);

    Bitmap overlayBitmap = Bitmap.createBitmap(bitmap1Width, bitmap1Height, bitmap1.getConfig());
    Canvas canvas = new Canvas(overlayBitmap);
    canvas.drawBitmap(bitmap1, new Matrix(), null);
    canvas.drawBitmap(scaledImg, marginLeft, marginTop, null);

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    overlayBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
    return new ByteArrayInputStream(stream.toByteArray());





private class AsyncImageLoader extends AsyncTask<String, Void, BitmapDrawable>
    private Realm realm;

    private ProductModel product;

    @Override
    protected BitmapDrawable doInBackground(String... itemIds) 
        realm = Realm.getDefaultInstance();
        product = realm.where(ProductModel.class)
                .equalTo("isIbr", selectedBrand)
                .equalTo("id", itemIds[0])
                .findFirst();
        byte[] image = product.getImage();
        product = null;
        realm.close();
        BitmapDrawable mDrawable = new BitmapDrawable(getResources(), BitmapFactory
                .decodeByteArray(image, 0, image.length));
        int mDrawableHeight = mDrawable.getIntrinsicHeight();
        int mDrawableWidth = mDrawable.getIntrinsicWidth();
        int valueInPixels = (int) getResources().getDimension(R.dimen.video_view_dimen);
        mDrawable.setBounds(0, 0, valueInPixels, valueInPixels * mDrawableHeight / mDrawableWidth);
        return mDrawable;
    

    @Override
    protected void onPostExecute(BitmapDrawable drawable) 
        super.onPostExecute(drawable);

        LayoutInflater vi = (LayoutInflater) getApplicationContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final View v = vi.inflate(R.layout.imageview_product, null);
        ((SizeAwareImageView)v).setImageDrawable(drawable);



        ViewTreeObserver viewTreeObserver = v.getViewTreeObserver();
        if (viewTreeObserver.isAlive()) 
            viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() 
                @Override
                public void onGlobalLayout() 
                    Log.e(TAG, "onGlobalLayout: updating sizes for drawable");
                    float[] sizez = ((SizeAwareImageView) v).getImageWidthAndHeight();
                    /*if (v.getRotation() == 90 || v.getRotation() == 270) 
                        drawableWidth = dp2px(sizez[1]);
                        drawableHeight = dp2px(sizez[0]);
                     else 
                        drawableWidth = dp2px(sizez[0]);
                        drawableHeight = dp2px(sizez[1]);
                    */
                    drawableWidth = dp2px((int) sizez[0]);
                    drawableHeight = dp2px((int) sizez[1]);

                    /*Log.e("picB4Action", "" + drawableWidth + ", " + drawableHeight);*/
                
            );
        
        int px = (int) (getResources().getDimension(R.dimen.video_view_dimen)/* /
                getResources().getDisplayMetrics().density*/);

        mCameraView.addView(v, new FrameLayout.LayoutParams(px, px, Gravity.CENTER));

    


SizeAwareImageView.java:

public class SizeAwareImageView extends ImageView 
    public SizeAwareImageView(Context context) 
        super(context);
    

    public SizeAwareImageView(Context context, AttributeSet attrs) 
        super(context, attrs);
    

public SizeAwareImageView(Context context, AttributeSet attrs, int defStyleAttr) 
    super(context, attrs, defStyleAttr);


@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SizeAwareImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) 
    super(context, attrs, defStyleAttr, defStyleRes);


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    // Get image matrix values and place them in an array
    float[] f = new float[9];
    getImageMatrix().getValues(f);

    // Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
    final float scaleX = f[Matrix.MSCALE_X];
    final float scaleY = f[Matrix.MSCALE_Y];

    // Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
    final Drawable d = getDrawable();
    final int origW = d.getIntrinsicWidth();
    final int origH = d.getIntrinsicHeight();

    // Calculate the actual dimensions
    final int actW = Math.round(origW * scaleX);
    final int actH = Math.round(origH * scaleY);

    Log.e("DBG", "["+origW+","+origH+"] -> ["+actW+","+actH+"] & scales: x="+scaleX+" y="+scaleY);


public float[] getMatrixValues() 
    float[] f = new float[9];
    getImageMatrix().getValues(f);
    return f;



public float[] getImageWidthAndHeight() 
    // Get image matrix values and place them in an array
    float[] f = new float[9];
    getImageMatrix().getValues(f);

    // Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
    final float scaleX = f[Matrix.MSCALE_X];
    final float scaleY = f[Matrix.MSCALE_Y];

    // Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
    final Drawable d = getDrawable();
    final int origW = d.getIntrinsicWidth();
    final int origH = d.getIntrinsicHeight();

    // Calculate the actual dimensions
    final int actW = Math.round(origW * scaleX);
    final int actH = Math.round(origH * scaleY);
    //Log.e("DBG", "["+origW+","+origH+"] -> ["+actW+","+actH+"] & scales: x="+scaleX+" y="+scaleY);
    return new float[] actW, actH, scaleX, scaleY;



【讨论】:

你能分享你的工作吗? 你能提供这些类吗simport bronteel.ir.dcatalogue.widgets.SizeAwareImageView;导入 io.realm.Realm;还有 ProductModel @Arjunsaini 我已经添加了 SizeAwareImageView,但 Realm 只是库:realm.io 和 ProductModel 是我的领域数据库模型,这不会是你的问题。 您在 cameraView 中拍摄了什么? 它也是一个图书馆,你搜索一下很容易找到

以上是关于如何使用实时贴纸制作自定义相机的主要内容,如果未能解决你的问题,请参考以下文章

如何使用自定义相机 API 制作圆形框架布局并捕获圆形图像?

如何在Android中制作自定义相机布局?

Android App 自定义相机

Android Camera增加自定义图像处理并录制MP4

Android Camera增加自定义图像处理并录制MP4

Android中的自定义相机过滤器