Calcular el ángulo entre dos objetos en una imagen.
Tengo algunas imágenes específicas de dos objetos (un teléfono y un control remoto de TV) y quiero calcular el ángulo entre dos bordes que se intersecan. Usé Canny para detectar los bordes y la función hough_line para el ángulo, pero la función hough_line encontró demasiados ángulos que no cumplen con el requisito.
Imagen original:
imagen
Este es el requisito:
imagen
Y esto es lo que hice:
imagen
Mi código:
import cv2
from skimage.transform import hough_line, hough_line_peaks
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
def edge_detection(img, blur_ksize=5, threshold1=100, threshold2=200):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_gaussian = cv2.GaussianBlur(gray, (blur_ksize, blur_ksize), 0)
img_canny = cv2.Canny(img_gaussian, threshold1, threshold2)
return img_canny
image = edge_detection(cv2.imread('img1.png'))
h, theta, d = hough_line(image)
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
ax = axes.ravel()
ax[0].imshow(image)
ax[0].set_title('Imagen original')
ax[0].set_axis_off()
ax[1].imshow(image, cmap=cm.gray)
for _, angle, dist in zip(*hough_line_peaks(h, theta, d)):
y0 = (dist - 0 * np.cos(angle)) / np.sin(angle)
y1 = (dist - image.shape[1] * np.cos(angle)) / np.sin(angle)
ax[1].plot((0, image.shape[1]), (y0, y1), '-r')
ax[1].set_xlim((0, image.shape[1]))
ax[1].set_ylim((image.shape[0], 0))
ax[1].set_axis_off()
ax[1].set_title('Líneas detectadas')
plt.tight_layout()
plt.show()
angle = []
dist = []
for _, a, d in zip(*hough_line_peaks(h, theta, d)):
angle.append(a)
dist.append(d)
angle = [a*180/np.pi for a in angle]
print(angle)
¿Hay alguna forma de detectar y calcular exactamente el ángulo que necesito en OpenCV? Muchas gracias.
Actualización:
Intenté diferentes valores de blur_ksize, threshold1 y threshold2 en la detección de Canny, parece que pude eliminar las líneas redundantes, pero ahora los ángulos que hough_line_peaks() devuelve son negativos. ¿Alguien puede explicarme esto? También quiero agregar los valores de los ángulos a los picos en la gráfica, para ver qué ángulo tiene qué valor.
imagen
davy.ai
Sí, existen diferentes formas de detectar y calcular exactamente un ángulo en OpenCV. Un enfoque podría ser utilizar la función HoughLinesP en lugar de la función HoughLines. HoughLinesP es una transformada de Hough probabilística que puede detectar segmentos de líneas en lugar de líneas completas. Con segmentos de líneas, se pueden calcular los ángulos entre ellos de manera más precisa.
Aquí hay una versión actualizada de tu código que utiliza HoughLinesP y calcula el ángulo entre los dos segmentos de líneas detectados:
En este código, primero utilizamos HoughLinesP para detectar segmentos de líneas en la imagen. Luego calculamos la longitud de cada segmento de línea, el producto escalar entre ellos y finalmente el ángulo entre ellos. También dibujamos los dos segmentos de líneas detectados en la imagen original.
Ten en cuenta que HoughLinesP requiere algunos parámetros adicionales en comparación con HoughLines, incluyendo la longitud mínima de un segmento de línea (
longitud_minima_linea
) y la distancia máxima entre dos segmentos para considerarlos una sola línea (espacio_maximo_entre_lineas
). Es posible que debas ajustar estos parámetros según las imágenes específicas con las que estés trabajando.Respecto a los ángulos negativos que estás obteniendo, esto se debe a que la función
arccos
de NumPy devuelve ángulos en el rango [0, pi] radianes, lo cual corresponde a [0, 180] grados. Para obtener el rango completo de ángulos en grados, debes agregar una condición para verificar si el producto escalar entre los dos segmentos de línea es positivo o negativo, y ajustar el ángulo en consecuencia:Respecto a colocar los valores de los ángulos en los picos del gráfico, una forma de hacerlo es utilizando la función
text
de Matplotlib, de la siguiente manera:Esto colocará los valores de los ángulos encima de cada segmento de línea en el gráfico. Puedes ajustar la posición del texto cambiando las coordenadas x e y, y otras propiedades del texto (como el tamaño de fuente) utilizando argumentos opcionales de
text
.