5分鐘給商品創建3D模型,我是如何作到的?

提問:3D模型展現商品不香嗎?
香!固然香。
java

當3D建模成爲電商網購應用的左膀右臂,大同小異的產品首圖就有了面目一新的呈現面貌!商品3D模型360°全方位展現,細節更豐富,輔以線上虛擬「看、試、穿、戴」,提供接近實物的差別化網購體驗,助力高效提高用戶轉化。
3D模型雖美麗,然而,時下效果佳的3D建模技術因其較高的成本而使得讓廣大需求者望而卻步。android

  • 技術門檻高:專業人員手工製做,師帶徒傳承,學習成本高;
  • 時間成本高:完成一個簡單物體的低模模型,工做量以小時起步,高模模型耗時更長。
  • 耗費高:單個商品的專業建模成本高,平均價格達到上千元,複雜模型更貴;

華爲移動服務最新開放的3D建模服務,助力輕鬆建模。用戶只需使用普通的RGB相機,經過拍攝物體的不一樣角度圖像,即可實現物體的3D幾何模型和紋理的自動化生成,爲應用提供3D模型構建、預覽等能力。如在電商鞋子展現的場景,您能夠經過此能力自動生成鞋子3D模型,用於3D展現,用戶可360°隨心放大或縮小商品,爲用戶提供差別化的購買體驗。 git

效果示例

技術方案

3D物體建模能力由端雲協同完成,端側負責採集RGB圖像,經過環繞物體一週拍攝多張圖像,從而獲取物體的不一樣角度圖像,拍攝完畢後上傳至雲端實現3D物體建模。雲端建模的流程及關鍵技術包括目標檢測分割、特徵檢測與匹配、稀疏點雲計算、稠密點雲計算以及紋理重建等模塊。最終輸出業界通用的3D模型格式(.obj文件),面片數約40K~200K。github

開發準備

1. 配置集成的SDK包服務器

在應用的build.gradle文件中,dependencies內添加3D建模服務的SDK依賴app

// 3D Modeling Kit SDK
implementation 'com.huawei.hms:modeling3d-object-reconstruct:1.0.0.300'

2. 配置AndroidManifest.xmlide

打開main文件夾中的AndroidManifest.xml文件,能夠根據場景和使用須要,配置讀取和寫入手機存儲以及相機權限,在<application>前添加學習

<!-- 往sdcard中寫入數據的權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 使用相機的權限 -->
<uses-permission android:name="android.permission.CAMERA" />

開發步驟

1. 配置存儲權限申請gradle

在MainActivity的onCreate()方法中,首先對手機存儲的讀取權限進行判斷,若是未獲取權限,則經過requestPermissions進行申請。ui

if (EasyPermissions.hasPermissions(MainActivity.this, PERMISSIONS)) {
    Log.i(TAG, "Permissions OK");
} else {
    EasyPermissions.requestPermissions(MainActivity.this, "To use this app, you need to enable the permission.",
            RC_CAMERA_AND_EXTERNAL_STORAGE, PERMISSIONS);
}

檢查權限申請的結果,若是有權限初始化界面,沒有權限提示用戶開啓。

@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
    Log.i(TAG, "permissions = " + perms);
    if (requestCode == RC_CAMERA_AND_EXTERNAL_STORAGE &&              PERMISSIONS.length == perms.size()) {
        initView();
        initListener();
    }
}

@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
    if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
        new AppSettingsDialog.Builder(this)
                .setRequestCode(RC_CAMERA_AND_EXTERNAL_STORAGE)
                .setRationale("To use this app, you need to enable the permission.")
                .setTitle("Insufficient permissions")
                .build()
                .show();
    }
}

2. 新建3D物體建模配置器

// Initializing the RGB Mode
Modeling3dReconstructSetting setting = new Modeling3dReconstructSetting.Factory()
        .setReconstructMode(Modeling3dReconstructConstants.ReconstructMode.PICTURE)
        .create();

3. 新建3D物體建模引擎並初始化任務

調用Modeling3dReconstructEngine的getInstance()接口,傳入當前應用的上下文建立3D建模引擎實例

// Initializing the Rebuild Engine
modeling3dReconstructEngine = Modeling3dReconstructEngine.getInstance(mContext);

使用3D物體建模引擎初始化任務

// Creating a Rebuilding Task
modeling3dReconstructInitResult = modeling3dReconstructEngine.initTask(setting);
// Getting a Rebuilding Task
String taskId = modeling3dReconstructInitResult.getTaskId();

4. 新建上傳監聽器回調,處理拍攝的物體上傳結果

新建上傳回調接口,您能夠在該回調接口中編寫上傳成功或失敗後須要執行的操做。

// Re-establishing the upload callback listener
private final Modeling3dReconstructUploadListener uploadListener = new Modeling3dReconstructUploadListener() {
    @Override
    public void onUploadProgress(String taskId, double progress, Object ext) {
        // Upload progress
    }

    @Override
    public void onResult(String taskId, Modeling3dReconstructUploadResult result, Object ext) {
        if (result.isComplete()) {
            isUpload = true;
            ScanActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progressCustomDialog.dismiss();
                    Toast.makeText(ScanActivity.this, getString(R.string.upload_text_success), Toast.LENGTH_SHORT).show();
                }
            });
            TaskInfoAppDbUtils.updateTaskIdAndStatusByPath(new Constants(ScanActivity.this).getCaptureImageFile() + manager.getSurfaceViewCallback().getCreateTime(), taskId, 1);
        }
    }

    @Override
    public void onError(String taskId, int errorCode, String message) {
        isUpload = false;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressCustomDialog.dismiss();
                Toast.makeText(ScanActivity.this, "Upload failed." + message, Toast.LENGTH_SHORT).show();
                LogUtil.e("taskid" + taskId + "errorCode: " + errorCode + " errorMessage: " + message);
            }
        });

    }
};

5. 3D物體建模引擎設置上傳監聽器,上傳採集的圖片數據

上傳回調接口傳入3D建模引擎並調用uploadFile()接口,傳入第三步獲取到的任務ID以及須要上傳的圖片路徑,將數據上傳到雲端服務器。

// Set the callBack to engine.
modeling3dReconstructEngine.setReconstructUploadListener(uploadListener);
// Executing a Rebuild Upload Task
modeling3dReconstructEngine.uploadFile(taskId, filePath);

6. 查詢3D物體建模任務狀態

調用Modeling3dReconstructTaskUtils的getInstance接口建立3D建模任務處理實例,一樣是傳入當前應用的上下文做爲入參。

// Initialize the reconstruction task tool class.
modeling3dReconstructTaskUtils = Modeling3dReconstructTaskUtils.getInstance(Modeling3dDemo.getApp());

調用任務處理實例的queryTask接口查詢當前建模任務的進度。

// Query the reconstruction task execution result. The options are as follows: 0: To be uploaded; 1: Generating; 3: Completed; 4: Failed.
Modeling3dReconstructQueryResult queryResult = modeling3dReconstructTaskUtils.queryTask(task.getTaskId());

7.  新建下載監聽器回調,用於處理3D物體建模模型文件的下載結果

新建下載回調接口,您能夠在該回調接口中編寫下載成功或失敗後須要執行的操做

// Re-establishing the download callback listener
private Modeling3dReconstructDownloadListener modeling3dReconstructDownloadListener = new Modeling3dReconstructDownloadListener() {
    @Override
    public void onDownloadProgress(String taskId, double progress, Object ext) {
        ((Activity) mContext).runOnUiThread(new Runnable() {
            @Override
            public void run() {
                dialog.show();
            }
        });
    }

    @Override
    public void onResult(String taskId, Modeling3dReconstructDownloadResult result, Object ext) {
        ((Activity) mContext).runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getContext(), "Download complete", Toast.LENGTH_SHORT).show();
                TaskInfoAppDbUtils.updateDownloadByTaskId(taskId, 1);
                dialog.dismiss();
            }
        });
    }

    @Override
    public void onError(String taskId, int errorCode, String message) {
        LogUtil.e(taskId + " <---> " + errorCode + message);
        ((Activity) mContext).runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getContext(), "Download failed." + message, Toast.LENGTH_SHORT).show();
                dialog.dismiss();
            }
        });
    }
};

8. 3D物體建模引擎加入下載監聽,下載重建成功的模型文件

將下載回調接口傳入3D建模引擎並調用downloadModel接口,傳入第三步中獲取的任務id和保存路徑進行模型文件的下載。

// Setting Rebuild Download Listening
modeling3dReconstructEngine.setReconstructDownloadListener(modeling3dReconstructDownloadListener);
// Executing a Rebuild Download Task
modeling3dReconstructEngine.downloadModel(appDb.getTaskId(), appDb.getFileSavePath());

注意事項

  1. 支持的物體紋理需豐富(紋理特徵明顯)、不反光、不透明/不半透明、尺寸中等、剛體,典型物體包括:商品類(毛絨玩具、包、鞋子)、 傢俱類(沙發)、文物類(青銅器、石器、木器)等。
  2. 支持物體尺寸15cm*15cm*15cm < 物體尺寸 < 1.5m*1.5m*1.5m(尺寸越大建模時間越長)。
  3. 不支持人臉、人體建模。
  4. 圖像拍攝時需將單一的採集物體靜置於純色平面上,光照要柔和、避免燈光過暗,拍攝時要對焦,覆蓋均勻而足夠的多視角,含仰視、平視、俯視(50張以上),相機移動儘量緩慢,全部角度照片儘量一致,同時全過程採集中物體屏佔比儘可能大且完整,要求儘可能保證拍攝無虛焦、運動模糊、抖動模糊。

超詳細代碼教程奉上,誠邀親愛的開發者小夥伴們親自實踐一把,再爲你身邊的物品建個模!

>>訪問華爲3D建模服務官網,瞭解更多相關內容
>>獲取華爲3D建模開發指導文檔
>>華爲3D建模開源倉庫地址GitHubGitee
>>華爲HMS Core官方論壇
>>解決集成問題請到Stack Overflow

點擊右上角頭像右方的關注,第一時間瞭解HMS Core最新技術~

相關文章
相關標籤/搜索