OPENCV + GEOMETRIA

OPENCV / GEOMETRIA

Estamos estudiando las posibilidades de como nos puede ver nuestro robot. La idea inicial eran QRs pero la detección después de todas las optimizaciones a nivel de programación se quedaba en los 100 ms (no es mucho)

El problema principal es que a distancias superiores a 2 metros el QR debe ser muy grande, lo que lo convierte en poco práctico.

Después de un acalorado debate QR vs Geometrías y haciendo pruebas el sistema más eficiente es el de figuras geométricas. Dónde pasamos de los 100 ms a los 15ms y conseguimos distancias de varios metros.

Así que seguimos la máxima de la programación simplifica, vuelve a simplificar y finalmente lo vuelves a simplificar (mínimo 3 simplificaciones)

Detección de cuadrados y polígonos y el tiempo que ha tardado.

El código fuente se simplifica y el tiempo se mejora y la distancia aumenta , esto parece que será la opción elegida para que nuestro robot se comunique con el mundo.

#include <opencv2/opencv.hpp>
#include <iostream>
#include <chrono>

using namespace cv;
using namespace std;
using namespace std::chrono;

//Funcion para detectar las formas
void detectShapes(Mat& frame) {
    Mat gray, blurred, thresholded;
    
    // Convertir en gris
    cvtColor(frame, gray, COLOR_BGR2GRAY);
    
    // Hacer un blur para reducir el ruido
    GaussianBlur(gray, blurred, Size(5, 5), 0);
    
    // Aplicar la detección de las fronteras
    Canny(blurred, thresholded, 50, 150);
    
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    
    // Buscar los contornos
    findContours(thresholded, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
    
    for (size_t i = 0; i < contours.size(); i++) {
        // Aproximar los contornos contiguos
        vector<Point> approx;
        approxPolyDP(contours[i], approx, 0.02 * arcLength(contours[i], true), true);
        
		  Rect rect =boundingRect(approx);
        // Saltar los tamaños pequeños y que no sean "convexos" posibles figuras cerradas
        if (fabs(contourArea(contours[i])) < 1000 || !isContourConvex(approx))
            continue; // Si no es muy ortodoxo usar continue pero aquí hoy lo permito.
        
        if (approx.size() == 3) { //Comprobamos si es un triángulo
            putText(frame, "Triangle", approx[0], FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2);
		  rectangle (frame, rect, Scalar (0,255,255),2);
        } else if (approx.size() == 4) {
            // Comprobar si es un rectángulo/cuadrado
            Rect r = boundingRect(approx);
		  rectangle (frame, rect, Scalar (0,255,255),2);
            float aspectRatio = (float)r.width / r.height;
            if (aspectRatio >= 0.9 && aspectRatio <= 1.1) //si la relación entre los lados es pequeña es un cuadrado
                putText(frame, "Square", approx[0], FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 0), 2);
            else
                putText(frame, "Rectangle", approx[0], FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 0), 2);
        } else if (approx.size() > 4 && approx.size() <= 8) { //Si tenemos más de 4 es un poligono (dijimos simplificar)
            putText(frame, "Polygon", approx[0], FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 255), 2);
		  rectangle (frame, rect, Scalar (0,255,255),2);
        } else {
            // El círculo es algo más complejo.
            Point2f center;
            float radius;
		  rectangle (frame, rect, Scalar (0,255,255),2);
            minEnclosingCircle(contours[i], center, radius);
            if (fabs(1 - ((float)radius / radius)) < 0.2)
                putText(frame, "Circle", approx[0], FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 2);
        }
    }
}

char buf[20];

int main() {
    // Capturamos el vídeo.
    VideoCapture cap(0);
    
    // Comprobar si abre la web cam 
    if (!cap.isOpened()) {
        cout << "Error: Could not open the camera" << endl;
        return -1;
    }
    
    while (true) {
        Mat frame;
        
        // Capturar fotograma.
        cap >> frame;
        
        // Si no hay imagen cerramos
        if (frame.empty()) {
            cout << "Error: Could not read frame" << endl;
            break;
        }
		auto start = high_resolution_clock::now();
        // Detectar las formas.
        detectShapes(frame);
		auto stop = high_resolution_clock::now();
		auto total =duration_cast<milliseconds>(stop -start);

        // Mostrar el resultado
		sprintf(buf,"%d",total.count());
		putText(frame,buf,Point(10,10),FONT_HERSHEY_SIMPLEX,0.5,Scalar(255,0,255),2);
        imshow("Detected Shapes", frame);
        cout << total.count() << " ms" <<endl;

    
        if (waitKey(30) == 'q') {
            break;
        }
    }
    
    cap.release();
    
    destroyAllWindows();
    
    return 0;
}

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

catorce + 4 =

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.