介紹
簡介
HwCameraKit為開發者提供了一套相容EMUI的相機能力開放介面,開發者可以通過HwCameraKit使自己的應用快速接入華為相機的私有能力,擴充套件應用的拍攝功能,為使用者提供更好拍攝體驗。
人像模式為HwCameraKit開放的多種相機模式其中之一,它將允許您:
- 獲取華為相機的人像拍攝能力,包括背景虛化、環境光、瘦臉,皮膚光滑、調色等能力;
- 提供相機模式高階程式設計介面,簡化相機應用開發,並藉助IDE工具快速接入上述能力。
關於本次CodeLab
你將建立什麼
在本次CodeLab中,您將使用HwCameraKit建立一款Android相機應用程式,使其可以獲得華為相機的人像拍攝功能,實現人像的虛化、美膚等效果。
普通拍攝(左) VS 人像模式開啟虛化(右)
你會學到什麼
- 使用HwCameraKit IDE高效整合華為相機開放能力
- 熟悉HwCameraKit基本開發模式
你需要什麼
硬體要求
- 開發計算機(桌上型電腦或膝上型電腦)
- 作業系統為EMUI10.0及以上版本的華為手機
軟體要求
- JAVA JDK安裝包
- Android SDK包
- HwCameraKit IDE工具:DevEco
申請Camera相關許可權
Duration: 0:05
1. 在工程的Manifest檔案中新增相關許可權:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2. 動態申請相關許可權:
private static final String [] PERMISSIONS_ARRAY = new String[] {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.ACCESS_FINE_LOCATION
};
private static List<String> permissionsList = new ArrayList<>(PERMISSIONS_ARRAY.length);
/**
* 動態請求WRITE_EXTERNAL_STORAGE CAMERA RECORD_AUDIO許可權
*
* @param activity 應用activity
*/
public static void requestPermission (final Activity activity) {
for (String permission : PERMISSIONS_ARRAY) {
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
}
}
ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String [permissionsList.size()]), REQUEST_CODE_ASK_PERMISSIONS);
}
整合HwCameraKit開放能力
Duration: 0:60
通過IDE提供的功能卡片,可以快速獲取示例程式碼並將其新增到工程中,以人像模式為例,找到人像能力卡片:可通過Tools->EMUI Kits->Kit Assistant->Camera->Portrait Mode 來找到該卡片。
提示:本次Codelabs提供了配套的app開發工程,請使用IDE工具匯入,並根據如下步驟,實現提供的配套工程中帶有/* TODO */註釋的方法,從而快速整合人像模式。
步驟1 模式建立:獲取CameraKit例項,建立人像模式
private @Mode.Type int mCurrentModeType;
private CameraKit mCameraKit;
private ModeCharacteristics mModeCharacteristics;
private void createMode() {
mCameraKit = CameraKit.getInstance(getApplicationContext());
if (mCameraKit == null) {
Log.e(TAG, "This device does not support CameraKit!");
}
/** Query camera id list*/
String[] cameraLists = mCameraKit . getCameraIdList ();
if ((cameraLists != null) && (cameraLists.length > 0)) {
Log.i(TAG, "Try to use camera with id " + cameraLists[0]);
/** Query supported modes of this device*/
int[] modes = mCameraKit . getSupportedModes (cameraLists[0]);
if (!Arrays.stream(modes).anyMatch((i) -> i == mCurrentModeType)) {
Log.w(TAG, "Current mode is not supported in this device!");
return;
}
mCameraKit.createMode(cameraLists[0], mCurrentModeType, mModeStateCallback, mCameraKitHandler);
}
}
步驟2 配置模式:配置模式的狀態回撥,資料回撥及處理這些回撥的Handler,以及預覽、拍照解析度等引數
從mModeStateCallback的onCreated回撥後,可從入參可獲得人像Mode例項
/** 在onCreated回撥中獲取mode物件,然後以行為的狀態回撥和資料回撥及對應的執行緒為入參,初始化ModeConfig.Builder,配置預覽的surface和拍照的大小,通過configure命令將配置項設定到mMode中,進行模式的啟用*/
private void configMode() {
Log.i(TAG, "configMode begin");
/** Query supported preview size*/
List<Size> previewSizes = mModeCharacteristics.getSupportedPreviewSizes(SurfaceTexture.class);
/** Query supported capture size*/
List<Size> captureSizes = mModeCharacteristics.getSupportedCaptureSizes(ImageFormat.JPEG);
Log.d(TAG, "configMode: captureSizes = " + captureSizes.size() + ";previewSizes=" + previewSizes.size());
/** Use the first one or default 4000x3000*/
mCaptureSize = captureSizes.stream().findFirst().orElse(new Size(4000, 3000));
/** Use the same ratio with preview*/
mPreviewSize = previewSizes.stream().filter((size) -> Math.abs((1.0f * size.getHeight() / size.getWidth()) - (1.0f * mCaptureSize.getHeight() / mCaptureSize.getWidth())) < 0.01).findFirst().get();
Log.i(TAG, "configMode: mCaptureSize = " + mCaptureSize + ";mPreviewSize=" + mPreviewSize);
/** Update view*/
runOnUiThread(() -> mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth()));
SurfaceTexture texture = mTextureView.getSurfaceTexture();
if (texture == null) {
Log.e(TAG, "configMode: texture=null!");
return;
}
/** Set buffer size of view*/
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
/** Get surface of texture*/
Surface surface = new Surface(texture);
/** Add preview and capture parameters to config builder*/
modeConfigBuilder.addPreviewSurface(surface).addCaptureImage(mCaptureSize, ImageFormat.JPEG);
/** Set callback for config builder*/
modeConfigBuilder.setDataCallback(actionDataCallback, mCameraKitHandler);
modeConfigBuilder.setStateCallback(actionStateCallback, mCameraKitHandler);
/** Configure mode*/
mMode.configure();
Log.i(TAG, "configMode end");
}
使用構造器ModeConfig.Builder配置模式的狀態回撥及資料回撥及執行回撥所在的Handler。從狀態回撥中,開發者可以獲取如啟動預覽後狀態變化、拍照結束狀態、手動對焦結束、人臉檢測結果返回等資訊;從資料回撥中,開發者可獲取模式動作執行過程中產生資料結果(如拍照影像資料等)。還可通過ModeConfig.Builder配置預覽Surface及拍照解析度。
步驟3 模式操作
3.1 開啟預覽
/* 在接收到到onConfigured回撥後,說明mode配置成功,模式進入開啟狀態,此時呼叫startPreview命令開啟預覽。*/
private void startPreview() {
mMode.startPreview();
}
3.2 引數設定
/* 使用者可以通過ModeCharacteristics#getSupportedParameters查詢當前模式下支援的引數(以人像模式為例:支援背景虛化,美膚等),通過ModeCharacteristics#getParameterRange查詢引數支援的取值範圍,通過Mode#setParameter設定對應效果。*/
/* 設定人像虛化 */
mMode.setParameter(RequestKey.HW_PORTRAIT_SPOTS_BOKEH, validValue);
/* 設定美膚:皮膚光滑 */
int[] smoothLevels = modeCharacteristics.getSupportedBeauty(Metadata.BeautyType.HW_BEAUTY_SKIN_SMOOTH);
if (smoothLevels != null && smoothLevels.length != 0) {
mMode.setBeauty(Metadata.BeautyType.HW_BEAUTY_SKIN_SMOOTH,smoothLevels[smoothLevels.length - 1]);
}
/* 使用者可以通過設計按鈕等方式,呼叫takePicture進行拍照,非同步通過onImageAvailable回撥,返回照片Image資料。*/
mMode.takePicture();
步驟4 操作Callback
/* 以資料回撥為例,在拍照後從回撥裡獲取圖片 */
private final ActionDataCallback actionDataCallback = new ActionDataCallback() {
@Override
public void onImageAvailable(Mode mode, int id, Image image) {
super.onImageAvailable(mode, id, image);
Log.d(TAG, "onImageAvailable");
new ImageSaver(image, mFile, CameraKitActivity.this).run();
}
};
提示:除了從ActionDataCallback獲取拍照圖片等資料以外,從ActionStateCallback中還可獲取模式動作執行過程中,執行狀態結果的回撥處理,如啟動預覽後狀態變化、拍照結束狀態、手動對焦結束、人臉檢測結果返回等。
步驟5 模式釋放
/* 應用切後臺,需要將模式釋放 */
@Override
protected void onPause() {
if (mBackgroundHandler != null) {
mBackgroundHandler.post(new Runnable() {
@Override
public void run() {
if (mMode != null) {
mMode.release();
mMode = null;
}
}
});
}
super.onPause();
}
恭喜你
- HwCameraKit IDE外掛的安裝和使用
- 利用HwCameraKit將華為相機開放能力接入app
更多HwCameraKit相關資訊請關注我們的官網:
https://developer.huawei.com/consumer/cn/CameraKit
往期連結:Android | 教你如何快速整合機器學習能力
內容來源:https://developer.huawei.com/consumer/cn/forum/topicview?tid=0201234569803940158&fid=3467
原作者:艾羅門特