鸿蒙主体分割/剔除背景
鸿蒙主体分割/剔除背景
参考文档
鸿蒙原生提供用于实现主体分割/剔除背景的API,有一些场景例如说证件照之类的应用就非常好做了。
话不多话上代码。
private async doSeg(chooseImage: PixelMap) {
let visionInfo: subjectSegmentation.VisionInfo = {
pixelMap: chooseImage,
};
let config: subjectSegmentation.SegmentationConfig = {
maxCount: 1,
enableSubjectDetails: true,
enableSubjectForegroundImage: true,
};
subjectSegmentation.doSegmentation(visionInfo, config)
.then((data: subjectSegmentation.SegmentationResult) => {
let outputString = `Subject count: ${data.subjectCount}\n`;
outputString += `Max subject count: ${config.maxCount}\n`;
outputString += `Enable subject details: ${config.enableSubjectDetails ? 'Yes' : 'No'}\n\n`;
let segBox : subjectSegmentation.Rectangle = data.fullSubject.subjectRectangle;
let segBoxString = `Full subject box:\nLeft: ${segBox.left}, Top: ${segBox.top}, Width: ${segBox.width}, Height: ${segBox.height}\n\n`;
outputString += segBoxString;
if (config.enableSubjectDetails) {
outputString += 'Individual subject boxes:\n';
if (data.subjectDetails) {
for (let i = 0; i < data.subjectDetails.length; i++) {
let detailSegBox: subjectSegmentation.Rectangle = data.subjectDetails[i].subjectRectangle;
outputString += `Subject ${i + 1}:\nLeft: ${detailSegBox.left}, Top: ${detailSegBox.top}, Width: ${detailSegBox.width}, Height: ${detailSegBox.height}\n\n`;
}
}
}
hilog.info(0x0000, TAG, "Segmentation result: " + outputString);
if (data.fullSubject && data.fullSubject.foregroundImage) {
let rect = data.fullSubject.subjectRectangle
let tmpImage = data.fullSubject.foregroundImage
tmpImage.crop({
size: {
width: rect.width,
height: rect.height
},
x: rect.left,
y: rect.top
}).then( () => {
hilog.warn(0x0000, TAG, "截取完毕,检测人脸");
this.segImage = tmpImage
this.detectFace()
})
.catch((error: BusinessError) => {
hilog.warn(0x0000, TAG, `截取主体失败 ${error.code} ${error.message}`);
})
} else {
hilog.warn(0x0000, TAG, "No foreground image in segmentation result");
}
})
.catch((error: BusinessError) => {
hilog.error(0x0000, TAG, `Image segmentation failed errCode: ${error.code}, errMessage: ${error.message}`);
this.chooseImage = undefined;
});
}
完成示例
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { image } from '@kit.ImageKit';
import { fileIo } from '@kit.CoreFileKit';
import { subjectSegmentation } from '@kit.CoreVisionKit';
const TAG: string = "index";
@Entry
@Component
struct Index {
@State chooseImage: image.PixelMap | null = null
@State segImage: image.PixelMap | null = null
private openPhoto(): Promise<Array<string>> {
return new Promise<Array<string>>((resolve, reject) => {
let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
PhotoSelectOptions.maxSelectNumber = 1;
let photoPicker: photoAccessHelper.PhotoViewPicker = new photoAccessHelper.PhotoViewPicker();
hilog.info(0x0000, TAG, 'PhotoViewPicker.select successfully, PhotoSelectResult uri: ');
photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult) => {
hilog.info(0x0000, TAG, `PhotoViewPicker.select successfully, PhotoSelectResult uri: ${PhotoSelectResult.photoUris}`);
resolve(PhotoSelectResult.photoUris)
}).catch((err: BusinessError) => {
hilog.error(0x0000, TAG, `PhotoViewPicker.select failed with errCode: ${err.code}, errMessage: ${err.message}`);
reject();
});
})
}
private async loadImage(path: string) {
let imageSource: image.ImageSource | undefined = undefined
let fileSource = await fileIo.open(path, fileIo.OpenMode.READ_ONLY)
imageSource = image.createImageSource(fileSource.fd)
this.chooseImage = await imageSource.createPixelMap()
hilog.info(0x0000, TAG, `this.chooseImage===${this.chooseImage}`);
}
private async doSeg(chooseImage: PixelMap) {
let visionInfo: subjectSegmentation.VisionInfo = {
pixelMap: chooseImage,
};
let config: subjectSegmentation.SegmentationConfig = {
maxCount: 1,
enableSubjectDetails: true,
enableSubjectForegroundImage: true,
};
subjectSegmentation.doSegmentation(visionInfo, config)
.then((data: subjectSegmentation.SegmentationResult) => {
let outputString = `Subject count: ${data.subjectCount}\n`;
outputString += `Max subject count: ${config.maxCount}\n`;
outputString += `Enable subject details: ${config.enableSubjectDetails ? 'Yes' : 'No'}\n\n`;
let segBox : subjectSegmentation.Rectangle = data.fullSubject.subjectRectangle;
let segBoxString = `Full subject box:\nLeft: ${segBox.left}, Top: ${segBox.top}, Width: ${segBox.width}, Height: ${segBox.height}\n\n`;
outputString += segBoxString;
if (config.enableSubjectDetails) {
outputString += 'Individual subject boxes:\n';
if (data.subjectDetails) {
for (let i = 0; i < data.subjectDetails.length; i++) {
let detailSegBox: subjectSegmentation.Rectangle = data.subjectDetails[i].subjectRectangle;
outputString += `Subject ${i + 1}:\nLeft: ${detailSegBox.left}, Top: ${detailSegBox.top}, Width: ${detailSegBox.width}, Height: ${detailSegBox.height}\n\n`;
}
}
}
hilog.info(0x0000, TAG, "Segmentation result: " + outputString);
if (data.fullSubject && data.fullSubject.foregroundImage) {
let rect = data.fullSubject.subjectRectangle
let tmpImage = data.fullSubject.foregroundImage
tmpImage.crop({
size: {
width: rect.width,
height: rect.height
},
x: rect.left,
y: rect.top
}).then( () => {
hilog.warn(0x0000, TAG, "截取完毕,检测人脸");
this.segImage = tmpImage
})
.catch((error: BusinessError) => {
hilog.warn(0x0000, TAG, `截取主体失败 ${error.code} ${error.message}`);
})
} else {
hilog.warn(0x0000, TAG, "No foreground image in segmentation result");
}
})
.catch((error: BusinessError) => {
hilog.error(0x0000, TAG, `Image segmentation failed errCode: ${error.code}, errMessage: ${error.message}`);
this.segImage = null;
});
}
build() {
Column() {
Image(this.chooseImage)
.objectFit(ImageFit.Contain)
.width('100%')
.height('40%')
Row() {
Image(this.segImage)
.objectFit(ImageFit.Contain)
.width('100%')
.height('100%')
}
.width('100%')
.height('40%')
Blank()
Row() {
Text('选择图片')
.height(50)
.width(140)
.borderRadius(25)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
.onClick(async () => {
let urls = await this.openPhoto()
if (urls.length > 0) {
let url = urls[0]
this.loadImage(url)
}
})
Text('分割图片')
.height(50)
.width(140)
.borderRadius(25)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Orange)
.onClick(async () => {
if (this.chooseImage) {
this.doSeg(this.chooseImage)
}
})
}
}
.height('100%')
.width('100%')
}
}
后记
最近利用这些知识上架了两个应用
小鱼证件照,免费便捷的证件照生成工具。
小鱼抽签。出门之前占卜吉凶,总会有好事发生。
第1签 锤离成道
天开地辟结良缘,日吉时良万事全,若得此签非小可,人行中正帝王宜
上上签
子宫
此卦盘古初开天地之象,诸事皆吉也
快使用鸿蒙next版本扫一扫体验一下吧~