我想要帮助使用OpenCV for Android(Git:https://github.com/CarlosHe/OpenCV-Android-Firemonkey),轮廓示例.

我不知道如何使用轮廓列表(JLIST)? 我想循环通过所有的等高线,并在Memo1中输出每一个.

下面是代码(返回错误"地址C8E40F40,访问地址47F027B5处的访问冲突"):

    var
      LSrcMat: JMat;
      LDstMat: JMat;
      LHierarchyMat: JMat;
      LJBitmap: JBitmap;
      LThreshold: Double;
      LContoursList: JList;
      trash, maxval: Double;
      i, type_: Integer;
    begin
      FOpenCVInProgress := True;
      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;
        LContoursList:= JList(TJArrayList.JavaClass.init(0));
        LJBitmap := TJBitmap.JavaClass.createBitmap(Trunc(FCamBitmap.Width), Trunc(FCamBitmap.Height), TJBitmap_Config.JavaClass.ARGB_8888);
        TJandroid_Utils.JavaClass.bitmapToMat(BitmapToJBitmap(FCamBitmap), LSrcMat);
        TJImgproc.JavaClass.cvtColor(LSrcMat, LDstMat, TJImgproc.JavaClass.COLOR_RGB2GRAY);   // change picture to gray
        LThreshold := TJImgproc.JavaClass.threshold(LDstMat, LDstMat, trash, maxval, type_);  // classify pixels into two different groups
        TJImgproc.JavaClass.Canny(LDstMat, LDstMat, LThreshold, LThreshold * 2);              // Edge detection
        TJImgproc.JavaClass.findContours(LDstMat, LContoursList, LHierarchyMat, TJImgproc.JavaClass.RETR_EXTERNAL, TJImgproc.JavaClass.CHAIN_APPROX_SIMPLE ); // find edge
        TJImgproc.JavaClass.cvtColor(LDstMat, LDstMat, TJImgproc.JavaClass.COLOR_GRAY2RGB);   // change picture to color
        TJImgproc.JavaClass.drawContours(LDstMat, LContoursList, -1, TJScalar.JavaClass.init(255,255,0) , 3);  // draw edge
        TJandroid_Utils.JavaClass.MatToBitmap(LDstMat, LJBitmap);
        FCamBitmap := JBitmapToBitmap(LJBitmap);
 // returns an error "Access violation at address C8E40F40, access address 47F027B5"
 For i := 0 to LContoursList.size - 1 do
 begin
         Memo1.Lines.Add(JStringToString((LContoursList.get(i).toString)));
 end;

推荐答案

您需要JList个实例才能传递到findContours,但是要获得JList个实例,您不能像您所做的那样从JArrayList进行类型转换.

在Delphi中,JListJArrayList属于不同的接口层次 struct ,不能直接进行类型转换.问题出在以下几行

LContoursList:= JList(TJArrayList.JavaClass.init(0));

上面的强制类型转换将转换两个不兼容的接口,而不会给您任何警告,然后当您try 使用LContoursList时,它将崩溃.

如果您以安全的方式编写上述类型转换:

LContoursList := TJArrayList.Create as JList;

你会得到运行时异常,告诉你JArrayList不支持JList接口.

异常类EIntfCastError,消息为‘不支持的接口’.

因为底层Java类支持这两个接口,所以您可以不同地执行类型转换,并使用以下代码将底层Java对象公开为JList:

var
  LArr: JArrayList;
  LContoursList: JList;


  LArr := TJArrayList.Create;
  LContoursList:= TJList.Wrap(LArr);

注意:在Delphi中,如果你想调用默认的Java构造函数,你可以只说TJXXX.Create而不是TJXXX.JavaClass.init.在您的例子中,调用容量为0的Java构造函数与使用默认构造函数没有太大区别.

注:原始FMX示例运行在后台线程中.由于您尚未展示如何运行示例,因此如果您使用的是后台线程,则需要确保将所有使用的图形用户界面控件与主线程同步.

Android相关问答推荐

垂直居中图标

Android编写动画在发布版本中崩溃

推断的类型是片段,但应为上下文

Play Google上发布的一款应用的房间数据库迁移

如何防止在Android Studio中设置kotlin断点时优化变量

Kotlin - 在继续之前如何等待这个协程完成?

升级到 Jetpack Compose 物料 list 2023.08.00 需要我将 targetSdk 更改为 34

如何在另一个函数中初始化主类参数? (我是初学者)代码推荐

尽管我在onCreate()期间已经初始化,但仍出现未初始化的late init变量错误

如何在 Jetpack Compose 中处理水平滚动手势和变换手势

具有管理员权限的 Kotlin 中的多用户系统

在段的中心绘制饼图(甜甜圈图)的图例

如何正确地将图像上传到 Jetpack Compose 中的 LazyList 中的项目?

组成不重叠的元素

从 Firebase 云存储中获取照片会导致 Android Jetpack Compose 闪烁

Jetpack Compose:如何绘制这样的路径/线

更新应用程序是否会取消对应用程序特定文件的权限?

将生成的 AAR 与 Composables 一起使用时未解决的参考

使用 Android 字符串数组在 Room 中迁移

如何在 Kotlin 中使用反向绑定适配器将小写文本转换为大写?