TransWikia.com

¿Cómo puedo encontrar el centroide sin que me de error?

Stack Overflow en español Asked by Sheccid Selene Cortés Servín on December 31, 2020

Estoy intentando encontrar el centroide de una área de un contorno que marqué con un rectángulo pero cuando añado la parte con los momentos me aparece un error ZeroDivisionError: float division by zero y dado a eso no me marca el centroide en cada uno de los contornos.

Estoy agregando un for dentro del for que esta colocando los rectángulos del área encontrada y lo coloco ahí porque ya que se iteró en dibujar el rectángulo de las áreas, quiero que ahora itere para poner el centroide en cada uno de ellos.

from matplotlib import pyplot as plt
import cv2
import numpy as np

image = cv2.imread('radio.jpg',0)
img = cv2.resize(image,(600,300))
ret,th1 = cv2.threshold(img,49,255,cv2.THRESH_BINARY)
im_flood_fill_inv = cv2.bitwise_not(th1)
imgr = cv2.threshold(im_flood_fill_inv,49,255, cv2.THRESH_BINARY)[1]
num_labels, labels_im = cv2.connectedComponents(imgr)

def imshow_components(labels):
    label_hue = np.uint8(179*labels/np.max(labels))
    blank_ch = 255*np.ones_like(label_hue)
    labeled_img = cv2.merge([label_hue, blank_ch, blank_ch])
    labeled_img = cv2.cvtColor(labeled_img, cv2.COLOR_HSV2BGR)
    labeled_img[label_hue==0] = 0
    cv2.imshow('labeled',labeled_img)
    ret,th1 = cv2.threshold(labeled_img,49,255,cv2.THRESH_BINARY)
histo = cv2.calcHist([th1],[0],None,[256],[0,256])
plt.hist(th1.ravel(),256,[0,256]); plt.show()

contours, _ = cv2.findContours(th1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 0, 255), 2, cv2.LINE_AA)

lista = []
for c in contours:
    area = cv2.contourArea(c)
    if area > 1000 and area <  10000:
        cv2.drawContours(img, [c], 0, (0, 255, 0), 2, cv2.LINE_AA)
        lista.append(area)
        resultado = sorted(lista, reverse=True)[0:-2]
        print("Áreas encontradas:", resultado)
   
for c in contours:
    area = cv2.contourArea(c)
    if area  > 1300 and area < 10000:
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1, cv2.LINE_AA)
        for i in contours:
            momentos = cv2.moments(i)
            cx = int(momentos['m10']/momentos['m00'])
            cy = int(momentos['m01']/momentos['m00'])
            cv2.circle(img,(cx, cy), 3, (0,255,0), -1)

cv2.imshow('contornos', img)
imshow_components(labels_im)
cv2.waitKey(0)
cv2.destroyAllWindows()

    

Estoy intentando lo recomendado por @Abulafia y esta en lo correcto. Solo que estoy imprimiendo el circulo en la esquina inferior izquierda y si intendo poner cada termino dividido entre 2 me aparece un error, ¿cómo podria colocar el circulo en el centro?

for c in contours:
area = cv2.contourArea(c)
if area  > 1300 and area < 10000:
    (x, y, w, h) = cv2.boundingRect(c)
    rectangle= cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1, cv2.LINE_AA)
    #Momento
    cv2.circle(img,(x + w, y + h),3, (0,255,0), -1)

One Answer

SOLUCIÓN

Como lo comentó @Abulafia la manera adecuada de encontrár el centro de un cuadrado es tomando el promedio del ancho y altura ya que simplemente es un rectángulo.

Lo único que se hizo fue dividir el ancho y el alto entre 2 para que tome la mitad del alto y ancho del rectángulo.

for c in contours:
    area = cv2.contourArea(c)
    if area  > 1300 and area < 10000:
        (x, y, w, h) = cv2.boundingRect(c)
        box = cv2.minAreaRect(c)
        rectangle= cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1, cv2.LINE_AA)
        cv2.circle(rectangle,((x+(w//2)), (y+(h//2))),5 , (255,255,255),-1)

Answered by Sheccid Selene Cortés Servín on December 31, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP