谁家没几张有魔力的老照片,虽然背景简单、pose不经设计,但有了几十年时间发酵,也成了一段父母长辈们年轻岁月的故事,意义非凡。本周末父亲节报到,我厂程序员阿强苦思冥想,如何给老爸带来不一样的节日礼物?环顾四周,桌上一个旧相册激发了他的灵感。陈旧泛黄的照片,封藏了老爸年轻时意气风发的模样,为何不用自己的技术,让老爸重现往日时光呢?想到做到!他旋即就对老爸珍藏的旧照下了一番功夫,运用机器学习图像超分辨率,将那些斑驳模糊、褶皱破损的老照片,一键高清,效果惊艳老爸!
效果示例
图像超分辨率
图像超分辨率即将低分辨率、成像模糊的图片恢复到高分辨率,提升图像像素密度,还原更多原图场景成像细节。
图像超分辨率在计算机视觉领域拥有广泛应用需求,助力高效提升图像模式识别能力和图像分析效果。日渐精进的图像超分辨率技术也在我们的生活工作中扮演越来越重要的角色,小到一张个人模糊旧照的清晰化处理,大到医疗图像诊断、安防监控、甚至是卫星成像等领域的诸多运用。
华为机器学习-图像超分辨率提供了1x和3x的超分能力。1x超分去除压缩噪声,3x超分不仅有效抑制压缩噪声,而且提供3倍的放大能力。支持通用场景超分(绿植、美食、工卡等),如提升网络上低质图片画质,在阅读新闻时获取更清晰大图等。
开发准备
Maven仓和SDK的配置步骤可以参考开发者网站中的应用开发介绍:https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides-V5/imagesuper-resolution-sdk-0000001052064928-V5?ha_source=hms1
配置集成的SDK包
在应用的build.gradle文件中,dependencies内添加图像超分的SDK依赖
implementation'com.huawei.hms:ml-computer-vision-imagesuperresolution:2.0.4.300'
implementation'com.huawei.hms:ml-computer-vision-imagesuperresolution-model:2.0.4.300'
配置AndroidManifest.xml
打开main文件夹中的AndroidManifest.xml文件,可以根据场景和使用需要,配置读取和写入手机存储的权限,在<application>前添加
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
在<application>内添加如下语句,当应用安装后,会自动更新最新的机器学习模型到设备
<meta-data
android:name="com.huawei.hms.ml.DEPENDENCY"
android:value= "imagesuperresolution"/>
详细开发步骤
配置存储权限申请
在MainActivity的onCreate()方法中,首先对手机存储的读取权限进行判断,如果未获取权限,则通过requestPermissions进行申请,如果已经获取了,则调用的startSuperResolutionActivity()方法,进行图像超分操作
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE);
} else {
startSuperResolutionActivity();
}
检查权限申请的结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startSuperResolutionActivity();
} else {
Toast.makeText(this, "Permission application failed, you denied the permission", Toast.LENGTH_SHORT).show();
}
}
}
权限申请完毕之后,创建Button,并配置点击Button后对存储内的图片进行读取
private void selectLocalImage() {
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, REQUEST_SELECT_IMAGE);
}
配置图像超分辨率分析器
在进行图像超分处理之前,要创建并配置图像超分辨率分析器,本例中配置了1x和3x两种超分参数,通过selectItem的不同取值进行对应的选择
private MLImageSuperResolutionAnalyzer createAnalyzer() {
if (selectItem == INDEX_1X) {
return MLImageSuperResolutionAnalyzerFactory.getInstance().getImageSuperResolutionAnalyzer();
} else {
MLImageSuperResolutionAnalyzerSetting setting = new MLImageSuperResolutionAnalyzerSetting.Factory()
.setScale(MLImageSuperResolutionAnalyzerSetting.ISR_SCALE_3X)
.create();
return MLImageSuperResolutionAnalyzerFactory.getInstance().getImageSuperResolutionAnalyzer(setting);
}
}
构造并处理图像
在对图像进行超分处理之前,需要将其转换为ARGB8888类型的Bitmap格式,再创建为MLFrame。首先在添加图片后,获取图片的相关信息,覆写onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_SELECT_IMAGE && resultCode == Activity.RESULT_OK) {
if (data != null) {
imageUri = data.getData();
}
reloadAndDetectImage(true, false);
} else if (resultCode == REQUEST_SELECT_IMAGE && resultCode == Activity.RESULT_CANCELED) {
finish();
}
}
将Bitmap创建为MLFrame
srcBitmap = BitmapUtils.loadFromPathWithoutZoom(this, imageUri, IMAGE_MAX_SIZE, IMAGE_MAX_SIZE);
MLFrame frame = MLFrame.fromBitmap(srcBitmap);
之后调用asyncAnalyseFrame异步处理方法,对所加载的图片进行超分处理
Task<MLImageSuperResolutionResult> task = analyzer.asyncAnalyseFrame(frame);
task.addOnSuccessListener(new OnSuccessListener<MLImageSuperResolutionResult>() {
public void onSuccess(MLImageSuperResolutionResult result) {
// Recognition success.
desBitmap = result.getBitmap();
setImage(desImageView, desBitmap);
setImageSizeInfo(desBitmap.getWidth(), desBitmap.getHeight());
}
}).addOnFailureListener(new OnFailureListener() {
public void onFailure(Exception e) {
// Recognition failure.
Log.e(TAG, "Failed." + e.getMessage());
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
识别完成后,停止分析器
if (analyzer != null) {
analyzer.stop();
}
同时覆写Activity的onDestroy方法对Bitmap资源进行释放
@Override
protected void onDestroy() {
super.onDestroy();
if (srcBitmap != null) {
srcBitmap.recycle();
}
if (desBitmap != null) {
desBitmap.recycle();
}
if (analyzer != null) {
analyzer.stop();
}
}
源码
Demo已在相关社区进行开源,欢迎开发者关注、下载并提供宝贵意见:
>>访问华为机器学习服务官网,了解更多相关内容
>>获取华为机器学习服务开发指导文档
>>华为机器学习服务开源仓库地址:GitHub、Gitee
点击右上角头像右方的关注,第一时间了解华为移动服务最新技术~