Height of contour at different positions

Hello,
i have a picture where i can easily find contours in. And i am also able to put a minAreaRect around it and display its width and height.
Now im wondering whether i can also calculate the height of the contour at different positions. Maybe i can even calculate height (y-direction) for every pixel in x-direction and display the minimum and maximum height?
So far i havent found a solution, this topic has good ideas but i cant come to a solution: opencv - Contour width measurement along its entire lendth - Stack Overflow
My contours are even easier i guess, its always oval shaped.

example: this is what i do at the moment without problems

example: this is what i would like to have

So far i havent found a way to solve the problem. I looked into DistanceTransform but i dont know how to use it so i can calculate height at different positions. The contours are ALWAYS oval shaped and have similar ratio. The x length is always greater than y length and its horizontally aligned.

If your ovals are practically ellipses, and you don’t need absolute accuracy, you can calculate it instead of measuring.

Just think of the oval as squashed circle. Now calculate the measure on that opened-up circle (simple trigonometry) and then squash the measure down by the squashing ratio.

Actually they are not ellipses! Contours found are similar but more like a rectangle with half circles left and right and the horizontal lines of rectangle aren’t 100 percent straight but can go up and down.

ditch contours. definitely not a useful data structure for this task.

work with connected components. for each pixel column (or whichever you desire), find the first and last pixel in the contour. you can do that with some `numpy` functions.

if the shapes are FILLED, you can just do a columnwise sum, hence counting, which is equal to the “thickness” in that column.

if the shapes are NOT filled, I’d recommend getting them filled, or else you’ll have some more work getting the thickness (or numpy will).

present actual data, not just drawn ellipses. then we can discuss that.

Okay, heres my object after processing my image. It is filled. All objects look like this. At the moment i use only cv.minAreaRect to see width and height.

I’ll have a look into connected components tomorrow!

OK, i looked into connected components and wrote a script that instead of using `cv.findCountours()` uses `cv.connectedComponentsWithStats()`.
How can i now find the height of each (or every n-th) pixel column? I havent worked with numpy a lot.

say you consider one component, labeled with the number `label`. stats contain the bounding box (xywh, also area)

take a slice so you don’t have to work on the entire picture.

in that slice, find pixels given your label. you’ll have a boolean numpy array. `True` values as 1, which is convenient for summing. OpenCV masks contain 0 or 255 (any non-zero but usually 255), i.e. work slightly differently.

columns lie along axis 0.

``````mask = (labels[y:y+h, x:x+w] == label)
``````

Yesterday i managed to implement your idea and got good results i guess. For the mask i just took` output.copy()[y:y+h, x:x+h]` (`output` is a black numpy array with the relevant components added) because i didnt know what to use for `labels` and `label` in your example.

Now i have a numpy array with as many elements as the width of the objects in pixel, which is good. But i dont know what the results show. In output the objects are white and background black, as my sent picture. What confuses me, is that the area of one component is 20000, but the elements in array summed up is way more than this. Each element (except far left and far right) is approx 12000. And the height of bounding box for the objects is approx 110, i expected similar values for the `column_sums`.
I can post code and output of code when im home after work if this is interesting, i didnt want to overload this post.
Where do i think wrong? So far it seems like im on a good way. I hope thats true

see above. you really must inspect the values of variables/elements of arrays.

result from CC with stats; one specific label (number) for example.

Sorry, i dont get it…
I dont know what to use for labels and `label`. I tried every return of `CCwithstats` but i cant get results. With my try, i get results but work with OpenCv mask i think…
I mean the results i get make sense. They get bigger at beginning and smaller at end, as the height of the picture i sent. Ill post my code and return of one object, maybe you can help me to understand. Many lines are from internet, i just found out about CCwithstats when u told me. I understand what it does, but dont understand every single parameter. I think this is my problem.
Code:

``````# image
img = cv.resize(img4k, dsize=(1920, 1080)) # img = img4k
imggray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imggray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
# CC
analysis = cv.connectedComponentsWithStats(thresh, 4, cv.CV_32S)
(totalLabels, label_ids, values, centroid) = analysis
# Initialize a new image to store all the output components
output = np.zeros(imggray.shape, dtype="uint8")

# Loop through each component
for i in range(1, totalLabels):
# Area of the component
area = values[i, cv.CC_STAT_AREA]

if (area > 25000):
print('area: ', area)
componentMask = (label_ids == i).astype("uint8") * 255

# extract coordinate points
x = values[i, cv.CC_STAT_LEFT]
y = values[i, cv.CC_STAT_TOP]
w = values[i, cv.CC_STAT_WIDTH]
h = values[i, cv.CC_STAT_HEIGHT]
# bounding box
pt1 = (x, y)
pt2 = (x+ w, y+ h)
(X, Y) = centroid[i]
cv.rectangle(img,pt1,pt2, (255, 0, 255), 1)
cv.putText(img, "w={},h={}".format(w, h), (int(x),int(y)-int(h/1.6)), cv.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 1)