2016-04-15 50 views
0

openCVとtesseractを使用してカードを読み取ります。私は現在、「私はカメラからのすべての長方形や正方形を検出した後で最大の矩形をトリミングする方法について説明します。以下のコードで、見てくださいで立ち往生しています。あなたはこれで何をしたいのでOpenCVを使用して最大の矩形を切り抜く

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {  
     if (Math.random()>0.80) {  
      findSquares(inputFrame.rgba().clone(),squares);  
     } 

     Mat image = inputFrame.rgba();  
     Imgproc.drawContours(image, squares, -1, new Scalar(0,0,255));  
     return image; 
    } 

    int thresh = 50, N = 11; 

    // helper function: 
    // finds a cosine of angle between vectors 
    // from pt0->pt1 and from pt0->pt2 
    double angle(Point pt1, Point pt2, 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)/Math.sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); 
    } 

    // returns sequence of squares detected on the image. 
    // the sequence is stored in the specified memory storage 
    void findSquares(Mat image, List<MatOfPoint> squares) 
    {  
     squares.clear();  
     Mat smallerImg=new Mat(new Size(image.width()/2, image.height()/2),image.type());  
     Mat gray=new Mat(image.size(),image.type());  
     Mat gray0=new Mat(image.size(), CvType.CV_8U);  
     // down-scale and upscale the image to filter out the noise 
     Imgproc.pyrDown(image, smallerImg, smallerImg.size()); 
     Imgproc.pyrUp(smallerImg, image, image.size());  
     // find squares in every color plane of the image 
     for(int c = 0; c < 3; c++) 
     {  
      extractChannel(image, gray, c);  
      // try several threshold levels 
      for(int l = 1; l < N; l++) 
      { 
       //Cany removed... Didn't work so well   
       Imgproc.threshold(gray, gray0, (l+1)*255/N, 255, Imgproc.THRESH_BINARY);   
       List<MatOfPoint> contours=new ArrayList<MatOfPoint>(); 

       // find contours and store them all as a list 
       Imgproc.findContours(gray0, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);  
       MatOfPoint approx=new MatOfPoint();  
       // test each contour 
       for(int i = 0; i < contours.size(); i++) 
       {  
        // approximate contour with accuracy proportional 
        // to the contour perimeter 
        approx = approxPolyDP(contours.get(i), Imgproc.arcLength(new MatOfPoint2f(contours.get(i).toArray()), 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.toArray().length == 4 && 
          Math.abs(Imgproc.contourArea(approx)) > 1000 && 
          Imgproc.isContourConvex(approx)) 
        { 
         double maxCosine = 0; 

         for(int j = 2; j < 5; j++) 
         { 
          // find the maximum cosine of the angle between joint edges 
          double cosine = Math.abs(angle(approx.toArray()[j%4], approx.toArray()[j-2], approx.toArray()[j-1])); 
          maxCosine = Math.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.add(approx); 
        } 
       } 
      } 
     } 
    } 

    void extractChannel(Mat source, Mat out, int channelNum) { 
     List<Mat> sourceChannels=new ArrayList<Mat>(); 
     List<Mat> outChannel=new ArrayList<Mat>();  
     Core.split(source, sourceChannels);  
     outChannel.add(new Mat(sourceChannels.get(0).size(),sourceChannels.get(0).type()));  
     Core.mixChannels(sourceChannels, outChannel, new MatOfInt(channelNum,0));  
     Core.merge(outChannel, out); 
    } 

    MatOfPoint approxPolyDP(MatOfPoint curve, double epsilon, boolean closed) { 
     MatOfPoint2f tempMat=new MatOfPoint2f();  
     Imgproc.approxPolyDP(new MatOfPoint2f(curve.toArray()), tempMat, epsilon, closed);  
     return new MatOfPoint(tempMat.toArray()); 
    } 
} 
+2

サンプル入力と欲しい結果イメージ – Micka

答えて

0

あなたがアルゴリズムの効率や複雑さを心配していない場合は(おそらくそうかもしれませんが)、aproxを四角形に追加する前に線を追加するだけで、四角形を計算することができます。あなたの現在のおよその輪郭領域。次に、正方形の端に達するまで、または現在の輪郭の領域が領域iより大きい正方形の要素に達するまで、正方形のインデックスの輪郭領域をチェックするループを持つそのインデックスの輪郭。これは選択ソートと呼ばれ、シンプルで低速ですが、動作します。

さらに収益を上げたい場合は、ソートはコンピュータサイエンスの非常に興味深い概念です。あなたの四角形の配列を並べ替えるより効率的な方法については、heapsort、mergesort、quicksortで読んでください。ソートの基礎を学ぶことができますhere

幸運!

+0

こんにちは@bstadt、これは私が探しているものではありません、私は実際に私が検出した四角形にのみ画像をトリミングまたはサイズ変更するコードを探しています。私のイメージには1つの正方形しか含まれないので、ソートは必要ありません。 –

関連する問題