2016-12-26 14 views
0

私はAndroidアプリケーションでOpenCVを使用しています。矩形(領収書の形のものなど)が表示されているときに、モバイルアプリケーションが自動的に写真を撮るようにしたいと思います。私はCannyエッジ検出を使用していますが、輪郭を探しているとき、配列のサイズは1500より大きくなります。明らかに、すべての輪郭をループして最大のものを見つけるのは最適ではないので、自動的にAPIを介して等高線?OpenCV Javaの等高線

私のコード今のところ:

ArrayList contours; 

    @Override 
    public Mat onCameraFrame(final CameraBridgeViewBase.CvCameraViewFrame inputFrame) { 

    // Clear contours array on each frame 
    contours.clear(); 

    // Get Grayscale image 
    final Mat gray = inputFrame.gray(); 

    // Canny edge detection 
    Imgproc.Canny(gray, gray, 300, 1000, 5, true); 

    // New empty black matrix to store the edges captured 
    Mat dest = new Mat(); 
    Core.add(dest, Scalar.all(0), dest); 

    // Copy the edge data over to the empty black matrix 
    gray.copyTo(dest); 

    // Is there a way to filter the size of contours so that not everything is returned? Right now this function is returning a lot of contours (1500 +) 
    Imgproc.findContours(gray, contours, hirearchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); 

    return dest; 
} 

EDIT ユーザーが携帯電話を保有することになると私は領収書が表示されているときにアプリケーションが自動的に写真を撮りたいです。 Example receipt

+0

Cannyよりも優れた技術をいくつか提供している場合があります。エッジを検出するためにキャニーが使用されているため、キャニーの結果を使用してオブジェクトを検出することは賢明ではありません。パラメータを調整した後でも、あらかじめレシピの色を知っているように、色のセグメンテーションを行って、入力画像の明るさのばらつきに対抗するために色の限界のしきい値を調整することをお勧めします。 – ZdaR

+0

レシート画像は白黒になります。私は、カメラが背景から領収書を検出し、自動的にその写真を撮る方法が欲しい。 –

+0

そして、人が偽の空白の白紙を持っている場合や、背景に白い色のオブジェクトがある場合はどうなりますか? – ZdaR

答えて

0

次のPythonコードでは、使用する基本的なテクニックをカバーしています。この場合は、選択した言語のコードを翻訳するのが難しくありません。だから、技術が含まれます。

  • 見積りあなたのケースでは白であるあなたがセグメントにするオブジェクトの色、のためので、安全な上限および下限は、のように近似することができます。

    RECEIPT_LOWER_BOUND = np.array([200, 200, 200]) 
    RECEIPT_UPPER_BOUND = np.array([255, 255, 255]) 
    
  • 一部のぼかしを入力画像に適用して、色分布を滑らかにします。これにより、後で小さな輪郭が縮小されます。

    img_blurred = cv2.blur(img, (5, 5)) 
    
  • 今以上の操作を適用した後にマスクの輪郭を見つけ、上の輪郭をフィルタリングあなたのターゲット最大の輪郭

    kernel = np.ones((10, 10), dtype=np.uint8) 
    mask = cv2.dilate(mask, kernel) 
    
  • を囲む隣接小さい輪郭を削除するには、バイナリイメージに拡張を適用します。 contourAreaの基になります。

    im, contours, hierarchy = cv2.findContours(receipt_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) 
    largest_contour = max(contours, key=lambda x: cv2.contourArea(x)) 
    
  • 最後に、入力が実際にチケットであったかどうかを確認するために、しきい値を適用することができます。

コード:

import cv2 
import numpy as np 


# You may change the following ranges to define your own lower and upper BGR bounds. 
RECEIPT_LOWER_BOUND = np.array([200, 200, 200]) 
RECEIPT_UPPER_BOUND = np.array([255, 255, 255]) 


def segment_receipt(img): 
    # Blur the input image to reduce the noise which in-turn reduces the number of contours 
    img_blurred = cv2.blur(img, (5, 5)) 
    mask = cv2.inRange(img_blurred, RECEIPT_LOWER_BOUND, RECEIPT_UPPER_BOUND) 

    # Also dilate the binary mask which further reduces the salt and pepper noise 
    kernel = np.ones((10, 10), dtype=np.uint8) 
    mask = cv2.dilate(mask, kernel) 
    return mask 


def get_largest_contour_rect(image): 
    receipt_mask = segment_receipt(image) 
    im, contours, hierarchy = cv2.findContours(receipt_mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) 
    print "Number of contours found :", len(contours) 

    # Sorting the contours to get the largest one 
    largest_contour = max(contours, key=lambda x: cv2.contourArea(x)) 

    # Return the last contour in sorted list as the list is sorted in increasing order. 
    return cv2.boundingRect(largest_contour) 

image = cv2.imread("path/to/your/image.jpg") 
rect = get_largest_contour_rect(image) 

出力:J.Doe @

enter image description here

0

私は現在、このようなプロジェクトに取り組んでいると私が成功することができることしています大量の処理を行った後、画像内の最大の輪郭を分離します。残っているのは、長方形の輪郭を認識して写真を撮ることだけです。

mRgba = inputFrame.rgba(); 
    Imgproc.Canny(mRgba,mCanny,50,200); 
    Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_RGB2GRAY); 

    Imgproc.GaussianBlur(mGray, mGray1, new Size(3, 3), 1); 
    Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(9,9)); 

    Imgproc.dilate(mGray1, mGray2, kernel); 
    Imgproc.Canny(mGray2, mCanny, 50, 200); 

    Imgproc.findContours(mCanny,contours,hierarchy,Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE); 
    double maxVal = 0; 
    int maxValIdx = 0; 
    for(int contourIdx = 0; contourIdx < contours.size(); contourIdx++){ 
     double contourArea = Imgproc.contourArea(contours.get(contourIdx)); 
     if(maxVal < contourArea) 
     { 
      maxVal = contourArea; 
      maxValIdx = contourIdx; 
     } 
    } 
    Imgproc.drawContours(mRgba,contours,maxValIdx,new Scalar(0,255,255),-1); 
    return mRgba; 

私は別のプロセスでそれらを変更しました。

関連する問題