Estoy tratando de averiguar qué tecnologías que iba a necesitar para el proceso de imágenes de los personajes.

Específicamente, en este ejemplo, necesito extraer el hashtag que está en un círculo. Usted puede ver aquí:

Procesamiento de imágenes y extracción de caracteres

Cualquier implementaciones sería de gran ayuda.

  • Yo no lo entiendo. ¿Desea que el extracto de las diferentes hashtags? usted puede hacer que el uso de OCR. ¿Desea detectar el círculo que encierra este hashtag?
  • Id como para detectar el círculo que encierra el hashtag y, a continuación, extraiga el hashtag eso es dentro del círculo.
  • No estoy seguro. Si se trataba de un rectángulo, se podría aplicar el umbral de + la línea de detección (hough, transformar o segmento de línea detector) y tratar de encontrar las 4 líneas que se cruzan con un ángulo de 90 grados.
  • ¿Usted quiere reconocer las letras F, S, a, y M? o usted apenas desea extraer el marco con ESPUMA en el interior, mientras que, dejando de lado todos los otros de la región con las letras?
  • sí quiero a reconocer las letras de ESPUMA debido a que existen dentro del círculo.
  • no utilice nunca haga clic aquí en el enlace…
  • He hecho clic a través de su imagen para el sitio web que lo aloja. Has leído lo que dice Nike se reserva el derecho a prohibir que ninguno de los participantes que hacen de amenazas, acoso o intento de estafa o abuso del proceso, por cualquier medio, , incluyendo el uso de programas o secuencias de comandos que les proporcionan una ventaja injusta.. No perder el tiempo aquí?
  • Él probablemente lo es, pero ahora que he contestar… yo quiero mi recompensa! 😀

InformationsquelleAutor jkushner | 2013-12-06

4 Comentarios

  1. 53

    Es posible resolver este problema con OpenCV + Tesseract

    aunque creo que no podría ser más fácil maneras. OpenCV es una fuente abierta de la biblioteca utilizada para construir aplicaciones de visión por computador y Tesseract es una fuente abierta de motor de OCR.

    Antes de empezar, quiero aclarar algo: que no es un círculo, es una rectángulo redondeado.

    Voy a compartir el código fuente de la aplicación que escribí para demostrar cómo se puede resolver el problema, así como algunos consejos sobre lo que está pasando. Esta respuesta no se supone que para educar a nadie en el tratamiento de la imagen digital y se espera que el lector tenga una mínima comprensión en este campo.

    Voy a describir muy brevemente cuáles son las secciones más grandes de lo que hace el código. La mayoría de los de la siguiente fragmento de código de vino de squares.cpp, una aplicación de ejemplo que se incluye con OpenCV para detectar plazas en las imágenes.

    #include <iostream>
    #include <vector>
    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    //angle: helper function.
    //Finds a cosine of angle between vectors from pt0->pt1 and from pt0->pt2.
    double angle( cv::Point pt1, cv::Point pt2, cv::Point pt0 )
    {
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
    }
    //findSquares: returns sequence of squares detected on the image.
    //The sequence is stored in the specified memory storage.
    void findSquares(const cv::Mat& image, std::vector<std::vector<cv::Point> >& squares)
    {  
    cv::Mat pyr, timg;
    //Down-scale and up-scale the image to filter out small noises
    cv::pyrDown(image, pyr, cv::Size(image.cols/2, image.rows/2));
    cv::pyrUp(pyr, timg, image.size());
    //Apply Canny with a threshold of 50
    cv::Canny(timg, timg, 0, 50, 5);
    //Dilate canny output to remove potential holes between edge segments
    cv::dilate(timg, timg, cv::Mat(), cv::Point(-1,-1));
    //find contours and store them all as a list 
    std::vector<std::vector<cv::Point> > contours;           
    cv::findContours(timg, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
    for( size_t i = 0; i < contours.size(); i++ ) //Test each contour
    {
    //Approximate contour with accuracy proportional to the contour perimeter
    std::vector<cv::Point> approx;   
    cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.02, true);
    //Square contours should have 4 vertices after approximation
    //relatively large area (to filter out noisy contours)
    //and be convex.
    //Note: absolute value of an area is used because
    //area may be positive or negative - in accordance with the
    //contour orientation
    if( approx.size() == 4 &&
    fabs(cv::contourArea(cv::Mat(approx))) > 1000 &&
    cv::isContourConvex(cv::Mat(approx)) )
    {
    double maxCosine = 0;
    for (int j = 2; j < 5; j++)
    {
    //Find the maximum cosine of the angle between joint edges
    double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
    maxCosine = MAX(maxCosine, cosine);
    }
    //If cosines of all angles are small
    //(all angles are ~90 degree) then write quandrange
    //vertices to resultant sequence
    if( maxCosine < 0.3 )
    squares.push_back(approx);
    }
    }         
    }
    //drawSquares: function draws all the squares found in the image
    void drawSquares( cv::Mat& image, const std::vector<std::vector<cv::Point> >& squares )
    {
    for( size_t i = 0; i < squares.size(); i++ )
    {
    const cv::Point* p = &squares[i][0];
    int n = (int)squares[i].size();
    cv::polylines(image, &p, &n, 1, true, cv::Scalar(0,255,0), 2, CV_AA);
    }
    cv::imshow("drawSquares", image);
    }

    Bien, así que nuestro programa comienza a las:

    int main(int argc, char* argv[])
    {
    //Load input image (colored, 3-channel)
    cv::Mat input = cv::imread(argv[1]);
    if (input.empty())
    {
    std::cout << "!!! failed imread()" << std::endl;
    return -1;
    }   
    //Convert input image to grayscale (1-channel)
    cv::Mat grayscale = input.clone();
    cv::cvtColor(input, grayscale, cv::COLOR_BGR2GRAY);
    //cv::imwrite("gray.png", grayscale);

    Lo escala de grises parece:

    Procesamiento de imágenes y extracción de caracteres

    //Threshold to binarize the image and get rid of the shoe
    cv::Mat binary;
    cv::threshold(grayscale, binary, 225, 255, cv::THRESH_BINARY_INV);
    cv::imshow("Binary image", binary);
    //cv::imwrite("binary.png", binary);

    Lo binario parece:

    Procesamiento de imágenes y extracción de caracteres

    //Find the contours in the thresholded image
    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(binary, contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
    //Fill the areas of the contours with BLUE (hoping to erase everything inside a rectangular shape)
    cv::Mat blue = input.clone();      
    for (size_t i = 0; i < contours.size(); i++)
    {
    std::vector<cv::Point> cnt = contours[i];
    double area = cv::contourArea(cv::Mat(cnt));               
    //std::cout << "* Area: " << area << std::endl; 
    cv::drawContours(blue, contours, i, cv::Scalar(255, 0, 0), 
    CV_FILLED, 8, std::vector<cv::Vec4i>(), 0, cv::Point() );         
    }       
    cv::imshow("Countours Filled", blue);  
    //cv::imwrite("contours.png", blue);  

    Lo azul parece:

    Procesamiento de imágenes y extracción de caracteres

    //Convert the blue colored image to binary (again), and we will have a good rectangular shape to detect
    cv::Mat gray;
    cv::cvtColor(blue, gray, cv::COLOR_BGR2GRAY);
    cv::threshold(gray, binary, 225, 255, cv::THRESH_BINARY_INV);
    cv::imshow("binary2", binary);
    //cv::imwrite("binary2.png", binary);

    Lo binario parece en este punto:

    Procesamiento de imágenes y extracción de caracteres

    //Erode & Dilate to isolate segments connected to nearby areas
    int erosion_type = cv::MORPH_RECT; 
    int erosion_size = 5;
    cv::Mat element = cv::getStructuringElement(erosion_type, 
    cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1), 
    cv::Point(erosion_size, erosion_size));
    cv::erode(binary, binary, element);
    cv::dilate(binary, binary, element);
    cv::imshow("Morphologic Op", binary); 
    //cv::imwrite("morpho.png", binary);

    Lo binario parece en este punto:

    Procesamiento de imágenes y extracción de caracteres

    //Ok, let's go ahead and try to detect all rectangular shapes
    std::vector<std::vector<cv::Point> > squares;
    findSquares(binary, squares);
    std::cout << "* Rectangular shapes found: "  << squares.size() << std::endl;
    //Draw all rectangular shapes found
    cv::Mat output = input.clone();
    drawSquares(output, squares);
    //cv::imwrite("output.png", output);

    Lo salida parece:

    Procesamiento de imágenes y extracción de caracteres

    ¡Está bien! Hemos resuelto la primera parte de que el problema era encontrar el rectángulo redondeado. Se puede ver en la imagen anterior que la forma rectangular que se ha detectado y verde líneas se han dibujado sobre la imagen original con fines educativos.

    La segunda parte es mucho más fácil. Empieza por crear un ROI (Región de interés) en la imagen original, de manera que podemos recortar la imagen para el área dentro del rectángulo redondeado. Una vez hecho esto, la imagen recortada se guarda en el disco como un archivo TIFF, que luego es alimentada a Tesseract hacer es magia:

    //Crop the rectangular shape
    if (squares.size() == 1)
    {    
    cv::Rect box = cv::boundingRect(cv::Mat(squares[0]));
    std::cout << "* The location of the box is x:" << box.x << " y:" << box.y << " " << box.width << "x" << box.height << std::endl;
    //Crop the original image to the defined ROI
    cv::Mat crop = input(box);
    cv::imshow("crop", crop);
    //cv::imwrite("cropped.tiff", crop);
    }
    else
    {
    std::cout << "* Abort! More than one rectangle was found." << std::endl;
    }
    //Wait until user presses key
    cv::waitKey(0);
    return 0;
    }

    Lo cultivo parece:

    Procesamiento de imágenes y extracción de caracteres

    Cuando esta aplicación termina su trabajo, se crea un archivo denominado cropped.tiff en el disco. Ir a la línea de comando y la invocación de Tesseract para detectar el texto presente en la imagen recortada:

    tesseract cropped.tiff out

    Este comando crea un archivo llamado out.txt con la detectada texto:

    Procesamiento de imágenes y extracción de caracteres

    Tesseract tiene un API que puede utilizar para agregar la característica OCR en su aplicación.

    Esta solución no es robusto y usted probablemente tendrá que hacer algunos cambios aquí y allá para hacer que funcione para otros casos de prueba.

    • no es la rectangular añadido por el autor? Es la incluida en el original hashtag? Sin rectangular, puede ser reto para diferenciar la ESPUMA y otras letras
    • El rectángulo naranja fue, de hecho, añadido por el autor. El otro que esta aplicación detecta creo que para ser parte de la imagen original. Al menos eso espero.
    • Sí que sería simplificar el problema. Sin embargo, este es un muy agradable y eficaz. Buen trabajo, Gracias!
    • ¿Recibió usted la plena recompensa? He estado fuera de la ciudad debido a una emergencia y me di cuenta de que echaba de menos la recompensa de la despedida.
    • Hola. Cuando el período de la recompensa expira, el sitio automáticamente le da el 50% de la recompensa para el más votado respuesta. Para responder a su pregunta, sólo he recibido un 50%. Pero eso no es un problema y espero que la respuesta te ayudó. Ver todo!
    • ¿cómo identificar los números en la matriz multidimensional de los Contornos en la tarjeta de Crédito de análisis ? Yo no soy capaz reconoces la región, tan sólo el número de la tarjeta queda en la imagen de muestra de modo que más tarde puede pasar a Tesseract para el reconocimiento de los números. Me pueden ayudar con eso , ya que yo no soy capaz de diferenciar entre la tarjeta de logotipo, números de & texto.Gracias!!!
    • Mantenga un ojo abierto para este hilo: stackoverflow.com/q/23706394/176769
    • Gracias, voy a mirar este post. Espero que las cosas estuvieran claras ahora 🙂
    • Gracias, Señor 🙂 Excelente respuesta 🙂 Buscando este tipo de ejemplo detallado. 🙂 Ahora lo he encontrado. 🙂

  2. 3

    Hay un par de alternativas: Java aplicación de OCR

    Se menciona el siguiente herramientas:

    Y algunos otros.

    Esta lista de enlaces pueden también ser útiles: http://www.javawhat.com/showCategory.do?id=2138003

    Generalmente este tipo de tarea requiere de mucho ensayo y pruebas. Probablemente la mejor herramienta de la que depende mucho más el perfil de los datos de entrada que cualquier otra cosa.

  3. 0

    OCR funciona bien con el documento escaneado.
    Lo que usted se refiere es el texto de detección en general las imágenes, que requiere de otras técnicas (a veces OCR se utiliza como parte del flujo)

    No estoy al tanto de toda la producción de «listo» de las implementaciones.

    para información general, tratar de google scholar con:
    «texto de detección en imágenes»

    un método específico que funcionó bien para mí es ‘ancho de trazo transformar» (SWT)
    no es difícil de implementar, y creo que hay también algunas implementaciones disponibles en línea.

Dejar respuesta

Please enter your comment!
Please enter your name here