2016-12-22 4 views
5

Ich versuchte Google Cloud Vision API (TEXT_DETECTION) auf 90 Grad gedrehtes Bild. Es kann erkannten Text trotzdem korrekt zurückgeben. (siehe Bild unten)Erhalte die korrekte Bildausrichtung von Google Cloud Vision api (TEXT_DETECTION)

Das bedeutet, der Motor kann Text erkennen, auch das Bild ist 90, 180, 270 Grad gedreht.

Das Antwort-Ergebnis enthält jedoch keine Informationen zur korrekten Bildausrichtung. (Dokument: EntityAnnotation)

Gibt es überhaupt nicht nur erkannten Text zu bekommen, sondern auch die Orientierung?
könnte Google es ähnlich unterstützen (FaceAnnotation: getRollAngle)

enter image description here

+0

I Wenn Sie möchten, dass diese Funktion vorhanden ist, können Sie eine Feature-Anfrage an den Google-Cloud-Plattform-Problemverfolger unter https://code.google.com/p/google-cloud-platform/issues/list senden. – Adam

+0

Danke. Ich wusste nicht, dass es eine solche Problemliste gibt. Ich habe gerade die Anfrage geschrieben. https://code.google.com/p/google-cloud-platform/issues/detail?id=194 –

Antwort

3

Wie in den Public Issue Tracker beschrieben, ist unser Engineering-Team dieses Feature Request jetzt bewusst, und es gibt derzeit keine ETA für ihre Umsetzung.

Hinweis: Informationen zur Ausrichtung sind möglicherweise bereits in den Metadaten Ihres Bilds verfügbar. Ein Beispiel für das Extrahieren der Metadaten finden Sie in dieser Third-party library.

Eine umfassende Problemumgehung wäre, die zurückgegebenen "boundingPoly" "Vertices" für die zurückgegebenen "textAnnotations" zu überprüfen. Wenn Sie die Breite und Höhe des Rechtecks ​​jedes erkannten Wortes berechnen, können Sie herausfinden, ob ein Bild nicht rechts oben ist, wenn das Rechteck "Höhe"> "Breite" (aka das Bild ist seitwärts) ist.

+0

neugierig zu wissen, wie die Google Cloud-Vision den richtigen Text aus einem Bild erhalten kann, auch wenn das Bild nicht horizontal ist ausgerichtet und muss gedreht werden. Wie weiß die API, wie viel das Bild gedreht werden muss? Wenn diese Informationen nicht in den Metadaten des Bilds enthalten sind, wie findet die Cloud-API dies heraus? – Omnipresent

1

Ich poste meine Workaround, die wirklich funktioniert für Bilder 90, 180, 270 Grad gedreht. Bitte beachten Sie den folgenden Code.

GetExifOrientation(annotateImageResponse.getTextAnnotations().get(1));
/** 
* 
* @param ea The input EntityAnnotation must be NOT from the first EntityAnnotation of 
*   annotateImageResponse.getTextAnnotations(), because it is not affected by 
*   image orientation. 
* @return Exif orientation (1 or 3 or 6 or 8) 
*/ 
public static int GetExifOrientation(EntityAnnotation ea) { 
    List<Vertex> vertexList = ea.getBoundingPoly().getVertices(); 
    // Calculate the center 
    float centerX = 0, centerY = 0; 
    for (int i = 0; i < 4; i++) { 
     centerX += vertexList.get(i).getX(); 
     centerY += vertexList.get(i).getY(); 
    } 
    centerX /= 4; 
    centerY /= 4; 

    int x0 = vertexList.get(0).getX(); 
    int y0 = vertexList.get(0).getY(); 

    if (x0 < centerX) { 
     if (y0 < centerY) { 
      //  0 -------- 1 
      //  |   | 
      //  3 -------- 2 
      return EXIF_ORIENTATION_NORMAL; // 1 
     } else { 
      //  1 -------- 2 
      //  |   | 
      //  0 -------- 3 
      return EXIF_ORIENTATION_270_DEGREE; // 6 
     } 
    } else { 
     if (y0 < centerY) { 
      //  3 -------- 0 
      //  |   | 
      //  2 -------- 1 
      return EXIF_ORIENTATION_90_DEGREE; // 8 
     } else { 
      //  2 -------- 3 
      //  |   | 
      //  1 -------- 0 
      return EXIF_ORIENTATION_180_DEGREE; // 3 
     } 
    } 
} 

Mehr Infos
Ich fand ich habe die Sprache Hinweis hinzufügen zu machen annotateImageResponse.getTextAnnotations().get(1) immer die Regel folgen.

Beispielcode Sprache Hinweis

ImageContext imageContext = new ImageContext(); 
String [] languages = { "zh-TW" }; 
imageContext.setLanguageHints(Arrays.asList(languages)); 
annotateImageRequest.setImageContext(imageContext); 
0

ist es nicht möglich zu erhalten Manchmal Orientierung von Metadaten hinzuzufügen. Zum Beispiel, wenn der Benutzer ein Foto mit der Kamera eines mobilen Geräts mit falscher Ausrichtung gemacht hat. Meine Lösung basiert auf Jack Fan Antwort und für google-api-services-vision (verfügbar über Maven).

meine Textunit Klasse

public class TextUnit { 
     private String text; 

     // X of lowest left point 
     private float llx; 

     // Y of lowest left point 
     private float lly; 

     // X of upper right point 
     private float urx; 

     // Y of upper right point 
     private float ury; 
    } 

Basismethode:

List<TextUnit> extractData(BatchAnnotateImagesResponse response) throws AnnotateImageResponseException { 
      List<TextUnit> data = new ArrayList<>(); 

      for (AnnotateImageResponse res : response.getResponses()) { 
       if (null != res.getError()) { 
        String errorMessage = res.getError().getMessage(); 
        logger.log(Level.WARNING, "AnnotateImageResponse ERROR: " + errorMessage); 
        throw new AnnotateImageResponseException("AnnotateImageResponse ERROR: " + errorMessage); 
       } else { 
        List<EntityAnnotation> texts = response.getResponses().get(0).getTextAnnotations(); 
        if (texts.size() > 0) { 

         //get orientation 
         EntityAnnotation first_word = texts.get(1); 
         int orientation; 
         try { 
          orientation = getExifOrientation(first_word); 
         } catch (NullPointerException e) { 
          try { 
           orientation = getExifOrientation(texts.get(2)); 
          } catch (NullPointerException e1) { 
           orientation = EXIF_ORIENTATION_NORMAL; 
          } 
         } 
         logger.log(Level.INFO, "orientation: " + orientation); 

         // Calculate the center 
         float centerX = 0, centerY = 0; 
         for (Vertex vertex : first_word.getBoundingPoly().getVertices()) { 
          if (vertex.getX() != null) { 
           centerX += vertex.getX(); 
          } 
          if (vertex.getY() != null) { 
           centerY += vertex.getY(); 
          } 
         } 
         centerX /= 4; 
         centerY /= 4; 


         for (int i = 1; i < texts.size(); i++) {//exclude first text - it contains all text of the page 

          String blockText = texts.get(i).getDescription(); 
          BoundingPoly poly = texts.get(i).getBoundingPoly(); 

          try { 
           float llx = 0; 
           float lly = 0; 
           float urx = 0; 
           float ury = 0; 
           if (orientation == EXIF_ORIENTATION_NORMAL) { 
            poly = invertSymmetricallyBy0X(centerY, poly); 
            llx = getLlx(poly); 
            lly = getLly(poly); 
            urx = getUrx(poly); 
            ury = getUry(poly); 
           } else if (orientation == EXIF_ORIENTATION_90_DEGREE) { 
            //invert by x 
            poly = rotate(centerX, centerY, poly, Math.toRadians(-90)); 
            poly = invertSymmetricallyBy0Y(centerX, poly); 
            llx = getLlx(poly); 
            lly = getLly(poly); 
            urx = getUrx(poly); 
            ury = getUry(poly); 
           } else if (orientation == EXIF_ORIENTATION_180_DEGREE) { 
            poly = rotate(centerX, centerY, poly, Math.toRadians(-180)); 
            poly = invertSymmetricallyBy0Y(centerX, poly); 
            llx = getLlx(poly); 
            lly = getLly(poly); 
            urx = getUrx(poly); 
            ury = getUry(poly); 
           }else if (orientation == EXIF_ORIENTATION_270_DEGREE){ 
            //invert by x 
            poly = rotate(centerX, centerY, poly, Math.toRadians(-270)); 
            poly = invertSymmetricallyBy0Y(centerX, poly); 
            llx = getLlx(poly); 
            lly = getLly(poly); 
            urx = getUrx(poly); 
            ury = getUry(poly); 
           } 


           data.add(new TextUnit(blockText, llx, lly, urx, ury)); 
          } catch (NullPointerException e) { 
           //ignore - some polys has not X or Y coordinate if text located closed to bounds. 
          } 
         } 
        } 
       } 
      } 
      return data; 
     } 

Hilfsmethoden:

private float getLlx(BoundingPoly poly) { 
     try { 
      List<Vertex> vertices = poly.getVertices(); 

      ArrayList<Float> xs = new ArrayList<>(); 
      for (Vertex v : vertices) { 
       float x = 0; 
       if (v.getX() != null) { 
        x = v.getX(); 
       } 
       xs.add(x); 
      } 

      Collections.sort(xs); 
      float llx = (xs.get(0) + xs.get(1))/2; 
      return llx; 
     } catch (Exception e) { 
      return 0; 
     } 
    } 

    private float getLly(BoundingPoly poly) { 
     try { 
      List<Vertex> vertices = poly.getVertices(); 

      ArrayList<Float> ys = new ArrayList<>(); 
      for (Vertex v : vertices) { 
       float y = 0; 
       if (v.getY() != null) { 
        y = v.getY(); 
       } 
       ys.add(y); 
      } 

      Collections.sort(ys); 
      float lly = (ys.get(0) + ys.get(1))/2; 
      return lly; 
     } catch (Exception e) { 
      return 0; 
     } 
    } 

    private float getUrx(BoundingPoly poly) { 
     try { 
      List<Vertex> vertices = poly.getVertices(); 

      ArrayList<Float> xs = new ArrayList<>(); 
      for (Vertex v : vertices) { 
       float x = 0; 
       if (v.getX() != null) { 
        x = v.getX(); 
       } 
       xs.add(x); 
      } 

      Collections.sort(xs); 
      float urx = (xs.get(xs.size()-1) + xs.get(xs.size()-2))/2; 
      return urx; 
     } catch (Exception e) { 
      return 0; 
     } 
    } 

    private float getUry(BoundingPoly poly) { 
     try { 
      List<Vertex> vertices = poly.getVertices(); 

      ArrayList<Float> ys = new ArrayList<>(); 
      for (Vertex v : vertices) { 
       float y = 0; 
       if (v.getY() != null) { 
        y = v.getY(); 
       } 
       ys.add(y); 
      } 

      Collections.sort(ys); 
      float ury = (ys.get(ys.size()-1) +ys.get(ys.size()-2))/2; 
      return ury; 
     } catch (Exception e) { 
      return 0; 
     } 
    } 

    /** 
    * rotate rectangular clockwise 
    * 
    * @param poly 
    * @param theta the angle of rotation in radians 
    * @return 
    */ 
    public BoundingPoly rotate(float centerX, float centerY, BoundingPoly poly, double theta) { 

     List<Vertex> vertexList = poly.getVertices(); 

     //rotate all vertices in poly 
     for (Vertex vertex : vertexList) { 
      float tempX = vertex.getX() - centerX; 
      float tempY = vertex.getY() - centerY; 

      // now apply rotation 
      float rotatedX = (float) (centerX - tempX * cos(theta) + tempY * sin(theta)); 
      float rotatedY = (float) (centerX - tempX * sin(theta) - tempY * cos(theta)); 

      vertex.setX((int) rotatedX); 
      vertex.setY((int) rotatedY); 
     } 
     return poly; 
    } 

    /** 
    * since Google Vision Api returns boundingPoly-s when Coordinates starts from top left corner, 
    * but Itext uses coordinate system with bottom left start position - 
    * we need invert the result for continue to work with itext. 
    * 
    * @return text units inverted symmetrically by 0X coordinates. 
    */ 
    private BoundingPoly invertSymmetricallyBy0X(float centerY, BoundingPoly poly) { 

     List<Vertex> vertices = poly.getVertices(); 
     for (Vertex v : vertices) { 
      if (v.getY() != null) { 
       v.setY((int) (centerY + (centerY - v.getY()))); 
      } 
     } 
     return poly; 
    } 

    /** 
    * 
    * @param centerX 
    * @param poly 
    * @return text units inverted symmetrically by 0Y coordinates. 
    */ 
    private BoundingPoly invertSymmetricallyBy0Y(float centerX, BoundingPoly poly) { 
     List<Vertex> vertices = poly.getVertices(); 
     for (Vertex v : vertices) { 
      if (v.getX() != null) { 
       v.setX((int) (centerX + (centerX - v.getX()))); 
      } 
     } 
     return poly; 
    } 
Verwandte Themen