2016-12-22 47 views
5

Google Cloud Vision api'yi (TEXT_DETECTION) 90 derece döndürülen görüntüde denedim. Hala tanınan metni doğru şekilde döndürebilir. (aşağıdaki resme bakın)Google Cloud Vision api ile doğru görüntü yönlendirmesi alın (TEXT_DETECTION)

Bu, motor 90, 180, 270 derece döndürüldüğünde bile metni tanıyabildiği anlamına gelir. Bununla birlikte, yanıt sonucu doğru görüntü yönlendirmesi bilgisini içermez. (belge: EntityAnnotation)

Sadece tanınan metni almak değil, aynı zamanda yönlendirme olsun?
Google için benzer destekleyecek Could (FaceAnnotation: getRollAngle)

Public Issue Tracker açıklandığı üzere

enter image description here

+0

ben Bu özelliğin mevcut olmasını istiyorsanız, https://code.google.com/p/google-cloud-platform/issues/list adresindeki google bulut platformu sorun izleyicisine bir özellik isteği göndermeyi düşünebilirsiniz. – Adam

+0

Teşekkürler. Böyle bir sorun listesi olduğunu bilmiyordum. İsteği yeni gönderdim. Google bulut vizyonunun görüntü yatay olarak yatay değilken bile görüntüden doğru metni nasıl alabileceğini öğrenmek için https://code.google.com/p/google-cloud-platform/issues/detail?id=194 –

cevap

3

, mühendislik ekibimiz şimdi bu özellik isteği farkındadır ve hiçbir ETA bunun uygulanması için şu anda yoktur.

Not, yönelim bilgisi resmin meta verilerinde zaten mevcut olabilir. Meta verilerin nasıl çıkarılacağına ilişkin bir örnek, bu Third-party library'da görülebilir.

Geniş bir geçici çözüm, döndürülen "textAnnotations" için döndürülen "boundingPoly" "köşelerini" kontrol etmek olacaktır. Algılanan her bir kelimenin dikdörtgeninin genişliğini ve yüksekliğini hesaplayarak, bir resmin dikdörtgenin 'height'> 'width' (resim yan yana) ise sağa-yukarı olup olmadığını anlayabilirsiniz.

+0

hizalanmış ve döndürülmesi gerekiyor. API, görüntüyü ne kadar döndüreceğini biliyor? Bu bilgi resmin meta verilerinde değilse, bulut API'sı bunu nasıl buluyor? – Omnipresent

1

90, 180, 270 derece döndürülen resimler için gerçekten işe yarayan geçici çözümümüzü gönderiyorum. Lütfen aşağıdaki kodu inceleyin. bilgi

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 
     } 
    } 
} 

Daha ben annotateImageResponse.getTextAnnotations().get(1) hep kuralı takip yapmak dil ipucu eklemek zorunda bulundu.

Örnek kod Bazen meta verilerinden yönlendirme almak mümkün değildir dil ipucu

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

ekleyin. Örneğin, kullanıcı, yanlış yönlendirmeyle mobil cihaz kamerasını kullanarak bir fotoğraf yaptıysa. Çözümüm, Jack Fan yanıtına ve google-api-services-vision'a (Maven üzerinden erişilebilir) dayanmaktadır.

benim TextUnit sınıfı

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; 
    } 

baz yöntemi:

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; 
     } 

yardımcı yöntemler:

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; 
    }