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

基于Azure目标检测结果的图片裁剪问题求助

问题:Azure Custom Vision目标检测后图片裁剪脚本错误排查

我在customvision.ai网站上拥有一个MS Azure目标检测模型,通过其API进行预测后,第一段PowerShell脚本可正常调用API并在图片中绘制出预测的边界框,但第二段使用相同坐标裁剪目标区域的脚本无法正确工作,裁剪出的是图片的其他部分,需要排查错误。

第一段可正常运行的脚本(预测并绘制边界框)

# First powershell script
# API call to object detection model to predict objects and their bounding boxes
$filePath = "C:\ImageOne.jpg"
$fileBytes = [System.IO.File]::ReadAllBytes($FilePath);
$Url = "<MyCustomVisionModelEndpoint>"
$headers = @{
          'Prediction-Key' = $customVisionPredictionKey
          'Content-Type' = 'application/octet-stream'
}
$proxy = [System.Net.WebRequest]::GetSystemWebProxy().GetProxy("https://<CustomVisionResourceName>.cognitiveservices.azure.com")
$APIresult = Invoke-RestMethod -Method 'Post' -Uri $url -Body $fileBytes -Headers $headers -UseDefaultCredentials -Proxy $proxy -ProxyUseDefaultCredentials

# Get Results and draw the predicted bounding boxes in the input image
$results = $APIresult.predictions | Where-Object {!$_.tagName.toString().contains("not") -and !$_.tagName.toString().contains("door") -and !$_.tagName.toString().contains("tyre") -and $_.probability -ge 0.02}
Add-Type -AssemblyName System.Drawing
$srcImage=[System.Drawing.Image]::FromFile($FilePath)
$height = $srcImage.height
$width = $srcImage.width
$graphics=[System.Drawing.Graphics]::FromImage($srcImage)
$pen = New-Object Drawing.Pen([System.Drawing.Color]::Blue,3);
$font = New-Object Drawing.Font("Arial", 7);
$brush = New-Object Drawing.SolidBrush([System.Drawing.Color]::Red);
foreach($result in $results)
{
 $left = $width * $result.boundingBox.left
 $top = $height * $result.boundingBox.top
 $PHeight = $height * $result.boundingBox.height
 $PWidth =  $width * $result.boundingBox.width
 $rect = New-Object Drawing.Rectangle($left, $top, $PWidth, $PHeight);
 $graphics.DrawRectangle($pen, $rect);
 $tag = "Tag: " + $result.tagName + " ,Probability: " + [math]::Round($result.probability * 100,2)
 $graphics.DrawString($tag,$font,$brush,$left, $top);
}
$graphics.Dispose()
if($results)
{
         $srcImage.Save("D:\Output.jpg")
}

第二段存在问题的裁剪脚本

# Second powershell script
Add-Type -AssemblyName System.Drawing
$filepath = "C:\ImageOne.jpg"
$srcImage=[System.Drawing.Image]::FromFile($FilePath)
$srcRect = New-Object Drawing.Rectangle(0,0,$srcImage.Width,$srcImage.Height)
# Here left, top, width, height co-ordinates comes from above powershell code which does predictions and draws rectangular bounding boxes
$destRect = New-Object Drawing.Rectangle([UInt32]($left),[UInt32]($top),[UInt32]($PWidth),[UInt32]($PHeight))
$bmp=new-object System.Drawing.Bitmap($destRect.Width,$destRect.Height)
$graphics=[System.Drawing.Graphics]::FromImage($bmp)
# I tried with [System.Drawing.GraphicsUnit]::Pixel also, but no use
$units = [System.Drawing.GraphicsUnit]::Point
$destRect = new-object Drawing.Rectangle($destRect.Left, $destRect.Top, $destRect.Width, $destRect.Height)
$srcRect = new-object Drawing.Rectangle($srcRect.Left, $srcRect.Top, $srcRect.Width, $srcRect.Height)
$graphics.DrawImage($srcImage, $srcRect, $destRect, $units)
$graphics.Dispose()
$bmp.Save("D:\test.jpg")

错误原因分析

  1. DrawImage参数顺序错误:你使用的DrawImage重载(DrawImage(Image, Rectangle, Rectangle, GraphicsUnit))中,第二个参数是目标画布上的绘制区域,第三个参数才是源图像中要裁剪的区域。你当前把源区域和目标区域的参数顺序搞反了,导致裁剪的区域完全错误。
  2. 多余的Rect重复创建:脚本中重复创建srcRect和destRect的代码没有意义,反而可能引入变量异常。
  3. 不必要的类型强制转换:将坐标强制转换为[UInt32]可能导致小数坐标被错误截断,而第一段脚本中直接使用计算后的数值创建Rectangle(其构造函数接受int类型,会自动进行合理的转换)。
  4. 变量传递风险:如果单独运行第二段脚本,$left、$top等变量未定义,会默认取0值,导致裁剪左上角区域。

修正后的裁剪脚本

如果是和第一段脚本结合运行(确保$left、$top、$PWidth、$PHeight已正确计算),修正后的脚本如下:

# 修正后的裁剪脚本(需在第一段脚本之后运行,或确保坐标变量已正确赋值)
Add-Type -AssemblyName System.Drawing
$filepath = "C:\ImageOne.jpg"
$srcImage = [System.Drawing.Image]::FromFile($FilePath)

# 使用第一段脚本中计算好的边界框坐标
$cropRect = New-Object Drawing.Rectangle([int]$left, [int]$top, [int]$PWidth, [int]$PHeight)

# 创建对应裁剪尺寸的位图
$croppedBmp = New-Object System.Drawing.Bitmap($cropRect.Width, $cropRect.Height)
$graphics = [System.Drawing.Graphics]::FromImage($croppedBmp)

# 正确调用DrawImage:目标区域是(0,0,裁剪宽,裁剪高),源区域是要裁剪的Rect
$graphics.DrawImage($srcImage, 
    (New-Object Drawing.Rectangle(0, 0, $cropRect.Width, $cropRect.Height)),
    $cropRect,
    [System.Drawing.GraphicsUnit]::Pixel
)

# 释放资源
$graphics.Dispose()
$srcImage.Dispose()
$croppedBmp.Save("D:\test.jpg")
$croppedBmp.Dispose()

如果需要单独运行裁剪脚本,需要先完成API预测并计算坐标,完整整合版脚本可以将两段逻辑合并,避免变量传递问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:40:21