我需要有关在 Android 上使用 OpenCV 的帮助(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
对其进行类型转换就像你做的那样。
在德尔福 JList
和JArrayList
属于不同的接口(interface)层次结构,不能直接类型转换。问题出在以下行
LContoursList:= JList(TJArrayList.JavaClass.init(0));
上面的强制类型转换将转换两个不兼容的接口(interface),而不给您任何警告,然后当您尝试使用 LContoursList
时它会崩溃。
如果您以安全的方式编写上述类型转换:
LContoursList := TJArrayList.Create as JList;
你会得到运行时异常,告诉你JArrayList
不支持JList
界面。
Exception class EIntfCastError with message 'Interface not supported'.
由于底层 Java 类支持这两个接口(interface),因此您可以进行不同的类型转换并将底层 Java 对象公开为 JList
使用以下代码:
var
LArr: JArrayList;
LContoursList: JList;
LArr := TJArrayList.Create;
LContoursList:= TJList.Wrap(LArr);
注意:在 Delphi 中,如果你想调用默认的 Java 构造函数,你只需说 TJXXX.Create
相反 TJXXX.JavaClass.init
。在您的情况下,调用容量为 0 的 Java 构造函数与使用默认构造函数没有太大区别。
注意:原始 FMX 示例在后台线程中运行。由于您尚未展示如何运行示例,因此如果您使用后台线程,则需要确保将 GUI 控件的任何使用与主线程同步。
关于android - 在 Delphi 中使用 OpenCV for Android 会在使用 JList 时引发错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77422784/