2016-12-22 50 views
5

90度回転した画像でGoogle Cloud Vision API(TEXT_DETECTION)を試しました。認識されたテキストを正しく返すことができます。Google Cloud Vision api(TEXT_DETECTION)で正しい画像の向きを取得する

これは、イメージが90度、180度、270度回転していてもテキストを認識できることを意味します。

ただし、応答結果には正しい画像方向情報が含まれていません。 (文書:EntityAnnotation

認識されたテキストを取得するだけでなく、オリエンテーションも取得できますか。
は、グーグル(FaceAnnotation:getRollAngle)に似て、それをサポートしてもらえPublic Issue Trackerで説明したように

enter image description here

+0

Iこの機能を使用するには、https://code.google.com/p/google-cloud-platform/issues/listのgoogle-cloud-platformの課題トラッカーに機能リクエストを投稿することを検討してください。 – Adam

+0

ありがとうございます。私はそのような問題リストがあることを知らなかった。 私はリクエストを投稿しました。 https://code.google.com/p/google-cloud-platform/issues/detail?id=194 –

答えて

3

を、当社のエンジニアリングチームは現在、この機能要求を認識し、その実現のためのETAは現在ありません。

注:画像のメタデータには、方向情報が既に用意されている場合があります。メタデータを抽出する方法の例は、Third-party libraryにあります。

戻ってきた "textAnnotations"に対して返された "boundingPoly" "頂点"をチェックするのが、広い回避策です。検出された各単語の矩形の幅と高さを計算することで、 'height'> 'width'という矩形(別名画像が横向き)の場合、画像が右上にならないかどうかを判断できます。

+0

画像が水平でなくても、Googleのクラウドビジョンが正しいテキストを画像からどのように得ることができるのか不思議です整列し、回転させる必要がある。 APIはイメージをどのくらい回転させるかをどのように知っていますか?この情報が画像のメタデータにない場合、クラウドAPIはこれをどのように見つけ出しますか? – Omnipresent

1

イメージを90度、180度、270度回転させた場合の回避策を掲載します。以下のコードをご覧ください。

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

詳細情報
私はannotateImageResponse.getTextAnnotations().get(1)はいつものルールに従わせるために、言語のヒントを追加する必要がありました。言語のヒント

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

を追加する

サンプル・コードは、時にはメタデータからの向きを取得することはできません。例えば、ユーザーが間違った向きでモバイルデバイスのカメラを使用して写真を作ったとします。 私の解決策は、Jack Fanの回答に基づいており、google-api-services-vision(Maven経由で利用可能)です。

私TextUnitクラス

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

基本法:

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

ヘルパーメソッド:

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; 
    } 
関連する問題