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

在Delphi中使用Android版OpenCV操作JList时遇访问违例求助

问题解决:Android OpenCV轮廓遍历访问冲突错误

错误根源

  1. List初始化方式错误:手动初始化固定容量的ArrayList,OpenCV的findContours需要接收空的、可动态扩容的List对象,强制转换为JList也可能导致类型不匹配。
  2. 轮廓元素类型处理错误:LContoursList中的每个元素是JMatOfPoint类型,直接调用toString()无法正确获取信息,甚至引发内存访问异常。
  3. 未正确释放资源:创建的Mat、Bitmap等对象未手动释放,可能导致内存溢出引发访问冲突。

修复后的代码

var
  LSrcMat: JMat;
  LDstMat: JMat;
  LHierarchyMat: JMat;
  LJBitmap: JBitmap;
  LThreshold: Double;
  LContoursList: TJArrayList; // 改用TJArrayList而非JList
  trash, maxval: Double;
  i, type_: Integer;
  LContour: JMatOfPoint;
  LPoints: TJavaArray<Integer>;
begin
  FOpenCVInProgress := True;
  LContoursList := TJArrayList.JavaClass.init; // 初始化空的ArrayList
  try
    trash := StrToFloat(edtTrash.Text);
    maxval := StrToFloat(edtMaxVal.Text);
    type_ := StrToInt(edtType.Text);
    LSrcMat := TJMat.JavaClass.init;
    LDstMat := TJMat.JavaClass.init;
    LHierarchyMat:= TJMat.JavaClass.init;
    LJBitmap := TJBitmap.JavaClass.createBitmap(Trunc(FCamBitmap.Width), Trunc(FCamBitmap.Height), TJBitmap_Config.JavaClass.ARGB_8888);
    try
      TJandroid_Utils.JavaClass.bitmapToMat(BitmapToJBitmap(FCamBitmap), LSrcMat);
      TJImgproc.JavaClass.cvtColor(LSrcMat, LDstMat, TJImgproc.JavaClass.COLOR_RGB2GRAY);
      LThreshold := TJImgproc.JavaClass.threshold(LDstMat, LDstMat, trash, maxval, type_);
      TJImgproc.JavaClass.Canny(LDstMat, LDstMat, LThreshold, LThreshold * 2);
      // 传入正确的ArrayList给findContours
      TJImgproc.JavaClass.findContours(LDstMat, LContoursList, LHierarchyMat, TJImgproc.JavaClass.RETR_EXTERNAL, TJImgproc.JavaClass.CHAIN_APPROX_SIMPLE );
      TJImgproc.JavaClass.cvtColor(LDstMat, LDstMat, TJImgproc.JavaClass.COLOR_GRAY2RGB);
      TJImgproc.JavaClass.drawContours(LDstMat, LContoursList, -1, TJScalar.JavaClass.init(255,255,0) , 3);
      TJandroid_Utils.JavaClass.MatToBitmap(LDstMat, LJBitmap);
      FCamBitmap := JBitmapToBitmap(LJBitmap);

      // 正确遍历轮廓列表
      Memo1.Lines.Clear;
      for i := 0 to LContoursList.size - 1 do
      begin
        // 将List元素转换为MatOfPoint
        LContour := JMatOfPoint(LContoursList.get(i));
        // 获取轮廓的点数据数组
        LPoints := LContour.toArray;
        try
          Memo1.Lines.Add(Format('轮廓%d:包含%d个点', [i, LPoints.length div 2]));
          // 可选:输出前几个点的坐标
          if LPoints.length >= 2 then
            Memo1.Lines.Add(Format('第一个点坐标:(%d, %d)', [LPoints.Items[0], LPoints.Items[1]]));
        finally
          LPoints.free; // 释放Java数组资源
        end;
        LContour.release; // 释放轮廓Mat资源
      end;
    finally
      // 释放所有Mat资源
      LSrcMat.release;
      LDstMat.release;
      LHierarchyMat.release;
      LJBitmap.recycle; // 释放Bitmap资源
    end;
  finally
    LContoursList.clear;
    LContoursList.free;
    FOpenCVInProgress := False;
  end;
end;

关键修复点

  • List类型修正:改用TJArrayList而非JList,直接初始化空列表,避免类型转换和容量限制问题。
  • 轮廓元素处理:明确将列表元素转换为JMatOfPoint,通过toArray()获取点数据,避免直接调用toString()导致的异常。
  • 资源释放:添加try...finally块释放所有Mat、Bitmap和Java数组资源,防止内存泄漏引发访问冲突。
  • 遍历逻辑优化:格式化输出轮廓的点数量和坐标,替代无意义的toString输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:24:55