I'm doing a code to identify vegetation and measure it linearly. I have already managed to generate the binary mask of vegetation and soil. Now comes the process of identifying the figures (vegetation), I can perfectly identify and measure them, but with an error in the measurement, it measures less than what it should measure. In the code I use the function 'Box' to identify the 4 extreme points of each figure, then I do the same to find the midpoints of the 4 sides. The objective is to measure the LONG, and at the moment of representing with a circle the average points to calculate the length, sometimes it puts them as the width and not the length. How can I make it so that it identifies only the long ones and does not confuse with the wide ones? In the code I represent with a circle the 4 midpoints, but to test if the midpoints of the upper and lower end are well identified, I mentioned the other two. And here I see the error, which puts me in some the width instead of the height, as shown in the image.
The other error is the measurement, in the figures that correctly detects the length, it does not measure exactly well. In the image you see the representation of the length in pixels for each figure, and for example the second from left to right should measure 127 pixels and measure 74.
Why are these errors?
Code (I enter a mask, the path of the original image and its name):
ruta = 'Mosaicos para Ploteo/30/'
filename = 'Mosaico Cuartel 30 - 35x35 cm.tif'
orig = cv2.imread(ruta+filename)
mask_hsv= cv2.cvtColor(orig,cv2.COLOR_BGR2HSV)
lw_range = np.array([0,0,0]) #oscuros
up_range = np.array([180,203,180]) #claros
mask=cv2.inRange(mask_hsv,lw_range,up_range)
def medir_y_dibujar(mask,ruta_orig,filename):
image, contours, hierarchy = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
total_m = 0
orig = cv2.imread(str(ruta_orig+filename))
for c in contours:
if cv2.contourArea(c) < 5:
continue
box = cv2.minAreaRect(c)
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
box = np.array(box, dtype="int")
box = perspective.order_points(box)
cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)
#for (x, y) in box:
# cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1)
(tl, tr, br, bl) = box # (top left, top right, bottom right, bottom left)
(tltrX, tltrY) = midpoint(tl, tr) #PUNTO MEDIO ENTRE TOPLEFT Y TOPRIGHT
(blbrX, blbrY) = midpoint(bl, br) #PUNTO MEDIO ENTRE BOTTOMLEFT Y BOTTOMRIGHT
(tlblX, tlblY) = midpoint(tl, bl) #PUNTO MEDIO ENTRE TOPLEFT Y BOTTOMLEFT
(trbrX, trbrY) = midpoint(tr, br) #PUNTO MEDIO ENTRE TOPRIGHT Y BOTTOMRIGHT
ekis , yy = tl
# draw the midpoints on the image
cv2.circle(orig, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1)
cv2.circle(orig, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1)
cv2.circle(orig, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1)
cv2.circle(orig, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1)
# draw lines between the midpoints
#cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),
# (255, 0, 255), 2)
cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),
(255, 30, 100), 2)
#medir distancias
distance = math.sqrt(((tltrX-tlblX)**2)+((tltrY-tlblY)**2))
cv2.putText(orig, "{:.1f}p".format(distance),(int(tltrX), int(tltrY)), cv2.FONT_HERSHEY_SIMPLEX,0.65, (255, 255, 255), 2)
return orig
I think about discriminating the length with the width with an IF and staying with the longest one. but I think there must be another solution.
The other error is the erroneous measurement of the LINE generated between two points.
SOLVED
distance_1 = math.sqrt(((tltrX-blbrX)**2)+((tltrY-blbrY)**2))
distance_2 = math.sqrt(((tlblX-trbrX)**2)+((tlblY-trbrY)**2))
if(distance_1 >= distance_2 ):
cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),
(255, 0, 0), 2)
m_lineal = distance_1 * cm_p_pixel
else:
cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),
(255, 0, 0), 2)
m_lineal = distance_2 * cm_p_pixel
I calculated the distances with Pythagoras and did the conditional to always stay with the longest (which will be the LONG and not the width)