41

I'm trying to implement the example code of the following question by using opencv java api. To implement findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); in java i used this syntax Imgproc.findContours(gray, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);.

So now contours should be List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); rather than vector<vector<cv::Point> > contours;.

Then i need implement this approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);. In java api, Imgproc.approxPolyDP accept argument as approxPolyDP(MatOfPoint2f curve, MatOfPoint2f approxCurve, double epsilon, boolean closed). How i can i convert MatOfPoint to MatOfPoint2f?

Or is there a way to use vectors as same as c++ interface to implement this. Any suggestion or sample code is greatly appreciated.

Community
  • 1
  • 1
chAmi
  • 1,704
  • 3
  • 19
  • 27

3 Answers3

44

MatOfPoint2f differs from MatOfPoint only in the type of the elements (32-bit float and 32-bit int respectively). The viable option (though with a performance penalty) is to create MatOfPoint2f instance and set its elements (in a loop) to be equal to the elements of of the source MatOfPoint.

There are

 public void fromArray(Point... lp);
 public Point[] toArray();

methods in both of the classes.

So you can do just

 /// Source variable
 MatOfPoint SrcMtx;

 /// New variable
 MatOfPoint2f  NewMtx = new MatOfPoint2f( SrcMtx.toArray() );
Viktor Latypov
  • 13,683
  • 3
  • 36
  • 53
34

I realise this question has already been well answered, but to add an alternative for anyone who finds it in the future -

Imgproc.findContours(gray, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

for(int i=0;i<contours.size();i++){
    //Convert contours(i) from MatOfPoint to MatOfPoint2f
    contours.get(i).convertTo(mMOP2f1, CvType.CV_32FC2);
    //Processing on mMOP2f1 which is in type MatOfPoint2f
    Imgproc.approxPolyDP(mMOP2f1, mMOP2f2, approxDistance, true); 
    //Convert back to MatOfPoint and put the new values back into the contours list
    mMOP2f2.convertTo(contours.get(i), CvType.CV_32S);
}
Dan Nuffer
  • 655
  • 1
  • 6
  • 11
eskimo9
  • 743
  • 10
  • 23
  • 2
    Where is the mMOP2f2 coming from? – user2534365 Oct 21 '15 at 11:19
  • `mMOP2f1` and `mMOP2f2` are local variables of the loop which are omitted in this example. My edit should clarify this. – t7tran Aug 06 '18 at 21:56
  • How do you know that @coolersport? They could be global variables too. – hellow Aug 07 '18 at 06:03
  • It doesn't hurt to declare them as global but it is a bad practice. Content two objects are corresponding/reset to each contour. And it is proven in my case which shares the same loop. – t7tran Aug 08 '18 at 07:15
  • Those guys rejected my changes which help clarify this code didn't have a clue. Best of luck guys. Look at the first comment/question with two upvotes. – t7tran Aug 08 '18 at 07:20
  • Those guys rejected my changes which help clarify this code didn't have a clue. Best of luck guys. Look at the first comment/question with two upvotes. – t7tran Aug 08 '18 at 07:20
24

Although this question has already been answered, I believe that the accepted answer is not the best. Converting a matrix to an array and then back comes with quite the performance penalty, both time-wise and memory-wise.

Instead, OpenCV already has a function that does exactly this: convertTo.

MatOfPoint src;
// initialize src
MatOfPoint2f dst = new MatOfPoint2f();
src.convertTo(dst, CvType.CV_32F);

I have found this to be significantly faster and more memory-friendly.

To convert a MatOfPoint2f to a MatOfPoint, use CvType.CV_32S instead.