使用主体分割,保存分割得到的前景图到沙箱中,保存的是PNG格式,图片背景是黑色的,不是透明背景。
将图片进行主体分割出来后,获取到的内容图片保存到沙箱中:
import { subjectSegmentation } from '@kit.CoreVisionKit';
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileIo } from '@kit.CoreFileKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import fs from '@ohos.file.fs';
@Entry
@Component
struct Index {
@State chooseImage: PixelMap | undefined = undefined;
subjectSegImage: PixelMap | undefined = undefined;
@State dataValues: string = '';
@State maxNum: string = '20';
async aboutToAppear() {
initSubjectSegmentation();
}
aboutToDisappear(): void {
releaseSubjectSegmentation();
}
build() {
Column() {
Image(this.chooseImage)
.objectFit(ImageFit.Contain)
.height('30%')
.accessibilityDescription('Image to be split')
Scroll() {
Text(this.dataValues)
.copyOption(CopyOptions.LocalDevice)
.margin(10)
.width('100%')
}
.height('20%')
Row() {
Text('Maximum number of principals:')
.fontSize(16)
TextInput({ placeholder: 'Please enter the maximum number of entities', text: this.maxNum })
.type(InputType.Number)
.placeholderColor(Color.Gray)
.fontSize(16)
.backgroundColor(Color.White)
.onChange((value: string) => {
this.maxNum = value;
})
}
.width('80%')
.margin(10)
Button('Select image')
.type(ButtonType.Capsule)
.fontColor(Color.White)
.alignSelf(ItemAlign.Center)
.width('80%')
.margin(10)
.onClick(() => {
// Pull up the gallery.
this.selectImage();
})
Button('Start subject segmentation')
.type(ButtonType.Capsule)
.fontColor(Color.White)
.alignSelf(ItemAlign.Center)
.width('80%')
.margin(10)
.onClick(async () => {
if (!this.chooseImage) {
return;
}
let visionInfo: subjectSegmentation.VisionInfo = {
pixelMap: this.chooseImage
};
let config: subjectSegmentation.SegmentationConfig = {
maxCount: parseInt(this.maxNum),
enableSubjectDetails: true,
enableSubjectForegroundImage: true
};
// Call the image segmentation API.
let data: subjectSegmentation.SegmentationResult =
await subjectSegmentation.doSegmentation(visionInfo, config);
this.subjectSegImage = data.fullSubject.foregroundImage;
let outputString = `Subjects: ${data.subjectCount}\n`;
outputString += `Maximum subjects: ${config.maxCount}\n`;
outputString += `Show bounding box of each subject: ${config.enableSubjectDetails ? 'Yes' : 'No'}\n\n`;
let segBox : subjectSegmentation.Rectangle = data.fullSubject.subjectRectangle;
let segBoxString = `Global bounding box:\nLeft: ${segBox.left}, Top: ${segBox.top}, Width: ${segBox.width}, Height: ${segBox.height}\n\n`;
outputString += segBoxString;
if (config.enableSubjectDetails) {
outputString += 'Individual bounding 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`;
}
}
}
this.dataValues = outputString;
})
SaveButton({ icon: SaveIconStyle.LINES, buttonType: ButtonType.Circle })
.onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result == SaveButtonOnClickResult.SUCCESS) {
if (!this.subjectSegImage) {
return;
}
// 配置图片编码参数
let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 100 };
const imagePackerApi: image.ImagePacker = image.createImagePacker();
// 将PixelMap编码为JPEG格式的二进制数据
imagePackerApi.packToData(this.subjectSegImage, packOpts).then(async (buffer: ArrayBuffer) => {
try {
// 保存至相册中
const context: Context = this.getUIContext().getHostContext() as Context;
let helper = photoAccessHelper.getPhotoAccessHelper(context);
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpeg');
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
await fs.write(file.fd, buffer);
await fs.close(file.fd);
} catch (error) {
console.error(`error is ${error}`);
}
}).catch((error: BusinessError) => {
console.error(`Failed to pack the image. ${error.code} ${error.name} ${error.message}`);
});
}
});
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
private async selectImage() {
let uri = await this.openPhoto();
if (uri === undefined) {
}
this.loadImage(uri);
}
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();
photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult) => {
resolve(PhotoSelectResult.photoUris);
}).catch((err: BusinessError) => {
console.error(err.message);
reject();
});
});
}
private loadImage(names: string[]) {
setTimeout(async () => {
let imageSource: image.ImageSource | undefined = undefined;
let fileSource = await fileIo.open(names[0], fileIo.OpenMode.READ_ONLY);
imageSource = image.createImageSource(fileSource.fd);
this.chooseImage = await imageSource.createPixelMap();
}, 100
);
}
}
async function initSubjectSegmentation() {
const initResult = await subjectSegmentation.init();
console.info('subjectSegmentationSample', `Subject segmentation initialization result:${initResult}`);
}
async function releaseSubjectSegmentation() {
await subjectSegmentation.release();
} 避免将获得的PixelMap转换成JPEG,可考虑转换成PNG等支持透明通道的格式,例如上方问题代码里就转换成了JPEG格式。可以修改为其他格式,如PNG,完整的示例代码:
import { subjectSegmentation } from '@kit.CoreVisionKit';
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileIo } from '@kit.CoreFileKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import fs from '@ohos.file.fs';
@Entry
@Component
struct Index {
@State chooseImage: PixelMap | undefined = undefined;
subjectSegImage: PixelMap | undefined = undefined;
@State dataValues: string = '';
@State maxNum: string = '20';
async aboutToAppear() {
initSubjectSegmentation();
}
aboutToDisappear(): void {
releaseSubjectSegmentation();
}
build() {
Column() {
Image(this.chooseImage)
.objectFit(ImageFit.Contain)
.height('30%')
.accessibilityDescription('Image to be split')
Scroll() {
Text(this.dataValues)
.copyOption(CopyOptions.LocalDevice)
.margin(10)
.width('100%')
}
.height('20%')
Row() {
Text('Maximum number of principals:')
.fontSize(16)
TextInput({ placeholder: 'Please enter the maximum number of entities', text: this.maxNum })
.type(InputType.Number)
.placeholderColor(Color.Gray)
.fontSize(16)
.backgroundColor(Color.White)
.onChange((value: string) => {
this.maxNum = value;
})
}
.width('80%')
.margin(10)
Button('Select image')
.type(ButtonType.Capsule)
.fontColor(Color.White)
.alignSelf(ItemAlign.Center)
.width('80%')
.margin(10)
.onClick(() => {
// Pull up the gallery.
this.selectImage();
})
Button('Start subject segmentation')
.type(ButtonType.Capsule)
.fontColor(Color.White)
.alignSelf(ItemAlign.Center)
.width('80%')
.margin(10)
.onClick(async () => {
if (!this.chooseImage) {
return;
}
let visionInfo: subjectSegmentation.VisionInfo = {
pixelMap: this.chooseImage
};
let config: subjectSegmentation.SegmentationConfig = {
maxCount: parseInt(this.maxNum),
enableSubjectDetails: true,
enableSubjectForegroundImage: true
};
// Call the image segmentation API.
let data: subjectSegmentation.SegmentationResult =
await subjectSegmentation.doSegmentation(visionInfo, config);
this.subjectSegImage = data.fullSubject.foregroundImage;
let outputString = `Subjects: ${data.subjectCount}\n`;
outputString += `Maximum subjects: ${config.maxCount}\n`;
outputString += `Show bounding box of each subject: ${config.enableSubjectDetails ? 'Yes' : 'No'}\n\n`;
let segBox : subjectSegmentation.Rectangle = data.fullSubject.subjectRectangle;
let segBoxString = `Global bounding box:\nLeft: ${segBox.left}, Top: ${segBox.top}, Width: ${segBox.width}, Height: ${segBox.height}\n\n`;
outputString += segBoxString;
if (config.enableSubjectDetails) {
outputString += 'Individual bounding 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`;
}
}
}
this.dataValues = outputString;
})
SaveButton({ icon: SaveIconStyle.LINES, buttonType: ButtonType.Circle })
.onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result == SaveButtonOnClickResult.SUCCESS) {
if (!this.subjectSegImage) {
return;
}
// 配置图片编码参数
let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 100 };
const imagePackerApi: image.ImagePacker = image.createImagePacker();
// 将PixelMap编码为JPEG格式的二进制数据
imagePackerApi.packToData(this.subjectSegImage, packOpts).then(async (buffer: ArrayBuffer) => {
try {
// 保存至相册中
const context: Context = this.getUIContext().getHostContext() as Context;
let helper = photoAccessHelper.getPhotoAccessHelper(context);
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpeg');
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
await fs.write(file.fd, buffer);
await fs.close(file.fd);
} catch (error) {
console.error(`error is ${error}`);
}
}).catch((error: BusinessError) => {
console.error(`Failed to pack the image. ${error.code} ${error.name} ${error.message}`);
});
}
});
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
private async selectImage() {
let uri = await this.openPhoto();
if (uri === undefined) {
}
this.loadImage(uri);
}
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();
photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult) => {
resolve(PhotoSelectResult.photoUris);
}).catch((err: BusinessError) => {
console.error(err.message);
reject();
});
});
}
private loadImage(names: string[]) {
setTimeout(async () => {
let imageSource: image.ImageSource | undefined = undefined;
let fileSource = await fileIo.open(names[0], fileIo.OpenMode.READ_ONLY);
imageSource = image.createImageSource(fileSource.fd);
this.chooseImage = await imageSource.createPixelMap();
}, 100
);
}
}
async function initSubjectSegmentation() {
const initResult = await subjectSegmentation.init();
console.info('subjectSegmentationSample', `Subject segmentation initialization result:${initResult}`);
}
async function releaseSubjectSegmentation() {
await subjectSegmentation.release();
}