2013-07-14 6 views
6

適切な画像が表示されないため、getPerspectiveTransformのパラメータとちょっと混乱します。ここに私のコードです。 original_image変数は、私がトリミングして新しいイメージ(このようなもの)を作成する正方形のオブジェクト(およびその他のオブジェクト)を含むイメージです(Android OpenCV Find Largest Square or Rectangleなど)。変数p1、p2、p3、およびp4は、画像内の最大正方形/矩形の角の座標です。 p1は左上、p2は右上、p3は右下、p4は左下(時計回りの割り当て)です。Android OpenCV getPerspectiveTransformとwarpPerspective

Mat src = new Mat(4,1,CvType.CV_32FC2); 
    src.put((int)p1.y,(int)p1.x, (int)p2.y,(int)p2.x, (int)p4.y,(int)p4.x, (int)p3.y,(int)p3.x); 
    Mat dst = new Mat(4,1,CvType.CV_32FC2); 
    dst.put(0,0, 0,original_image.width(), original_image.height(),original_image.width(), original_image.height(),0); 

    Mat perspectiveTransform = Imgproc.getPerspectiveTransform(src, dst); 
    Mat cropped_image = original_image.clone(); 
    Imgproc.warpPerspective(untouched, cropped_image, perspectiveTransform, new Size(512,512)); 

cropped_imageを表示しようとすると、「私はそれが何であるかわかりません」というイメージが表示されます。私はgetPerspectiveTransform()の私のパラメータが間違っている(またはそれ)と思います。助けてください。ありがとう!

更新:私のコードをデバッグすると、四角形/矩形のエッジが正しくないことがわかりました.P4以外のいくつかは正しくあります。これは画像内の正方形または矩形のエッジを検出するコードです。私の画像は、白い輪郭を持つ最大の正方形/矩形の輪郭を除いてすべて黒です。

//we will find the edges of the new_image (corners of the square/rectangle) 
    Point p1 = new Point(10000, 10000); //upper left; minX && minY 
    Point p2 = new Point(0, 10000); //upper right; maxX && minY 
    Point p3 = new Point(0, 0); //lower right; maxX && maxY 
    Point p4 = new Point(10000, 0); //lower left; minX && maxY 
    double[] temp_pixel_color; 
    for (int x=0; x<new_image.rows(); x++) { 
     for (int y=0; y<new_image.cols(); y++) { 
      temp_pixel_color = new_image.get(x, y); //we have a black and white image so we only have one color channel 
      if (temp_pixel_color[0] > 200) { //we found a white pixel 
       if (x<=p1.x && y<=p1.y) { //for p1, minX && minY 
        p1.x = x; 
        p1.y = y; 
       } 
       else if (x>=p2.x && y<=p2.y) { //for p2, maxX && minY 
        p2.x = x; 
        p2.y = y; 
       } 
       else if (x>=p3.x && y>=p3.y) { //for p3, maxX && maxY 
        p3.x = x; 
        p3.y = y; 
       } 
       else if (x<=(int)p4.x && y>=(int)p4.y) { //for p4, minX && maxY 
        p4.x = x; 
        p4.y = y; 
       } 
      } 
     } 
    } 

ここは私のサンプル画像です。エッジが検出された後、それらが描かれているように着色された円を無視する:

enter image description here

が更新:2013年7月16日 Iは、最大4-尖った輪郭のみapproxCurveを使用して今の角を検出することができます。ここで

private Mat findLargestRectangle(Mat original_image) { 
    Mat imgSource = original_image; 
    //Mat untouched = original_image.clone(); 

    //convert the image to black and white 
    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 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; 
    MatOfPoint temp_contour = contours.get(0); //the largest is at the index 0 for starting point 
    MatOfPoint2f approxCurve = new MatOfPoint2f(); 
    MatOfPoint2f maxCurve = new MatOfPoint2f(); 
    List<MatOfPoint> largest_contours = new ArrayList<MatOfPoint>(); 
    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(); 
      Imgproc.approxPolyDP(new_mat, approxCurve, contourSize*0.05, true); 
      if (approxCurve.total() == 4) { 
       maxCurve = approxCurve; 
       maxArea = contourarea; 
       maxAreaIdx = idx; 
       largest_contours.add(temp_contour); 
      } 
     } 
    } 

    //create the new image here using the largest detected square 
    Mat new_image = new Mat(imgSource.size(), CvType.CV_8U); //we will create a new black blank image with the largest contour 
    Imgproc.cvtColor(new_image, new_image, Imgproc.COLOR_BayerBG2RGB); 
    Imgproc.drawContours(new_image, contours, maxAreaIdx, new Scalar(255, 255, 255), 1); //will draw the largest square/rectangle 

    double temp_double[] = maxCurve.get(0, 0); 
    Point p1 = new Point(temp_double[0], temp_double[1]); 
    Core.circle(new_image, new Point(p1.x, p1.y), 20, new Scalar(255, 0, 0), 5); //p1 is colored red 
    String temp_string = "Point 1: (" + p1.x + ", " + p1.y + ")"; 

    temp_double = maxCurve.get(1, 0); 
    Point p2 = new Point(temp_double[0], temp_double[1]); 
    Core.circle(new_image, new Point(p2.x, p2.y), 20, new Scalar(0, 255, 0), 5); //p2 is colored green 
    temp_string += "\nPoint 2: (" + p2.x + ", " + p2.y + ")"; 

    temp_double = maxCurve.get(2, 0);  
    Point p3 = new Point(temp_double[0], temp_double[1]); 
    Core.circle(new_image, new Point(p3.x, p3.y), 20, new Scalar(0, 0, 255), 5); //p3 is colored blue 
    temp_string += "\nPoint 3: (" + p3.x + ", " + p3.y + ")"; 

    temp_double = maxCurve.get(3, 0); 
    Point p4 = new Point(temp_double[0], temp_double[1]); 
    Core.circle(new_image, new Point(p4.x, p4.y), 20, new Scalar(0, 255, 255), 5); //p1 is colored violet 
    temp_string += "\nPoint 4: (" + p4.x + ", " + p4.y + ")"; 

    TextView temp_text = (TextView)findViewById(R.id.temp_text); 
    temp_text.setText(temp_string); 

    return new_image; 
} 

試料結果の画像である:ここで私のコードである

enter image description here

Iは正方形/長方形の角のために円を描かれていると私は、すべて表示するためのTextViewを添加しました4点

+0

[OK]をクリックします。時間があるときにコードを上書きしますが、これまでは簡単な方法を教えています。メソッド「CV_CHAIN_APPROX_SIMPLE」で[findContours](http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours#findcontours)を使用すると、コーナーポイントをすぐに取得できます。 – baci

+0

また、それらは「エッジ」ではなく「コーナー」です:) – baci

+0

「src」と「dst」が正しく作成されていますか?マットの代わりに "Point2f"配列を使う方が良いと思います。 – baci

答えて

1

これは私のために働いた。 src_mat.putには最初に0,0を、次に座標の浮動小数点値を指定する必要があります。

Mat mat=Highgui.imread("inputImage.jpg"); 
    Mat src_mat=new Mat(4,1,CvType.CV_32FC2); 
    Mat dst_mat=new Mat(4,1,CvType.CV_32FC2); 


    src_mat.put(0,0,407.0,74.0,1606.0,74.0,420.0,2589.0,1698.0,2589.0); 
    dst_mat.put(0,0,0.0,0.0,1600.0,0.0, 0.0,2500.0,1600.0,2500.0); 
    Mat perspectiveTransform=Imgproc.getPerspectiveTransform(src_mat, dst_mat); 

    Mat dst=mat.clone(); 

    Imgproc.warpPerspective(mat, dst, perspectiveTransform, new Size(1600,2500)); 
    Highgui.imwrite("resultImage.jpg", dst);