Reputation: 9020
I started by reading in this Mat
.
Then I converted it to Greyscale and applied Imgproc.canny()
to it, getting the following mask.
Then I used Imgproc.findContours()
to find the contours, Imgproc.drawContours()
, and Core.putText()
to label the contours with numbers:
Then I did Rect boundingRect = Imgproc.boundingRect(contours.get(0));
Mat submatrix = new Mat();
submatrix = originalMat.submat(boundingRect);
to get following submatrix
:
So far so good. The Problem starts hereafter:
NOW I NEEDED A MASK OF THE submatrix
. So I decided to use Imgproc.drawContours()
to get the mask:
Mat mask = new Mat(submatrix.rows(), submatrix.cols(), CvType.CV_8UC1);
List<MatOfPoint> contourList = new ArrayList<>();
contourList.add(contours.get(0));
Imgproc.drawContours(mask, contourList, 0, new Scalar(255), -1);
I got the following mask:
WHAT I WAS EXPECTING was a filled (in white color) diamond shape on black background.
WHy am I getting this unexpected result?
EDIT:
When I replaced Mat mask = new Mat(submatrix.rows(),
submatrix.cols(), CvType.CV_8UC1);
by Mat mask =
Mat.zeros(submatrix.rows(), submatrix.cols(), CvType.CV_8UC1);
,
the last mask with white colored garbage was replaced by an empty
black mask withOUT any white color on it. I got the following submat
and mask:
I was getting the first contour in the list of contours (named
contours
) by contours.get(0)
, and using this first contour to
calculate Imgproc.boundingRect()
as well as in
contourList.add(contours.get(0));
later (where contourList
is
the list of just one contour which will be used in the last
drawContours()
).
Then I went ahead to change contours.get(0)
to
contours.get(1)
in Imgproc.boundingRect()
as well as in contourList.add();
(just before Imgproc.drawContours()
). That
resulted in this submat and mask:
Then I changed back to contours.get(0)
in
Imgproc.boundingRect()
; and let
contourList.add(contours.get(1));
be there. Got the following
submat and mask:
NOW I am completely Unable to Understand what is happening here.
Upvotes: 0
Views: 578
Reputation: 11420
I am not sure how this is handle in JAVA (I usually use OpenCV in c++ or python), but there is an error in your code...
The contours
list will have a list of list of points. This points will refer to the original image. So, this mean that if the figure one is in lets say, x=300, y= 300, width= 100, height=100
then when you get your submatrix it will try to draw those points in a smaller image... so when it tries to draw point (300,300)
in a 100 x 100 image, it will simply fail... probably throws an error or simply doesn't draw anything...
A solution for this is, do a for loop and substract to each point of the contour the initial point of the bounding rect (in my example (300,300)
).
As, why there is some garbage drawn... well you never initialize the matrix. Not sure in JAVA, but in c++ you have to set them to 0. I think it should be something like this:
Mat mask = new Mat(submatrix.rows(), submatrix.cols(), CvType.CV_8UC1, new Scalar(0));
I hope this helps :)
EDIT
I think I did not explain myself clearly before.
Your contours are an array of points (x,y). These are the coordinates of the points that represent each contour in the original image. This image has a size, and your submatrix has a smaller size. The points are outside of this small image boundaries....
you should do something like this to fix it:
for (int j = 0; j < contours[0].length; j++) {
contours[0][j].x -= boundingrect.x;
contours[0][j].y -= boundingrect.y;
}
and then you can draw the contours, since they will be in boundaries of the submat.
I think in java it is also possible to subtract the opencv points directly:
for (int j = 0; j < contours[0].length; j++) {
contours[0][j] -= boundingrect.tl();
}
but in this case I am not sure, since I have tried it in c++ only
boundingrect.tl()
-> gives you the top left point of the rect
Upvotes: 1