8

私はアンドロイドプラットフォームでopenCVライブラリを使用しています。 イメージから最大の四角形を検出できましたが、アプリケーションがスキャン目的で使用されているので、私はパースペクティブ変更機能をも持ちたいと思っています。openCVでRectオブジェクトの角を見つける方法は?

私は、perspectiveTransformとwarpPerspectiveTransformの適用方法を知っていますが、そのためにはソースポイントの矩形の角が必要です。

最初のコーナーの座標(左上)と幅/高さがRectオブジェクトに関連付けられているという事実を考えると、コーナーを見つけるのは非常に簡単ですが、問題は回転した矩形(通常のboundingRect軸に平行でない辺)の場合、これらの値は非常に異なります。この場合、軸に平行な辺を持つ別の矩形に対応する値が格納され、回転矩形を覆うので、実際の矩形の角を検出できなくなります。

また、画像からシートを検出するためのこれらの2つのアルゴリズムを比較したいと思います。

  1. キャニーエッジ - >最大の輪郭 - >最大四角形は - >コーナーを見つける - >斜視変化

  2. キャニーedge->ハフ線 - >線の交点 - >斜視変化

Rectオブジェクトがあれば、私に尋ねたいことがあります。その長方形のすべての角を取得する方法は?

ありがとうございます。

答えて

11

私の質問には非常にエキサイティングです!それは簡単でしたが、ちょうど適切な関連文書ではないものから始めるときに起こります。

openCVの実装では定義されていなかった一般的な四角形の角を得ることができず、ほとんど不可能でした。

私は、最大Square検出のためにstackoverflowの標準コードに従っています。 approxCurve自体を使用してコーナーを簡単に見つけることができます。

//白黒

 Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BGR2GRAY); 

     //convert the image to black and white does (8 bit) 
     Imgproc.Canny(imgSource, imgSource, 50, 50); 

     //apply gaussian blur to smoothen lines of dots 
     Imgproc.GaussianBlur(imgSource, imgSource, new org.opencv.core.Size(5, 5), 5); 

     //find the contours 
     List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); 
     Imgproc.findContours(imgSource, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); 

     double maxArea = -1; 
     int maxAreaIdx = -1; 
     Log.d("size",Integer.toString(contours.size())); 
     MatOfPoint temp_contour = contours.get(0); //the largest is at the index 0 for starting point 
     MatOfPoint2f approxCurve = new MatOfPoint2f(); 
     MatOfPoint largest_contour = contours.get(0); 
     //largest_contour.ge 
     List<MatOfPoint> largest_contours = new ArrayList<MatOfPoint>(); 
     //Imgproc.drawContours(imgSource,contours, -1, new Scalar(0, 255, 0), 1); 

     for (int idx = 0; idx < contours.size(); idx++) { 
      temp_contour = contours.get(idx); 
      double contourarea = Imgproc.contourArea(temp_contour); 
      //compare this contour to the previous largest contour found 
      if (contourarea > maxArea) { 
       //check if this contour is a square 
       MatOfPoint2f new_mat = new MatOfPoint2f(temp_contour.toArray()); 
       int contourSize = (int)temp_contour.total(); 
       MatOfPoint2f approxCurve_temp = new MatOfPoint2f(); 
       Imgproc.approxPolyDP(new_mat, approxCurve_temp, contourSize*0.05, true); 
       if (approxCurve_temp.total() == 4) { 
        maxArea = contourarea; 
        maxAreaIdx = idx; 
        approxCurve=approxCurve_temp; 
        largest_contour = temp_contour; 
       } 
      } 
     } 

     Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BayerBG2RGB); 
     sourceImage =Highgui.imread(Environment.getExternalStorageDirectory(). 
       getAbsolutePath() +"/scan/p/1.jpg"); 
     double[] temp_double; 
     temp_double = approxCurve.get(0,0);  
     Point p1 = new Point(temp_double[0], temp_double[1]); 
     //Core.circle(imgSource,p1,55,new Scalar(0,0,255)); 
     //Imgproc.warpAffine(sourceImage, dummy, rotImage,sourceImage.size()); 
     temp_double = approxCurve.get(1,0);  
     Point p2 = new Point(temp_double[0], temp_double[1]); 
     // Core.circle(imgSource,p2,150,new Scalar(255,255,255)); 
     temp_double = approxCurve.get(2,0);  
     Point p3 = new Point(temp_double[0], temp_double[1]); 
     //Core.circle(imgSource,p3,200,new Scalar(255,0,0)); 
     temp_double = approxCurve.get(3,0);  
     Point p4 = new Point(temp_double[0], temp_double[1]); 
     // Core.circle(imgSource,p4,100,new Scalar(0,0,255)); 
     List<Point> source = new ArrayList<Point>(); 
     source.add(p1); 
     source.add(p2); 
     source.add(p3); 
     source.add(p4); 
     Mat startM = Converters.vector_Point2f_to_Mat(source); 
     Mat result=warp(sourceImage,startM); 
     return result; 

透視のために使用される関数は、以下に与えられる変換するために画像を変換する:私は各コーナー座標の両方必要

public Mat warp(Mat inputMat,Mat startM) { 
      int resultWidth = 1000; 
      int resultHeight = 1000; 

      Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC4); 



      Point ocvPOut1 = new Point(0, 0); 
      Point ocvPOut2 = new Point(0, resultHeight); 
      Point ocvPOut3 = new Point(resultWidth, resultHeight); 
      Point ocvPOut4 = new Point(resultWidth, 0); 
      List<Point> dest = new ArrayList<Point>(); 
      dest.add(ocvPOut1); 
      dest.add(ocvPOut2); 
      dest.add(ocvPOut3); 
      dest.add(ocvPOut4); 
      Mat endM = Converters.vector_Point2f_to_Mat(dest);  

      Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM); 

      Imgproc.warpPerspective(inputMat, 
            outputMat, 
            perspectiveTransform, 
            new Size(resultWidth, resultHeight), 
            Imgproc.INTER_CUBIC); 

      return outputMat; 
     } 
+1

これは、遠近法を取得して罫線を見つけるための、これまでのJavaの最良のソリューションです。コードありがとうございました – Ujju

+0

@AnkurGautam私はImgproc.FindContoursメソッドを使用しているとき、なぜデータがリストに来るのですか?間違っている。ありがとうございました! – XTL

+0

@AnkurGautamまた、私はあなたに個人的に連絡することができますか?ありがとう! – XTL

2
1. find the coordinate of left ,right, top,bottom point of the rect 
2. min_x = min(left.x right.x,top.x,bottom.x) 
    min_y = min(left.y right.y,top.y,bottom.y) 
    max_x = max(left.x right.x,top.x,bottom.x) 
    max_y = max(left.y right.y,top.y,bottom.y) 
3. the corners's coordinate is the point with the min_x, min_y ,max_x, max_y 
+0

、iが「ドンその場合は助けになると思います! –

+0

min_xが見つかったら両方の座標を記録できますか? – michaeltang

+0

、取得していない、説明してください?四角形を負の角度と言うことで回転させるとどうなりますか? ? –

関連する問題