Ask Your Question
0

Calc the Seconds moments of area of huge number of countours

asked 2016-06-17 05:29:26 -0600

marcoE gravatar image

updated 2016-06-17 19:10:53 -0600

Hello! Finally I was able to properly fit he mesh with the layer. For this image (7158x16392 8MB)

I need to calculate the percentage of blacks and browns per triangle, and also the seconds moments of area per triangle. I'm facing some problems. The mesh layer should always be the master. For instance, If I have a triangle with all black, it should return 100% empty and without second moments.

So, I'm facing some problems to find out the proper bit-wise function, which allows me to make the mesh being the "master", and then I don't know how to iterate over a such huge amount of contours and make the calcs. I think the second moments which are native supported by opencv are the seconds moments of inertia, not the second moments of area..

edit retag flag offensive close merge delete

Comments

@marcoE again! please don't upload such a big files. you can give a link to image.

sturkmen gravatar imagesturkmen ( 2016-06-17 19:17:25 -0600 )edit

@sturkmen , what is big ? :)

marcoE gravatar imagemarcoE ( 2016-06-20 03:45:21 -0600 )edit

8mb is "too big".

berak gravatar imageberak ( 2016-08-04 01:36:29 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2016-06-17 16:11:10 -0600

Tetragramm gravatar image

updated 2016-08-03 18:27:38 -0600

The moments function calculates a weighted moment based on the intensity UNLESS you pass the binary image parameter as true. Then it's the same.

I'm not quite sure what you mean by using the triangle mesh as a master. I think you mean you have each triangle as either white or black. In that case, you need to either do bitwise_and to keep the triangles that are white, or do a bitwise_not to switch the white and black, then the and.

It would help if you made a small picture with say, 8 triangle and a square or circle on the other layer to show what you expect.

EDIT: Here's a practice image small enough to look at every pixel if you need to.

image description

edit flag offensive delete link more

Comments

link text I've cut a litle piece. I want to calculate the volumes and the second moments of intertia of each triangle. I've put some numbers just to have an example. So, the number 1 has 0% of Volume, it's empty, the seconds moments are null. The number 2 has 100% of volume, second moments would have big values. Number 3 would have 60% of volume more or less, and the second moments would be intermediate. Number 4 it's a big hole, I don't want to calc anything.

I think it's clearer what I'd like to calculate.

marcoE gravatar imagemarcoE ( 2016-06-20 05:03:49 -0600 )edit

Ok. So you need to do some pre-processing on your triangle mask. Threshold it, so you have lines of 255 separating your black triangles. Then do a bitwise_not to invert that. Now you have a separate areafor each. Run connectedComponents to get a different label for each area.

For your other image, convert it to a binary image.

Now, one by one, use inRange to extract a single triangle from the label image as a mask. Then do a bitwise_and with your floorplan layer. This leaves the only the area that is above zero within that triangle. Now call moments with the binary flag on, and that's the results for this triangle. To calculate percentages, you'll need to also use moments on the triangle mask after you've extracted just one triangle, to compare to the total area.

Tetragramm gravatar imageTetragramm ( 2016-06-20 07:39:07 -0600 )edit

@Tetragramm It's not easy. Should I keep all the mesh contours in white? Or some in white and others in black? Could I use other color to all mesh, and then calculate moments?

marcoE gravatar imagemarcoE ( 2016-07-19 05:19:44 -0600 )edit

another alternative approach. If I have the mesh and the "layer" where the mesh is. Is it easier to isolate? Mesh image: https://dl.dropboxusercontent.com/u/7... Layer image: https://dl.dropboxusercontent.com/u/7... code: http://pastebin.com/Q3sN5akv

marcoE gravatar imagemarcoE ( 2016-07-20 04:38:05 -0600 )edit

@Tetragramm is it something like this that is need to calc the moments per triangle? https://dl.dropboxusercontent.com/u/7...

marcoE gravatar imagemarcoE ( 2016-07-20 08:19:18 -0600 )edit

Not quite. Take your Mesh image there, and use Connected Components to get a label for each triangle.

Then extract just one triangle from the image.

You should have a single white triangle, and the rest black. Make a copy of your layer image and use bitwise_and with the single triangle to erase everything but what is inside that triangle.

Now you have a small amount of layer left. Calculate the moments, and that gives you one triangle.

Repeat for every connected component.

Tetragramm gravatar imageTetragramm ( 2016-07-20 21:42:36 -0600 )edit

@Tetragramm the connectComponents function is not available in python :\ Any alternative, or I should just implement in C++ ? It won't be easy to me, I'm used to use opencv python

marcoE gravatar imagemarcoE ( 2016-07-21 03:57:48 -0600 )edit

It should be available. It's used in THIS python tutorial.

Tetragramm gravatar imageTetragramm ( 2016-07-21 07:50:05 -0600 )edit

@Tetragramm you've said " Make a copy of your layer image and use bitwise_and with the single triangle to erase everything but what is inside that triangle." How can I select just one triangle for each time. I think that I'm understanding the process. Having n-masks, one for each triangle. Then for each mesh-triangle I can calc moments, centroids, etc . However. I don't get the "process" to reach it.

marcoE gravatar imagemarcoE ( 2016-07-22 05:59:40 -0600 )edit

Well, in the label image that returns from connected components, each triangle has a different label. You can use several methods, the simplest of which is compare.

There's an easy way to call it: Mat singleTriangle = (everyTriangle == labelNumber);

Tetragramm gravatar imageTetragramm ( 2016-07-22 09:58:46 -0600 )edit

when I appy the ret, markers = cv2.connectedComponents(imMeshly_bw), with imMeshLayer = cv2.imread('testLayer6_.png', -1) imGrayMshLayer = cv2.cvtColor(imMeshLayer, cv2.COLOR_BGR2GRAY) (thresh, imMeshly_bw) = cv2.threshold(imGrayMshLayer, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) I got : https://dl.dropboxusercontent.com/u/7...

marcoE gravatar imagemarcoE ( 2016-07-22 10:06:59 -0600 )edit

That doesn't look like THIS image from a couple of comments ago. Whatever you did to get this one, that's what you want to run connected components on. In case you are wondering, there are 3079 connected components, so that should be your maximum label number, with connectedComponents returning 3080.

Tetragramm gravatar imageTetragramm ( 2016-07-22 13:47:37 -0600 )edit

Ok, I think that I'm understanding what you are saying. This is my current code: http://pastebin.com/HfuGUD2N I have 3080 connectComponents. But I don't know how to deal with the information

marcoE gravatar imagemarcoE ( 2016-07-25 05:16:28 -0600 )edit

It seems odd to me. I have more than 3080 components. There are far more triangles.

marcoE gravatar imagemarcoE ( 2016-07-25 07:43:29 -0600 )edit

Now use whatever method you prefer to get an image with just one of the labels (see 4 comments ago). Then use that as a mask to copy your other image, so the only part remaining is inside that triangle. Then do moments.

Tetragramm gravatar imageTetragramm ( 2016-07-25 07:44:37 -0600 )edit

@Tetragramm something is wrong. I look into the labels matrix. It's size is the same of the original image. However, they are 3079 different connectedComponents . If select according to the label value, I select a lot of triangles not only one.

marcoE gravatar imagemarcoE ( 2016-07-25 08:02:03 -0600 )edit

@Tetragramm when I use _, contours, hier_ = cv2.findContours(imMesh_bw1,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cv2.drawContours(colorMask,np.array(contours),-1,(0,0,255),6) it returns 125091 contours (probably the total number of triangles), and if I draw it, it returns this image : https://dl.dropboxusercontent.com/u/7... . Could this be an alternative? i'm not handling properly connectedComponents, I think.

marcoE gravatar imagemarcoE ( 2016-07-25 09:56:22 -0600 )edit

Ah, I see the problem. I thought the mesh layer was just black and white, but it's not. So it's connecting nearby triangles. Instead of using THRESH_OTSU, set a manual threshold of 250. Then connectedComponents returns 13052.

Contours might not work because some of the lines may be too close together and join into one.

Tetragramm gravatar imageTetragramm ( 2016-07-25 17:07:40 -0600 )edit

The highest number that I get of connect components labels is : 1740 and countours is : 172187 with this config : ret, imMesh_bw11 = cv2.threshold(imGrayMsh1, 128, 255, cv2.THRESH_BINARY) and I get this image: https://dl.dropboxusercontent.com/u/7...

marcoE gravatar imagemarcoE ( 2016-07-26 09:11:29 -0600 )edit

I think that finally I get the correct connectComponents value, 13053 . I still don't know how to do what I need to do :)

marcoE gravatar imagemarcoE ( 2016-07-27 08:09:51 -0600 )edit

However there are more triangles than labels. For istance with label 0, it has 7884676 triangles. With the label 1, 19673, etc.

marcoE gravatar imagemarcoE ( 2016-07-27 08:47:12 -0600 )edit

Do you know how many triangles there are in total? Using a threshold of 250 I didn't notice any triangles that shared the same label.

Tetragramm gravatar imageTetragramm ( 2016-07-27 21:06:49 -0600 )edit

No, I don't know how many triangle do I have. However, I know that are lot of labels = 0, and labels =1 ; so I can assume that are triangles with the same label. I did the tresh = 250 .

marcoE gravatar imagemarcoE ( 2016-07-28 04:23:05 -0600 )edit
marcoE gravatar imagemarcoE ( 2016-07-28 05:33:13 -0600 )edit

Labels is the image with each pixel replaced with the label it belongs to. Label 0 is background. So look and see, there's only one triangle with label 1, it just has however many pixels.

Tetragramm gravatar imageTetragramm ( 2016-07-28 19:39:50 -0600 )edit

@Tetragramm I understood what you said, but i'm not able to see the triangle or how to extract it. I'll look into the docs.

marcoE gravatar imagemarcoE ( 2016-07-29 05:18:33 -0600 )edit

Completly stucked . :\

marcoE gravatar imagemarcoE ( 2016-08-03 04:34:16 -0600 )edit

I added a practice image to my answer. It's got 13 triangles (more or less triangles anyway), and it's small enough you can look at every pixel individually if you have to. Use this to figure out how connected components works.

Tetragramm gravatar imageTetragramm ( 2016-08-03 18:26:21 -0600 )edit

@Tetragramm thx and I'll try. I think my problem is with "masks" and bitwise operations, to get the images that I want. But I'll do the "tests" anyway.

marcoE gravatar imagemarcoE ( 2016-08-04 05:18:13 -0600 )edit

This is my example code : http://pastebin.com/WvPwebS8 How can I get just one triangle ? I'm tryng selec only the labels which are one and then write a image without success

marcoE gravatar imagemarcoE ( 2016-08-05 05:25:54 -0600 )edit

In c++ it would be (labels == 1). In python it's probably better to use the compare function. triangle = cv2.compare(labels, 1, cv2.CMP_EQ) is how I think it goes. (again, I don't use python, so my syntax may not be right).

For other triangles, replace 1 with the other numbers. Remember 0 is background and it goes up to num_labels-1.

Tetragramm gravatar imageTetragramm ( 2016-08-05 14:01:08 -0600 )edit

I think that I get it : http://pastebin.com/m6FJnQpi I have the handicap with this code. I'll only see the label 14, because it's the last of the set. But I can do for all of the components. What's the next step ?

marcoE gravatar imagemarcoE ( 2016-08-08 09:35:33 -0600 )edit

Good. Now that you have a mask for each triangle, do a bitwise_and with the binary image of your layer image. This leaves you with just the part of the layer image inside the triangle. Then the moments function gives you what you need, as best you've described it.

Tetragramm gravatar imageTetragramm ( 2016-08-08 19:11:20 -0600 )edit

hi ! my current code : http://pastebin.com/PgucizcR This are my images https://dl.dropboxusercontent.com/u/7...https://dl.dropboxusercontent.com/u/7... But I have a problem. My "triangles" onde the layer are not "good" Because there black and white parts of the triangle, it depends on the geometry of the layer. Should I do other bitwise operation or use this image https://dl.dropboxusercontent.com/u/7...

marcoE gravatar imagemarcoE ( 2016-08-09 05:28:12 -0600 )edit

No, you do the bitwise stuff after the mask is created.

Tetragramm gravatar imageTetragramm ( 2016-08-09 17:36:38 -0600 )edit

@Tetragramm I didn't get it :) What bitwise stuff ? I know that i need some oeprations, but with so many comments and misunderstandings (of me ) I don't know what they are :) Anyway, I added features to my code, that I think with your help will be helpful. Code: http://pastebin.com/6TgZKXmD output: https://dl.dropboxusercontent.com/u/7...

marcoE gravatar imagemarcoE ( 2016-08-10 03:47:35 -0600 )edit

In your code from HERE there are only two steps left to do. After you calculate the mask for the label add the line maskedLayer = bitwise_and(mask, imLayer1)

Then copy code from HERE where you calculate the moments and replace where you use the contour with maskedLayer. Also pass true for the binaryImage parameter in the moments function.

Tetragramm gravatar imageTetragramm ( 2016-08-10 18:39:57 -0600 )edit

@Tetragramm Thank you for your support. I think there is a litle thing to solve. This is the updated code, and I think that's what you've recommended http://pastebin.com/NpjDz7Yw Is not possible do the maskedLayer = cv2.bitwise_and(mask, imLayer1) , because they don't have the same dimensions, So I assumed that was maskedLayer = cv2.bitwise_and(mask, imLayerBw) , but it does not work either. I think this is the "litle thing" to solve. it is almost done !

marcoE gravatar imagemarcoE ( 2016-08-11 04:23:33 -0600 )edit

Ok, I did an update http://pastebin.com/kaC8aVQu and the output is https://dl.dropboxusercontent.com/u/7... I think, something is missing, anyway ! But is close

marcoE gravatar imagemarcoE ( 2016-08-11 07:24:26 -0600 )edit

Something like this, but you need to fix the problem with imLayerBw. I don't know why that wouldn't work. It's a single channel image, with the same width and height as the mesh image, right?

Tetragramm gravatar imageTetragramm ( 2016-08-11 07:53:30 -0600 )edit

imLayerBw is what your are saying :) https://dl.dropboxusercontent.com/u/7... Your code update doesn't have the contour code. Without the code to take the countour how can we get the moments ?

marcoE gravatar imagemarcoE ( 2016-08-11 08:11:11 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-06-17 05:29:26 -0600

Seen: 985 times

Last updated: Aug 03 '16