Android OpenCV getPerspectiveTransform和warpPerspective

Android OpenCV getPerspectiveTransform和warpPerspective,android,opencv,transformation,warp,Android,Opencv,Transformation,Warp,我对getPerspectiveTransform的参数有点困惑,因为我看不到正确的图像。这是我的密码。原始的_image变量是包含一个方形对象(以及其他一些对象)的图像,我希望裁剪该对象并创建一个新图像(类似于这样)。变量p1、p2、p3和p4是图像中最大正方形/矩形的角的坐标。p1是左上角,p2是右上角,p3是右下角,p4是左下角(顺时针) 当我试图显示裁剪的图像时,我会得到一个“我不知道它是什么”的图像。我认为getPerspectiveTransform()中的参数不正确(或者是不正确)

我对getPerspectiveTransform的参数有点困惑,因为我看不到正确的图像。这是我的密码。原始的_image变量是包含一个方形对象(以及其他一些对象)的图像,我希望裁剪该对象并创建一个新图像(类似于这样)。变量p1、p2、p3和p4是图像中最大正方形/矩形的角的坐标。p1是左上角,p2是右上角,p3是右下角,p4是左下角(顺时针)

当我试图显示裁剪的图像时,我会得到一个“我不知道它是什么”的图像。我认为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;
                }
            }
        }
    }
//我们将找到新图像的边缘(正方形/矩形的角)
点p1=新点(10000,10000)//左上角;貂皮&貂皮
点p2=新点(0,10000)//右上角;maxX&minY
点p3=新点(0,0)//右下角;maxX&&maxY
点p4=新点(10000,0)//左下角;minX&maxY
双[]温度像素颜色;
对于(int x=0;x maxArea){
//检查此轮廓是否为正方形
MatOfPoint2f new_mat=新MatOfPoint2f(temp_contour.toArray());
int contourSize=(int)temp_contour.total();
Imgproc.approxPolyDP(新垫,approxCurve,轮廓尺寸*0.05,真);
如果(approxCurve.total()==4){
maxCurve=approxCurve;
最大面积=轮廓面积;
maxAreaIdx=idx;
最大等高线。添加(温度等高线);
}
}
}
//使用检测到的最大正方形在此处创建新图像
Mat new_image=new Mat(imgSource.size(),CvType.CV_8U)//我们将创建一个具有最大轮廓的新的黑色空白图像
Imgproc.cvtColor(新图像,新图像,Imgproc.COLOR\bg2rgb);
Imgproc.drawContours(新的_图像,轮廓,maxAreaIdx,新的标量(255,255,255),1)//将绘制最大的正方形/矩形
double temp_double[]=maxCurve.get(0,0);
点p1=新点(温度双精度[0],温度双精度[1]);
圆(新的_图像,新的点(p1.x,p1.y),20,新的标量(255,0,0),5)//p1是红色的
String temp_String=“第1点:(“+p1.x+”,“+p1.y+”);
temp_double=maxCurve.get(1,0);
点p2=新点(温度双精度[0],温度双精度[1]);
圆(新的_图像,新的点(p2.x,p2.y),20,新的标量(0,255,0),5)//p2是绿色的
临时字符串+=“\n点2:(“+p2.x+”,“+p2.y+”);
temp_double=maxCurve.get(2,0);
点p3=新点(温度双精度[0],温度双精度[1]);
圆心(新的_图像,新的点(p3.x,p3.y),20,新的标量(0,0,255),5)//p3是蓝色的
临时字符串+=“\n点3:(“+p3.x+”,“+p3.y+”);
temp_double=maxCurve.get(3,0);
点p4=新点(温度双精度[0],温度双精度[1]);
圆(新的_图像,新的点(p4.x,p4.y),20,新的标量(0,255,255),5)//p1是紫色的
临时字符串+=“\n点4:(“+p4.x+”,“+p4.y+”);
TextView temp_text=(TextView)findViewById(R.id.temp_text);
temp_text.setText(temp_字符串);
返回新的图像;
}
以下是示例结果图像:


我在正方形/矩形的角上画了圆圈,还添加了一个文本视图来显示所有的四个点。

这对我很有用。在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);

好的,我会在有时间的时候检查你的代码,但在那之前我会告诉你一个更简单的方法。如果使用“CV_CHAIN_APPROX_SIMPLE”方法,可以立即获得角点。此外,这些不是“边”,而是“角”:)您确定“src”和“dst”创建正确吗?我认为最好使用“Point2f”数组,而不是Mat。另外,不要寻找“白色”像素。只需使用轮廓。检查所有轮廓点,保存具有最小x的点。。。我认为Java/Android没有Point2f数据类型。在Java或Android中,Imgproc.getPerspectiveTransform()接受两个Mat参数。我错过什么了吗?再次感谢
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;
}
    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);