继上次完成基础视觉API的开发之后,老板似乎对我的图像处理能力充满了信心。他又给我布置了一项新的任务:实现物体检测功能。这个功能可以用来识别图片中的不同物体,并标记出它们的位置,比如检测一张街景照片中有几辆车,哪里有人等。老板依旧风格如故,甩给我一个链接——鸿蒙的物体检测API文档。

image.png

我心里想着,这次的任务听起来很有意思,也充满挑战。物体检测与之前的人脸检测和主体分割不同,它的目标是尽可能多地识别出图片中的所有物体。虽然挑战大,但这也让我非常兴奋。于是我决定立刻动手,看看能不能把这个有趣的功能搞定。

第一步:理解物体检测API

首先,我还是先从文档入手,了解物体检测API的功能。MLObjectAnalyzer是这次开发的核心类,文档中介绍了它的各种功能和参数配置。物体检测的目标是从图像中识别出物体并标记它们的位置,同时可以给出每个物体的类别信息。这些信息在很多应用场景中都非常有用,比如智能相册的分类、物流中货物自动识别等。

image.png

文档的内容并不复杂,但如何将这些基础功能整合到我们项目的实际需求中,这需要我好好思考。因此,我决定先编写一个小demo,看看物体检测的效果,再根据需求进行功能拓展。

第二步:配置开发环境并动手实现

首先,根据文档的提示,我在项目中引入了物体检测的依赖:

dependencies {
    implementation 'com.huawei.hms:ml-computer-vision:5.0.0.300'
}

接下来,我开始编写物体检测的代码。为了实现这个功能,我创建了一个类来封装物体检测的逻辑。

  1. 初始化物体检测器

首先,我们需要初始化物体检测器。在初始化的过程中,可以配置一些参数,比如是否启用多类别检测、是否检测所有物体等。

import com.huawei.hms.mlsdk.objects.MLObjectAnalyzer;
import com.huawei.hms.mlsdk.objects.MLObjectAnalyzerSetting;
import com.huawei.hms.mlsdk.common.MLFrame;

public class ObjectDetectionDemo {
    private MLObjectAnalyzer objectAnalyzer;

    public void initializeAnalyzer() {
        MLObjectAnalyzerSetting setting = new MLObjectAnalyzerSetting.Factory()
                .setAnalyzerType(MLObjectAnalyzerSetting.TYPE_PICTURE)
                .allowMultiResults()
                .allowClassification()
                .create();
        objectAnalyzer = MLObjectAnalyzer.Factory.getInstance().getLocalAnalyzer(setting);
    }
}

在这里,我配置了检测类型为图片检测,并启用了多物体检测和分类功能。这样设置后,检测器将能够识别出图片中的多个物体并对它们进行分类。

  1. 实现物体检测

初始化完成后,我编写了一个方法,用于检测图片中的物体。

public void detectObjects(Bitmap bitmap) {
    MLFrame frame = MLFrame.fromBitmap(bitmap);
    Task<List<MLObject>> task = objectAnalyzer.asyncAnalyseFrame(frame);
    
    task.addOnSuccessListener(objects -> {
        for (MLObject obj : objects) {
            Rect bounds = obj.getBorder();
            int type = obj.getTypeIdentity();
            System.out.println("检测到的物体类别: " + type + ", 位置: " + bounds.toString());
        }
    }).addOnFailureListener(e -> {
        System.err.println("物体检测失败: " + e.getMessage());
    });
}

在这段代码中,asyncAnalyseFrame方法会对输入的图像进行物体检测,并返回检测到的物体列表。每个物体都有一个边界框,用于标记它在图像中的位置。同时,还会返回物体的类别,这些信息可以用来进一步处理和分类。

第三步:测试与调优

写完代码之后,我对物体检测功能进行了各种测试。我选择了不同类型的图片,包括街景、室内物品、人群等,来检验物体检测的效果。刚开始的时候,检测的结果还不错,能识别出大部分物体,但也有一些问题,比如有时候会误将背景中的物体当作目标检测出来。

为了提升检测的准确性,我对设置参数进行了调整,比如通过设置setClassificationConfidenceThreshold来提高分类的置信度阈值,减少误检的可能性。

MLObjectAnalyzerSetting setting = new MLObjectAnalyzerSetting.Factory()
        .setAnalyzerType(MLObjectAnalyzerSetting.TYPE_PICTURE)
        .allowMultiResults()
        .allowClassification()
        .setClassificationConfidenceThreshold(0.7f)
        .create();

通过提高置信度阈值,检测的准确性有了一定的提升。同时,我还对图像进行了预处理,比如调整亮度、对比度,以确保图像中的物体更容易被检测到。在经过几轮测试和调整之后,最终的检测效果让我感到比较满意,基本上可以准确识别出图像中的各类物体。

第四步:功能扩展与实际应用

在完成物体检测的基本功能之后,我开始思考如何将它应用到公司现有的项目中。结合之前的主体分割和基础视觉功能,我尝试将物体检测整合进一个完整的图像处理工具中。

比如,我们可以实现一个智能相册应用,用户可以上传自己的照片,系统自动检测并分类其中的物体,比如汽车、宠物、建筑等。这种分类功能可以极大地方便用户管理自己的相册。为了实现这一目标,我编写了一个简单的分类逻辑,将检测到的物体按类别存储到不同的相册中。

public void categorizeObjects(List<MLObject> objects) {
    Map<Integer, List<MLObject>> categorizedObjects = new HashMap<>();
    for (MLObject obj : objects) {
        int type = obj.getTypeIdentity();
        categorizedObjects.computeIfAbsent(type, k -> new ArrayList<>()).add(obj);
    }
    // 根据类别将物体进行分类保存
    for (Map.Entry<Integer, List<MLObject>> entry : categorizedObjects.entrySet()) {
        System.out.println("类别: " + entry.getKey() + ", 数量: " + entry.getValue().size());
    }
}

通过这种方式,系统可以自动分类图片中的物体,用户只需要简单操作,就能找到自己需要的照片,大大提升了相册管理的便捷性。

最后的感悟

在这次物体检测功能的开发过程中,我感受到了图像处理的广阔应用前景。物体检测不仅仅是一个技术实现,更是为了解决实际问题,提升用户体验的一种手段。从实现单一功能,到思考如何将其应用到实际场景,再到功能的优化和扩展,这个过程让我更加理解了开发工作的价值所在。

我学会了如何通过调整参数来提高检测的准确性,也学会了如何通过多次测试不断完善功能。每一次的失败和改进,都是在为最终的成功打下基础。尤其是在面对复杂的图像场景时,如何结合之前学到的知识,比如灰度转换、边缘检测等基础视觉功能,来进行预处理,这些都是非常有用的经验。

image.png

如果你也在从事类似的开发工作,我的建议是:不要害怕困难,勇敢尝试新技术。每一次的探索都是一个成长的机会。保持对技术的好奇心,始终思考如何将技术应用到实际问题中去,最终你会发现,这些看似困难的任务,实际上是让你变得更好的阶梯。开发不仅是技术的实现,更是创造价值的过程。


郝敬学
22 声望1 粉丝