Camera:高斯模糊

本文介绍了如何在手机相机应用中使用高斯模糊技术,以减少分辨率切换时的视觉冲击,通过尽早显示模糊效果、精确控制模糊时机、捕获预览帧并进行模糊处理,提供更平滑的用户体验。对比华为手机的处理策略,展示了优化过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

           高斯模糊场景:手机相机不同于工业相机以及车载相机,手机相机的模式切换往往会伴随着预览分辨率的改变,而分辨率的切换伴随手机App->Framework->HAL->Drivel一层层的下发上传,所造成的时间延迟已经带来了不可忽略的视觉冲击,为了缓解这种冲击,引入高斯模糊对手机切换分辨率场景进行处理,提高用户体验舒适度。

应用层处理高斯模糊:

            1.处理时机:肯定是越早越好,放到CameraActivity的Resume阶段,保证了每一次切换都可以调到高斯模糊的showPreviewAnim(0)方法。

@Override
    protected void onResumeTasks() {
        super.onResumeTasks();
        PictureQuality.enterCameraMode();
        mCameraAppUI.showPreviewAnim(0);
        mCameraAppUI.removeTopSurface();
        CameraSysTrace.onEventSystrace("CameraActivity.onResumeTasks", false, true);
    }


//高斯模糊的处理,getPreviewBlurDrawable拿到最后的预览Bitmap
public void showPreviewAnim(int duration) {
        if (mSwitchAnim == null || mSwitchAnim.getVisibility() == View.VISIBLE) {
            return;
        }
        if (!mPause) {
            getPreviewBlurDrawable();
        }
        if (mLastBitmap == null) {
            mLastBitmap = mDefaultBitmap;
        }
        //RectF rect = new RectF(0, 0, 720, 1280);
        RectF rect = mPreviewManager.getPreviewArea();
        if (!isCameraSwitch) {
            mSwitchAnim.setVisibility(View.VISIBLE);
            startSwitchAnimation(0.0f, 1.0f, duration);
            mSwitchAnim.setSwitchAnimInfo(mLastBitmap, rect);
        }
    }

           2.高斯模糊去除时机:这个肯定是要在旧的预览session已经切断,新的预览session创建且上传数据之后去除高斯模糊效果,可通过下发预览请求时的回调函数达到这个时机的监控以及把握,CaptureCallback回调函数的onCaptureFailed捕捉旧预览切断的时机,onCaptureCompleted捕捉新预览第一帧数据上传时机。

//下发repeatingPreview请求
mSession.setRepeatingRequest(mBuilder.build(), mCaptureCallback, mModeHandler); 


//mCaptureCallback回调函数监控
private final CaptureCallback mCaptureCallback = new CaptureCallback() {
@Override
        public void onCaptureCompleted(@Nonnull CameraCaptureSession session,
                @Nonnull CaptureRequest request, @Nonnull TotalCaptureResult result) {
            super.onCaptureCompleted(session, request, result);
            if (mCamera2Proxy == null
                    || mModeDeviceCallback == null
                    || session.getDevice() != mCamera2Proxy.getCameraDevice()) {
                return;
            }
            if (!CameraUtil.isStillCaptureTemplate(result) && !mFirstFrameArrived) {
                mFirstFrameArrived = true;
                new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        LogHelper.d(TAG, "[onCaptureCompleted] hidePreviewAnim");
                        ((CameraAppUI) ((CameraActivity) mActivity).getAppUi()).hidePreviewAnim(0);
                    }
                }, 700);
            }
        }

        @Override
        public void onCaptureFailed(@Nonnull CameraCaptureSession session,
                @Nonnull CaptureRequest request, @Nonnull CaptureFailure failure) {
            super.onCaptureFailed(session, request, failure);

        }

           3.高斯模糊预览帧获:通过应用层接收预览buffer的CaptureSurface的OnImageAvailable来获取预览的Image,高斯模糊对之前分辨率下的最后一帧Buffer进行模糊处理。

private PreviewImageCallback mPreviewImageCallback;
public interface PreviewImageCallback {
    void onPreviewImageCallback(Image image);
}

public void setPreviewCallback(PreviewImageCallback captureCallback) {
    mPreviewImageCallback = captureCallback;
} 

public final OnImageAvailableListener mCaptureImageListener = new OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader imageReader) {
            int format = image.getFormat();
            int width = image.getWidth();
            int height = image.getHeight();
            if((format == ImageFormat.YUV_420_888 && "previewImage".equalsIgnoreCase(mCaptureType))) {
                if(mPreviewImageCallback != null) {
                    mPreviewImageCallback.onPreviewImageCallback(image);
                }
                image.close();
            }
        }
}


//每次下发repeatingPreview请求时
mPreviewImageSurface.setPreviewCallback(this);

@Override
public void onPreviewImageCallback(Image image) {
    //拿到了预览帧Image
    ((CameraAppUI) ((CameraActivity) mActivity).getAppUi()).setPreviewBitmap(image);
}


public void getPreviewBlurDrawable() {
        mLastBitmap = mDefaultBitmap;
        GaussianBlur blur = new GaussianBlur(mApp.getActivity());
        Bitmap preview;

		preview = getPreviewBitmap(mPreviewImageData);
        if (preview != null) {
            Bitmap bitmap = blur.blurBitmap(mApp.getActivity(), blur.small(preview));
            if (bitmap != null) {
                mLastBitmap = bitmap;
            }
        }
    }

            4.对最后的预览帧Bitmap进行高斯模糊处理:对Bitmap数据的高斯模糊处理也是引入canvas以及一些Matrix的方式进行坐标的模糊处理,上代码。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        final DisplayMetrics metrics = new DisplayMetrics();
        mApp.getActivity().getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
        int[] loc = new int[2];
        getPreviewFrameLayout().getLocationOnScreen(loc);
        int x = loc[0];
        int y = loc[1];
        if (mBlurBitmapWidth > 0 && mBlurBitmapHeight > 0) {
            mPreviewRatio = CameraUtil.determineRatio((int) mBlurBitmapWidth, (int) mBlurBitmapHeight);

            canvas.drawColor(mBgColor);
            mMatrix.reset();
            final Bitmap bitmap = changeBitmapSize(mBlurBitmap, mBlurBitmapWidth, mBlurBitmapHeight);
            mMatrix.postTranslate(x, y);
            canvas.drawBitmap(bitmap, mMatrix, null);
        }
    }

经过高斯模糊处理后:

对比华为手机模式切换时候的高斯模糊处理:

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值