HarmonyOS NEXT AI基礎(chǔ)視覺服務(wù)-背景替換
案例描述
這是一個基于AI基礎(chǔ)視覺服務(wù)實現(xiàn)的背景替換案例,通過調(diào)用設(shè)備相冊選擇圖片后對主體進(jìn)行智能分割,并支持動態(tài)更換背景顏色。
實現(xiàn)步驟:
1. 模塊導(dǎo)入與組件定義
import { photoAccessHelper } from **********' import { fileIo } from **********' import image from **********' import { subjectSegmentation } from **********' import { promptAction } from **********' @Entry @ComponentV2 struct SubjectSegmentation { @Local chooseImage?: PixelMap // 原始圖片 @Local segmentedImage?: PixelMap // 分割后圖片 @Local bgColor: ResourceColor = Color.White // 背景色狀態(tài)
2. 圖片選擇與處理
async segmentImage() { if (canIUse('SystemCapability.AI.Vision.SubjectSegmentation')) { // 創(chuàng)建圖片選擇器 const photoPicker: photoAccessHelper.PhotoViewPicker = new photoAccessHelper.PhotoViewPicker(); // 選擇單張圖片 const photoResult = await photoPicker.select({ MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE, maxSelectNumber: 1 }) // 獲取圖片URI并轉(zhuǎn)換為PixelMap格式 const photoUri = photoResult.photoUris[0] const fileSource = await fileIo.open(photoUri, fileIo.OpenMode.READ_ONLY); const imageSource = image.createImageSource(fileSource.fd); this.chooseImage = await imageSource.createPixelMap();
3. 主題分割處理
// 配置視覺識別參數(shù) const visionInfo: subjectSegmentation.VisionInfo = { pixelMap: this.chooseImage, }; try { // 執(zhí)行主體分割 const result = await subjectSegmentation.doSegmentation(visionInfo, { enableSubjectForegroundImage: true }) this.segmentedImage = result.fullSubject.foregroundImage } catch (e) { promptAction.showToast({ message: e.message }) } } }
4. 背景替換機制
build() { Column({ space: 20 }) { // 原始圖片展示區(qū)域 Text('原圖:') Image(this.chooseImage) .objectFit(ImageFit.Fill) .height('30%') // 分割后圖片展示區(qū)域 Text('扣除背景:') Image(this.segmentedImage) .objectFit(ImageFit.Fill) .height('30%') .backgroundColor(this.bgColor) // 功能操作按鈕 Button('選擇圖片').onClick(() => this.segmentImage()) Button('更換背景').onClick(() => { // 生成隨機RGB背景色 const a = Math.round(Math.random() * 255) const b = Math.round(Math.random() * 255) const c = Math.round(Math.random() * 255) this.bgColor = `rgb(${a},$,${c})` }) } .padding(15) .height('100%') .width('100%') } }
總結(jié)梳理:
核心點
- 多媒體庫調(diào)用實現(xiàn)圖片選擇與格式轉(zhuǎn)換
- subjectSegmentation.doSegmentation接口完成智能主體分割
- 動態(tài)背景色機制通過隨機RGB值實現(xiàn)
完整代碼
// 此處完整保留用戶提供的原始代碼 import { photoAccessHelper } from **********' import { fileIo } from **********' import image from **********' import { subjectSegmentation } from **********' import { promptAction } from **********' @Entry @ComponentV2 struct SubjectSegmentation { @Local chooseImage?: PixelMap @Local segmentedImage?: PixelMap @Local bgColor: ResourceColor = Color.White async segmentImage() { if (canIUse('SystemCapability.AI.Vision.SubjectSegmentation')) { const photoPicker: photoAccessHelper.PhotoViewPicker = new photoAccessHelper.PhotoViewPicker(); const photoResult = await photoPicker.select({ MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE, maxSelectNumber: 1 }) const photoUri = photoResult.photoUris[0] const fileSource = await fileIo.open(photoUri, fileIo.OpenMode.READ_ONLY); const imageSource = image.createImageSource(fileSource.fd); this.chooseImage = await imageSource.createPixelMap(); const visionInfo: subjectSegmentation.VisionInfo = { pixelMap: this.chooseImage, }; try { const result = await subjectSegmentation.doSegmentation(visionInfo, { enableSubjectForegroundImage: true }) this.segmentedImage = result.fullSubject.foregroundImage } catch (e) { promptAction.showToast({ message: e.message }) } } } build() { Column({ space: 20 }) { Text('原圖:') Image(this.chooseImage) .objectFit(ImageFit.Fill) .height('30%') Text('扣除背景:') Image(this.segmentedImage) .objectFit(ImageFit.Fill) .height('30%') .backgroundColor(this.bgColor) Button('選擇圖片') .onClick(() => this.segmentImage()) Button('更換背景') .onClick(() => { const a = Math.round(Math.random() * 255) const b = Math.round(Math.random() * 255) const c = Math.round(Math.random() * 255) this.bgColor = `rgb(${a},$,${c})` }) } .padding(15) .height('100%') .width('100%') } }