You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Azure Custom Vision API创建项目时的404资源未找到错误

Azure Custom Vision Java项目创建404错误排查与解决

问题描述

按照微软文档用Java实现Azure Custom Vision图像分类模型训练,执行Gradle构建运行时出现以下错误:

Exception in thread "main" com.microsoft.azure.cognitiveservices.vision.customvision.training.models.CustomVisionErrorException: Status code 404, {"error":{"code":"404","message": "Resource not found"}}

错误触发点为createProject方法中的Project project=trainer.createProject().withName("Moon-Phases-Trainer").execute();语句,目标是在Vision Studio中创建项目,但连接训练API时失败。

完整代码如下:

class CustomVisionQuickstart
{
    final static String trainingApiKey=System.getenv("VISION_TRAINING_KEY");
    final static String trainingEndpoint=System.getenv("VISION_TRAINING_ENDPOINT");
    final static String predictionApiKey=System.getenv("VISION_PREDICTION_KEY");
    final static String predictionEndpoint=System.getenv("VISION_PREDICTION_ENDPOINT");
    final static String predictionResourceID=System.getenv("VISION_PREDICTION_RESOURCE_ID");

    private static Tag newMoonTag, waxingCrescentTag, firstQuarterTag, waxingGibbousTag,
            fullTag, waningGibbousTag, thirdQuarterTag, waningCrescentTag;


    public static void main(String[] args) throws InterruptedException
    {
//        System.out.println(trainingApiKey);
//        System.out.println(trainingEndpoint);
        CustomVisionTrainingClient trainClient=CustomVisionTrainingManager
                .authenticate(trainingEndpoint,trainingApiKey)
                .withEndpoint(trainingEndpoint);

        CustomVisionPredictionClient predictor=CustomVisionPredictionManager
                .authenticate(predictionEndpoint,predictionApiKey)
                .withEndpoint(predictionEndpoint);

        Project project=createProject(trainClient);
        addTags(trainClient, project);
        uploadImages(trainClient, project);
        trainProject(trainClient, project);
        publishIteration(trainClient, project);
        testProject(predictor, project);
    }
    public static Project createProject(CustomVisionTrainingClient trainClient)
    {
        Trainings trainer=trainClient.trainings();
        System.out.println("Creating Project");
        Project project=trainer.createProject().withName("Moon-Phases-Trainer").execute();
        return project;
    }
    public static void addTags(CustomVisionTrainingClient trainClient, Project project)
    {
        Trainings trainer = trainClient.trainings();

        newMoonTag = trainer.createTag().withProjectId(project.id()).withName("New Moon").execute();
        waxingCrescentTag = trainer.createTag().withProjectId(project.id()).withName("Waxing Crescent Moon").execute();
        firstQuarterTag = trainer.createTag().withProjectId(project.id()).withName("First Quarter Moon").execute();
        waxingGibbousTag = trainer.createTag().withProjectId(project.id()).withName("Waxing Gibbous Moon").execute();
        fullTag = trainer.createTag().withProjectId(project.id()).withName("Full Moon").execute();
        waningGibbousTag = trainer.createTag().withProjectId(project.id()).withName("Waning Gibbous Moon").execute();
        thirdQuarterTag = trainer.createTag().withProjectId(project.id()).withName("Third Quarter Moon").execute();
        waningCrescentTag = trainer.createTag().withProjectId(project.id()).withName("Waning Crescent Moon").execute();
    }
    public static void uploadImages(CustomVisionTrainingClient trainClient, Project project)
    {
        Trainings trainer=trainClient.trainings();
        for (int x=0;x<4;x++)
        {
            String fileName="New_Moon_"+x+".jpg";
            byte contents[]=getImage("/Moons",fileName);
            addImageToProject(trainer,project,fileName,contents,newMoonTag.id(),null);
        }
        for (int x=0;x<9;x++)
        {
            String fileName="Waxing_Crescent_"+x+".jpg";
            byte contents[]=getImage("/Moons",fileName);
            addImageToProject(trainer,project,fileName,contents,waxingCrescentTag.id(),null);
        }
        for (int x=0;x<8;x++)
        {
            String fileName="First_Quarter_"+x+".jpg";
            byte contents[]=getImage("/Moons",fileName);
            addImageToProject(trainer,project,fileName,contents,firstQuarterTag.id(),null);
        }
        for (int x=0;x<13;x++)
        {
            String fileName="Waxing_Gibbous_"+x+".jpg";
            byte contents[]=getImage("/Moons",fileName);
            addImageToProject(trainer,project,fileName,contents,waxingGibbousTag.id(),null);
        }
        for (int x=0;x<5;x++)
        {
            String fileName="Full_Moon_"+x+".jpg";
            byte contents[]=getImage("/Moons",fileName);
            addImageToProject(trainer,project,fileName,contents,fullTag.id(),null);
        }
        for (int x=0;x<15;x++)
        {
            String fileName="Waning_Gibbous_"+x+".jpg";
            byte contents[]=getImage("/Moons",fileName);
            addImageToProject(trainer,project,fileName,contents,waningGibbousTag.id(),null);
        }
        for (int x=0;x<6;x++)
        {
            String fileName="Third_Quarter_"+x+".jpg";
            byte contents[]=getImage("/Moons",fileName);
            addImageToProject(trainer,project,fileName,contents,thirdQuarterTag.id(),null);
        }
        for (int x=0;x<13;x++)
        {
            String fileName="Waning_Crescent_"+x+".jpg";
            byte contents[]=getImage("/Moons",fileName);
            addImageToProject(trainer,project,fileName,contents,waningCrescentTag.id(),null);
        }
    }
    private static void addImageToProject(Trainings trainer, Project project, String fileName, byte[] contents, UUID tag, double[] regionValues)
    {
        System.out.println("Adding image: "+fileName);
        ImageFileCreateEntry file=new ImageFileCreateEntry().withName(fileName).withContents(contents);
        ImageFileCreateBatch batch=new ImageFileCreateBatch().withImages(Collections.singletonList(file));
        if(regionValues!=null)
        {
            Region region=new Region().withTagId(tag).withLeft(regionValues[0]).withTop(regionValues[1]).withWidth(regionValues[2]).withHeight(regionValues[3]);
            file=file.withRegions(Collections.singletonList(region));
        }
        else
            batch = batch.withTagIds(Collections.singletonList(tag));
        trainer.createImagesFromFiles(project.id(),batch);
    }
    private static byte[] getImage(String folder, String fileName)
    {
        try
        {
            return ByteStreams.toByteArray(CustomVisionQuickstart.class.getResourceAsStream(folder+"/"+fileName));
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }
    public static Iteration trainProject(CustomVisionTrainingClient trainClient, Project project) throws InterruptedException
    {
        System.out.println("Training...");
        Trainings trainer=trainClient.trainings();
        Iteration iteration=trainer.trainProject(project.id(),new TrainProjectOptionalParameter());

        while(iteration.status().equals("Training"))
        {
            System.out.println("Training Status: " + iteration.status());
            Thread.sleep(1000);
            iteration = trainer.getIteration(project.id(), iteration.id());
        }
        System.out.println("Training Status: " + iteration.status());
        return iteration;
    }
    public static void publishIteration(CustomVisionTrainingClient trainClient, Project project) throws InterruptedException
    {
        Trainings trainer=trainClient.trainings();
        Iteration iteration=trainProject(trainClient,project);
        String publishedModelName="myMoonPhaseModel";
        trainer.publishIteration(project.id(),iteration.id(),publishedModelName,predictionResourceID);
    }
    public static void testProject(CustomVisionPredictionClient predictor, Project project)
    {
        byte[] testImeage=getImage("/Moons","testImage.jpg");
        String publishedModelName = "myMoonPhaseModel";
        ImagePrediction results=predictor.predictions().classifyImage().withProjectId(project.id()).withPublishedName(publishedModelName).withImageData(testImeage).execute();
        for (Prediction prediction : results.predictions())
            System.out.println(String.format("\t%s: %.2f%%", prediction.tagName(), prediction.probability() * 100.0f));
    }
}

可能原因

  • 训练端点/密钥错误:使用了预测端点/密钥代替训练专用的,或者端点格式不正确(如缺失末尾斜杠、区域不匹配)。
  • 环境变量未正确加载:VISION_TRAINING_ENDPOINT或VISION_TRAINING_KEY未设置,或设置的值与Azure门户中的资源信息不符。
  • Custom Vision资源状态异常:Azure上的资源未成功部署、被暂停或删除。

解决方案

  1. 验证训练端点与密钥

    • 登录Azure门户,找到你的Custom Vision资源,进入「密钥和端点」页面,确认训练端点(格式示例:https://eastus.api.cognitive.microsoft.com/)和训练密钥,注意区分训练与预测的两组密钥/端点,不要混用。
    • 确保环境变量VISION_TRAINING_ENDPOINT和VISION_TRAINING_KEY的值与上述确认的信息完全一致。
  2. 检查环境变量加载情况

    • 取消代码中// System.out.println(trainingApiKey);和// System.out.println(trainingEndpoint);的注释,运行程序后查看控制台输出,确认变量值是否正确加载,避免因环境变量未设置导致空值或错误值。
  3. 修正客户端初始化代码
    原代码中CustomVisionTrainingManager.authenticate方法已接受端点参数,无需重复调用withEndpoint,可简化为:

    CustomVisionTrainingClient trainClient = CustomVisionTrainingManager
        .authenticate(trainingApiKey)
        .withEndpoint(trainingEndpoint);
    

    该调整可避免潜在的端点重复配置问题。

  4. 确认资源状态与区域一致性

    • 在Azure门户确认Custom Vision资源处于「运行中」状态,无异常。
    • 确保训练端点的区域(如eastus)与资源创建时选择的区域完全一致,区域不匹配会导致API请求无法找到对应资源。

内容的提问来源于stack exchange,提问作者Ppp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 09:52:33