• 华为云图像识别服务


    1. 什么是图像识别服务?

    图像识别服务是利用计算机对图像进行处理、分析和理解,以识别各种不同模式的目标和对象的技术,并对质量不佳的图像进行一系列的增强与重建技术手段,从而有效改善图像质量。

    比如:

    (1)翻拍识别
    准确识别出商品标签图片是否为经过二次翻拍、打印翻拍等手段处理的非合规图片。

    (2)低光照增强
    解决夜晚或光线暗区域拍摄的图像导致人眼或机器 "看不清” 暗光区域的问题。

    (3)图像去雾
    解决雾霾对成像质量的影响,使图片变得清晰。

    (4)超分图像构建
    解决图像在成像过程中像素过少导致的视觉信息不够或者由于压缩导致的图像信息丢失的问题。

    (5)图像标签
    领先的通用物体检测算法,有效检测出图片中超过3000类常见物体。包括千种通用物体以及数百种场景标签,一个图像可包含多个标签内容,语义内容非常丰富。更智能、准确的理解图像内容,让智能相册管理、照片检索和分类、基于场景内容或者物体的广告推荐等功能更加准确。

    image-20220516173542099

    (6)名人识别
    准确识别图像中包含的政治人物、影视明星及网红人物。

    (7)视频背景音乐识别
    可以实现视频中背景音乐的识别,完成视频获取、音频提取、音频识别并返回歌曲名称。

    (8)图片里的物体分类

    可以区分出图像中各种物体标签进行分类。

    image-20220516173630390

    华为云提供的图像识别支持以开放API(Application Programming Interface,应用程序编程接口)的方式提供给用户,用户通过实时访问和调用API获取推理结果,帮助用户自动采集关键数据,打造智能化业务系统,提升业务效率。

    image-20220515213501530

    2. 华为云图像识别服务功能

    目前华为云提供的图像识别接口支持图像标签识别,名人名片识别等。如果要识别自定义的目标,也可以采用ModelArts采集模型自行训练。

    2.1 实际应用场景举例

    图像标签识别功能:可识别上千种通用物体以及数百种场景标签,一个图像可包含多个标签内容,语义内容非常丰富。更智能、准确的理解图像内容,让智能相册管理、照片检索和分类、基于场景内容或者物体的广告推荐等功能更加准确。

    (1)场景分析

    图像标签功能可准确识别视频、图像内容,提高检索效率和精度,从而使得个性化推荐、内容检索和分发更为有效。

    image-20220516175226468

    (2)智能相册

    基于图像识别的标签可达近万种,智能相册可以自定义分类,比如“植物”、“美食”、“工作”等类别。方便用户管理相册,带来良好体验。

    image-20220516175251363

    (3)目标检测

    在建筑施工现场,基于定制化的图像识别目标检测系统,可实时监测现场人员是否佩戴安全帽,以降低安全风险。

    image-20220516175327889

    (4)图像搜索

    基于图像标签的图像搜索技术,不管用户输入关键字,还是输入一张图像,都可以快速搜索到想要的图像。

    image-20220516175358117

    2.2 使用限制

    使用华为云的图像识别服务时,需要了解一些约束限制。

    官网链接:https://support.huaweicloud.com/productdesc-image/image_01_0006.html

    (1)图像标签

    1、支持"华北-北京四、华东-上海一"区域。

    2、只支持识别PNG、JPEG、BMP格式的图片。

    3、图像各边的像素大小在15px至4096px之间。

    4、图片base64编码后大小不超过10MB(原图像大小不超过7.5MB)。

    5、默认API调用最大并发为10,更高并发需要提交工单申请。

    (2)名人识别

    1、支持"华北-北京四"区域。

    2、只支持识别处理PNG、JPEG、BMP格式的图片。

    3、图片base64编码后大小不超过10MB(原图像大小不超过7.5MB)。

    4、默认API调用最大并发为5,更高并发需要提交工单申请。

    2.3 计费说明

    链接:https://support.huaweicloud.com/productdesc-image/image_01_0008.html

    (1)计费模式

    图像识别已商用的服务提供两种计费模式供选择:按需计费和折扣套餐包计费。

    可以通图像识别提供的价格计算器,快速计算出购买图像识别的参考价格。

    (2)按需计费

    按需计费指按照调用次数阶梯价格计费,按月累计,一个自然月后次数清零重新累计。促销活动期间针对不同服务,每个用户每月有对应的免费调用次数,具体计费价格详情请参见图像识别价格详情。

    说明:

    只有调用成功才会计算调用次数,未用完的免费调用次数不流转到下一个月。

    计费规则:调用次数阶梯计费,按月累计,一个自然月后调用次数清零重新累计。
    计费周期:按小时计费,实时扣费(账单出账时间通常在当前计费周期结束后一小时内,具体出账时间以系统为准)。

    3. 动手实践-图像识别-标签识别

    本章节完整的介绍华为云图像识别服务使用方法,了解计费模式,了解调用方法,采用QT开发一款小软件,配合华为云提供的接口完成图像识别。

    3.1 开通服务

    官网链接:https://www.huaweicloud.com/

    (1)在网页顶上选择产品–>弹出窗口后选择人工智能–>图像识别

    image-20220516172701739

    (2)选择立即使用

    image-20220516172819895

    (3)授权OBS存储服务

    image-20220516172907739

    3.2 API的URL组成参数

    请求URI的组成部分:

    {URI-scheme} :// {Endpoint} / {resource-path} ? {query-string}
    
    • 1

    下面是URL组成部分的参数介绍:

    参数描述
    URI-scheme表示用于传输请求的协议,当前所有API均采用HTTPS协议。
    Endpoint指定承载REST服务端点的服务器域名或IP,不同服务不同区域的Endpoint不同,可以从终端节点中获取。例如:IAM服务在**“华北-北京一”区域的Endpoint为“iam.cn-north-1.myhuaweicloud.com”**。
    resource-path资源路径,也即API访问路径。从具体API的URI模块获取,例如:**“获取用户Token”**API的resource-path为“/v3/auth/tokens”。
    Query string查询参数,是可选部分,并不是每个API都有查询参数。查询参数前面需要带一个**“?”,形式为“参数名=参数取值”,例如“limit=10”**,表示查询不超过10条数据。

    例如:需要获取IAM在**“华北-北京一”区域的Token,则需使用“华北-北京一”区域的Endpoint(iam.cn-north-1.myhuaweicloud.com),并在获取用户Token的URI部分找到resource-path(/v3/auth/tokens**),拼接起来如下所示。

    https://iam.cn-north-1.myhuaweicloud.com/v3/auth/tokens
    
    • 1

    img

    3.3 请求参数说明

    自然图像的语义内容非常丰富,一个图像包含多个标签内容,图像标签服务准确识别自然图片中数百种场景、上千种通用物体及其属性,让智能相册管理、照片检索和分类、基于场景内容或者物体的广告推荐等功能更加直观。使用时用户发送待处理图片,返回图片标签内容及相应置信度。

    (1)URI格式

    格式: POST /v2/{project_id}/image/tagging

    参数是否必选参数类型描述
    project_idString用户的project_id登陆华为云 -> 用户中心 -> 我的凭证 -> api凭证 即可查看对应区域的项目ID。

    (2)请求参数

    参数是否必选参数类型描述
    X-Auth-TokenString用户Token。通过调用IAM服务获取用户Token接口获取(响应消息头中X-Subject-Token的值)。
    参数是否必选参数类型描述
    imageString与url二选一。图像数据,base64编码,要求base64编码后大小不超过10M,最短边至少15px,最长边最大4096px,支持JPG/PNG/BMP格式。
    urlString与image二选一。图片的URL路径,目前支持:公网HTTP/HTTPS URLOBS提供的URL,使用OBS数据需要进行授权。包括对服务授权、临时授权、匿名公开授权。
    languageStringzh:返回标签的语言类型为中文。en:返回标签的语言类型为英文。默认值为zh。
    thresholdFloat置信度的阈值(0~100),低于此置信数的标签,将不会返回。默认值:60最小值:0最大值:100缺省值:0.0
    limitInteger最多返回的tag数,默认值: 50。

    (3)响应参数

    状态码: 200

    参数参数类型描述
    resultresult object调用成功时为图片标签内容。调用失败时无此字段。
    参数参数类型描述
    tagsArray of ImageTaggingItemBody objects标签列表集合。
    参数参数类型描述
    confidenceString置信度,将Float型置信度转为String类型返回,取值范围:0-100。
    typeString标签的类别。有以下三种类别:object:实体标签scene:场景标签concept:概念标签
    tagString标签名称。
    i18n_tagi18n_tagobject标签的多种语言输出。
    i18n_typei18n_typeobject标签类别的多种语言输出。
    instancesImageTaggingInstanceobjects目标检测框信息,为空则表示没有目标检测框。
    参数参数类型描述
    zhString中文标签 。
    enString英文标签。
    参数参数类型描述
    zhString中文标签类别。
    enString英文标签类别。
    参数参数类型描述
    bounding_boxObject目标检测框位置信息,包括4个值:width:检测框区域宽度。height:检测框区域高度。top_left_x:检测框左上角到垂直轴距离。top_left_y:检测框左上角到水平轴距离。
    confidenceString检测标签置信度,将Float型置信度转为String类型返回,Float取值范围(0~100)。

    状态码: 400

    参数参数类型描述
    error_codeString调用失败时的错误码,调用成功时无此字段。
    error_msgString调用失败时的错误信息。调用成功时无此字段。

    (4)请求示例

    • 方式一:使用图片的BASE64编码

      POST https://{endpoint}/v2.0/image/tagging
      
      {
        "image" : "/9j/4AAQSkZJRgABAgEASABIAAD/4RFZRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAA...",
        "url" : "",
        "language" : "zh",
        "limit" : 5,
        "threshold" : 70.0
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 方式二:使用图片URL

      POST https://{endpoint}/v2.0/image/tagging
      
      {
        "image" : "",
        "url" : "https://BucketName.obs.myhuaweicloud.com/ObjectName",
        "language" : "zh",
        "limit" : 5,
        "threshold" : 70.0
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

    (5)响应示例

    状态码: 200

    成功响应结果

    {
      "result" : {
        "tags" : [ {
          "confidence" : "37.51",
          "instances" : [ {
            "confidence" : "92.38",
            "bounding_box" : {
              "height" : 133.32496056189905,
              "top_left_x" : 53.134917332575874,
              "top_left_y" : 254.21347984900842,
              "width" : 117.5866567171537
            }
          } ],
          "tag" : "人",
          "i18n_tag" : {
            "en" : "person",
            "zh" : "人"
          },
          "type" : "人类",
          "i18n_type" : {
            "en" : "Human",
            "zh" : "人类"
          }
        } ]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    状态码: 400

    失败响应结果

    {
      "error_code" : "AIS.0005",
      "error_msg" : "The service does not exist."
    }
    
    • 1
    • 2
    • 3
    • 4

    (6)状态码

    状态码描述
    200成功响应结果
    400失败响应结果

    3.3 使用API Explorer调试

    为了更加方便的了解API调用参数,以及使用方式,可以使用API Explorer调试接口在线调试。

    https://apiexplorer.developer.huaweicloud.com/apiexplorer/debug?product=Image&api=RunImageTagging

    image-20220518145946811

    图像参数支持base64格式或者公网的URL图片地址链接,我这里在百度上找了一张风景图片进行识别测试。

    image-20220518151118832

    API请求总结:

    请求URL:https://image.cn-north-4.myhuaweicloud.com/v2/0e5957be8a00f53c2fa7c0045e4d8fbf/image/tagging
    
    请求体: 
    {
     "url": "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1114%2F113020142315%2F201130142315-5-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1655449768&t=47ba9dbefe08d074e88f937bfc6baac1"
    }
    
    返回结果:
    {
     "result": {
      "tags": [
       {
        "confidence": "98.47",
        "i18n_tag": {
         "en": "Tree",
         "zh": "树"
        },
        "i18n_type": {
         "en": "Tree",
         "zh": "树"
        },
        "instances": [
         {
          "bounding_box": {
           "height": 440.74065135075494,
           "top_left_x": 16.602098024808445,
           "top_left_y": 5.777478218078613,
           "width": 427.61458616990313
          },
          "confidence": "46.38"
         },
         {
          "bounding_box": {
           "height": 355.3575699145977,
           "top_left_x": 0,
           "top_left_y": 313.1353580034696,
           "width": 502.20504173865686
          },
          "confidence": "44.64"
         }
        ],
        "tag": "树",
        "type": "树"
       },
       {
        "confidence": "72.08",
        "i18n_tag": {
         "en": "Snow",
         "zh": "雪"
        },
        "i18n_type": {
         "en": "Natural scenery",
         "zh": "自然风景"
        },
        "instances": [],
        "tag": "雪",
        "type": "自然风景"
       },
       {
        "confidence": "71.90",
        "i18n_tag": {
         "en": "Mountain",
         "zh": "山"
        },
        "i18n_type": {
         "en": "Natural scenery",
         "zh": "自然风景"
        },
        "instances": [],
        "tag": "山",
        "type": "自然风景"
       },
       {
        "confidence": "70.83",
        "i18n_tag": {
         "en": "Lake",
         "zh": "湖"
        },
        "i18n_type": {
         "en": "Natural scenery",
         "zh": "自然风景"
        },
        "instances": [],
        "tag": "湖",
        "type": "自然风景"
       },
       {
        "confidence": "64.86",
        "i18n_tag": {
         "en": "Cloud",
         "zh": "云"
        },
        "i18n_type": {
         "en": "Natural scenery",
         "zh": "自然风景"
        },
        "instances": [],
        "tag": "云",
        "type": "自然风景"
       },
       {
        "confidence": "63.13",
        "i18n_tag": {
         "en": "Ship",
         "zh": "船"
        },
        "i18n_type": {
         "en": "Water transportation",
         "zh": "水上交通"
        },
        "instances": [],
        "tag": "船",
        "type": "水上交通"
       },
       {
        "confidence": "62.83",
        "i18n_tag": {
         "en": "Plant",
         "zh": "植物"
        },
        "i18n_type": {
         "en": "Other plants",
         "zh": "其他植物"
        },
        "instances": [],
        "tag": "植物",
        "type": "其他植物"
       }
      ]
     }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131

    3.4 编写图像识别测试软件

    下面采用开发一个小工具,利用华为云的图像识别接口实现图像识别,演示整个接口的使用流程。

    (1)设计的界面

    image-20220518163003595

    (2)运行效果

    返回的结果是json数据,这里没有对结果进行解析处理,直接将结果显示在界面上了。

    image-20220523164925082

    image-20220523165248790

    image-20220523165209350

    (4)token更新: 实现代码

    /*
    功能: 获取token
    */
    void Widget::GetToken()
    {
        //表示获取token
        function_select=3;
    
        QString requestUrl;
        QNetworkRequest request;
    
        //设置请求地址
        QUrl url;
    
        //获取token请求地址
        requestUrl = QString("https://iam.%1.myhuaweicloud.com/v3/auth/tokens")
                     .arg(SERVER_ID);
    
        //自己创建的TCP服务器,测试用
        //requestUrl="http://10.0.0.6:8080";
    
        //设置数据提交格式
        request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;charset=UTF-8"));
    
        //构造请求
        url.setUrl(requestUrl);
    
        request.setUrl(url);
    
        QString text =QString("{\"auth\":{\"identity\":{\"methods\":[\"password\"],\"password\":"
        "{\"user\":{\"domain\": {"
        "\"name\":\"%1\"},\"name\": \"%2\",\"password\": \"%3\"}}},"
        "\"scope\":{\"project\":{\"name\":\"%4\"}}}}")
                .arg(MAIN_USER)
                .arg(IAM_USER)
                .arg(IAM_PASSWORD)
                .arg(SERVER_ID);
    
        //发送请求
        manager->post(request, text.toUtf8());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    (5)图像识别接口调用: 实现代码

    void Widget::on_pushButton_clicked()
    {
           function_select=2;
           QString requestUrl;
           QNetworkRequest request;
    
           QString filename=QFileDialog::getOpenFileName(this,"选择打开的文件","C:/",tr("*.bmp *.jpg *.png"));
           //filename==选择文件的绝对路径
           if(filename.isEmpty())return;
    
           QImage image(filename);
           ui->label->setPixmap(QPixmap::fromImage(image));
    
           //存放图片BASE64编码
           QString imgData;
    
           //设置请求地址
           QUrl url;
    
           //请求地址
           requestUrl = QString("https://image.%1.myhuaweicloud.com/v2/%2/image/tagging")
                   .arg(SERVER_ID)
                   .arg(PROJECT_ID);
    
           //设置数据提交格式
           request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;charset=UTF-8"));
    
           //将图片进行Base64编码
           imgData = QString(toBase64(image)); //编码后的图片大小不超过2M
           //设置token
           request.setRawHeader("X-Auth-Token",Token);
    
           //构造请求
           url.setUrl(requestUrl);
           request.setUrl(url);
    
           QString post_param=QString
                      ("{"
                        "\"image\": \"%1\""
                       "}").arg(imgData);
    
           //发送请求
           manager->post(request, post_param.toUtf8());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    (6)返回的分析结果

    //解析反馈结果
    void Widget::replyFinished(QNetworkReply *reply)
    {
        QString displayInfo="";
    
        int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    
        //读取所有数据
        QByteArray replyData = reply->readAll();
    
        qDebug()<<"状态码:"<<statusCode;
        qDebug()<<"反馈的数据:"<<QString(replyData);
    
        if(function_select==2)
        {
            ui->plainTextEdit->insertPlainText(QString(replyData));
        }
    
        //更新token
        if(function_select==3)
        {
            displayInfo="token 更新失败.";
            //读取HTTP响应头的数据
            QList<QNetworkReply::RawHeaderPair> RawHeader=reply->rawHeaderPairs();
            qDebug()<<"HTTP响应头数量:"<<RawHeader.size();
            for(int i=0;i<RawHeader.size();i++)
            {
                QString first=RawHeader.at(i).first;
                QString second=RawHeader.at(i).second;
                if(first=="X-Subject-Token")
                {
                    Token=second.toUtf8();
                    displayInfo="token 更新成功.";
    
                    //保存到文件
                    SaveDataToFile(Token);
    
                    int value;
                    value=QMessageBox::information(this,"提示",displayInfo, QMessageBox::Ok,QMessageBox::Ok);
                    break;
                }
            }
            return;
        }
    
        //判断状态码
        if(200 != statusCode)
        {
            //解析数据
            QJsonParseError json_error;
            QJsonDocument document = QJsonDocument::fromJson(replyData, &json_error);
            if(json_error.error == QJsonParseError::NoError)
            {
                //判断是否是对象,然后开始解析数据
                if(document.isObject())
                {
                    QString error_str="";
                    QJsonObject obj = document.object();
                    QString error_code;
                    //解析错误代码
                    if(obj.contains("error_code"))
                    {
                        error_code=obj.take("error_code").toString();
                        error_str+="错误代码:";
                        error_str+=error_code;
                        error_str+="\n";
                    }
                    if(obj.contains("error_msg"))
                    {
                        error_str+="错误消息:";
                        error_str+=obj.take("error_msg").toString();
                        error_str+="\n";
                    }
    
                    int value;
                    value=QMessageBox::information(this,"提示",error_str, QMessageBox::Ok,QMessageBox::Ok);
                }
             }
            return;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    4. 总结

    计算机图像识别技术是以计算机系统为平台,对图像进行分离和识别,从中破获和分析信息,而后反馈给使用者。这一技术的重要价值在于能够替代人眼来认识世界,并实现对人类视觉功能的放大。目前,图像识别技术在生活已经应用的非常广泛,涉及的行业也非常多,这篇文章介绍的主要是名人识别、物体标签识别、物体分类,翻拍识别等。华为云的图像识别接口里还提供了文字识别、表格识别、图像搜索等很多接口,如果现有的图像识别接口还无法满足需求,可以自己利用ModelArts框架进行训练,得到自己专属的图像识别模型。

  • 相关阅读:
    Chatgpt介绍及搭建步骤
    LeetCode高频题:戈壁滩种树,一排n棵树,至少有k棵树存活时,最终形成的风景线有多少不同的情况
    postgresql简单导出数据与手动本地恢复(小型数据库)
    【网络服务&数据库教程】07 ELK日志解决方案
    芯片公司名称
    深度学习之基于YoloV5-Deepsort人物识别与追踪系统
    Ansible-自动运维工具
    Mysql笔记1
    Acwing.4736步行者(模拟)
    js 删除数组中指定元素——5种方式
  • 原文地址:https://blog.csdn.net/xiaolong1126626497/article/details/124931365