3

I am using the following code to clone my array:

aproximatedContours = cloneList(contours);

The body of method:

public static ArrayList<MatOfPoint> cloneList(ArrayList<MatOfPoint> contours) {
    ArrayList<MatOfPoint> clone = new ArrayList<MatOfPoint>(contours.size());
    for(MatOfPoint item: contours) 
        clone.add((MatOfPoint) item.clone()); // Line 479
    return clone;
}

However, even though both contours and clone are type of ArrayList, and obviously their elements are type of MatOfPoint, I get the following error:

08-16 16:34:16.015: W/System.err(21747): java.lang.ClassCastException: org.opencv.core.Mat cannot be cast to org.opencv.core.MatOfPoint
08-16 16:34:16.020: W/System.err(21747):    at com.example.objecttracker.ObjectTracker.cloneList(ObjectTracker.java:469)
08-16 16:34:16.020: W/System.err(21747):    at com.example.objecttracker.ObjectTracker.onCameraFrame(ObjectTracker.java:446)
08-16 16:34:16.020: W/System.err(21747):    at org.opencv.android.CameraBridgeViewBase.deliverAndDrawFrame(CameraBridgeViewBase.java:387)
08-16 16:34:16.020: W/System.err(21747):    at org.opencv.android.JavaCameraView$CameraWorker.run(JavaCameraView.java:321)
08-16 16:34:16.025: W/System.err(21747):    at java.lang.Thread.run(Thread.java:856)

Does anyone have an idea what is happeining here?

Marek
  • 3,935
  • 10
  • 46
  • 70

3 Answers3

4

This appears to be an API bug in MatOfPoint: It inherits its clone method from Mat, so when you call it, you're getting a plain Mat returned (and presumably only the superclass's fields copied). The overall semantics for MatOfPoint don't appear to be cleanly defined, and there's no mechanism for copying one.

Edit: If the native object handle contains all of the necessary data, you might be able to use new MatOfPoint(Mat m) as a copy constructor.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • 2
    Possibly the [copy constructor](http://docs.opencv.org/java/org/opencv/core/MatOfPoint.html#MatOfPoint%28org.opencv.core.Mat%29) is the way to go, but you'd need to check the source to see if it works correctly with `MatOfPoint` instances. – Duncan Jones Aug 16 '13 at 07:43
  • I am having a lot of troubles while using OpenCV for android. Is there any other good library for CV? You are sure that it is a bug? Could you also check my bounty question: http://stackoverflow.com/questions/18073239/opencv-java-convexity-defects-computer-vision – Marek Aug 16 '13 at 07:44
  • @Marek Please don't use comments to ask further questions. – Duncan Jones Aug 16 '13 at 07:45
  • This is a bug in the sense that a class really shouldn't implement `clone()` unless it's `final`, and `Mat` also doesn't implement the `Cloneable` interface. – chrylis -cautiouslyoptimistic- Aug 16 '13 at 07:45
  • chrylis, accoring to Duncan Jones, new MatOfPoint(Mat m) will not help. So what should be correct way to have two independent list? I want to process second list that contain elements same as first list and I don't want to change first list elements. Would my code work if ArrayList would contain different elements? For example Point? – Marek Aug 16 '13 at 07:48
  • 1
    @Marek I didn't say it wouldn't help. I just recommended you looked at the source to confirm - have you done that? – Duncan Jones Aug 16 '13 at 08:48
1

Clone is a very tricky thing and maybe not implemented correctly in opencv

Community
  • 1
  • 1
Maxim Efimov
  • 2,747
  • 1
  • 19
  • 25
0

It looks like a library issue because MatOfPoint is oddly relying on Mat's clone method which will clone a Mat object that is not a MatOfPoint.

As a workaround you could try to not depend on the clone() method but explicitly build copies on your own (untested):

    // Use a copy ctor
    clone.add(new MatOfPoint(item));
cyberz
  • 884
  • 1
  • 8
  • 16
  • Not working - MatOfPoint have same references so when I change clone elements list elements get also changed... – Marek Aug 16 '13 at 07:57
  • You could try to deep clone the values then. Maybe something like new clone.add(new MatOfPoint(item.toArray())); – cyberz Aug 16 '13 at 08:14