JavaCV透视校正 [英] JavaCV Perspective Correction

查看:512
本文介绍了JavaCV透视校正的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我转换了使用OpenCV和C ++实现的透视校正代码:
https://opencv-code.com/tutorials/automatic-perspective-correction-for-quadrilateral-objects/

I converted the perspective correction code implemented using OpenCV and C++ at: https://opencv-code.com/tutorials/automatic-perspective-correction-for-quadrilateral-objects/

获取以下在Java中实现的OpenCV代码:

to obtain the following OpenCV code implemented in Java:

public class project 
{
static Point2f center;
public static void main(String args[])
{
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    center = new Point2f(0,0);
    Mat src = new Mat();
    src = Highgui.imread("image.jpg");
    if(src == null)
    {
        System.out.println("Image not loaded");
        System.exit(1);
    }

    Mat bw = new Mat();

    Imgproc.cvtColor(src, bw, Imgproc.COLOR_BGR2GRAY);
    Imgproc.blur(bw, bw, new Size(3,3));
    Imgproc.Canny(bw, bw, 100, 100, 3,true);

     Mat lines = new Mat();
        int threshold = 70;
        int minLineSize = 30;
        int lineGap = 10;

        Imgproc.HoughLinesP(bw, lines, 1, Math.PI / 180, threshold,
                minLineSize, lineGap);

        for (int x = 0; x < lines.cols(); x++) 
        {

            double[] vec = lines.get(0, x);
            double[] val = new double[4];

            val[0] = 0;
            val[1] = ((float) vec[1] - vec[3]) / (vec[0] - vec[2]) * -vec[0] + vec[1];
            val[2] = src.cols();
            val[3] = ((float) vec[1] - vec[3]) / (vec[0] - vec[2]) * (src.cols() - vec[2]) + vec[3];

            lines.put(0, x, val);

        }

        List<Point2f> corners = new ArrayList<Point2f>();
        for (int i = 0; i < lines.cols(); i++)
        {
            for (int j = i+1; j < lines.cols(); j++)
            {
                Mat m1 = null,m2 = null;
                double[] d1 = lines.get(0,i);
                double[] d2 = lines.get(0, j);
                m1.put(0, i, d1);
                m2.put(0, j, d2);
                Point2f pt = computeIntersect(m1, m2);
                if (pt.x >= 0 && pt.y >= 0)
                    corners.add(pt);
            }
        }

        List<Point2f> approx = new ArrayList<Point2f>();
        List<Point2f> curve;
        MatOfPoint2f mat2f = new MatOfPoint2f();
        for(int k=0;k<corners.size();++k)
        {
            Point2f rec = corners.get(k);
            Point p = new Point(rec.x,rec.y);
            mat2f.fromArray(p);
        }
        MatOfPoint2f mat2frec = new MatOfPoint2f();
        Imgproc.approxPolyDP(mat2f, mat2frec, Imgproc.arcLength(mat2f, true) * 0.02,true);

        if (approx.size() != 4)
        {
            System.out.println("The object is not quadrilateral!");

        }

        // Get mass center
        for (int i = 0; i < corners.size(); i++)
        {
            center.x = center.x + corners.get(i).x;
            center.y = center.y + corners.get(i).y;
        }
        center.x *= (1. / corners.size());
        center.y *= (1. / corners.size());

        sortCorners(corners, center);

        Mat dst = src.clone();

        // Draw lines
        for (int i = 0; i < lines.cols(); i++)
        {
            double[] v = lines.get(0, i);
            Scalar cc = new Scalar(0,255,0,0);
            Core.line(dst, new Point(v[0], v[1]), new Point(v[2], v[3]), cc);

        }

        Scalar c1 = new Scalar(0,0,255,0);
        Scalar c2 = new Scalar(0,255,0,0);
        Scalar c3 = new Scalar(255,0,0,0);
        Scalar c4 = new Scalar(255,255,255,0);

        // Draw corner points

        Core.circle(dst, new Point(corners.get(0).x,corners.get(0).y), 3, c1, 2);
        Core.circle(dst, new Point(corners.get(1).x,corners.get(1).y), 3, c2, 2);
        Core.circle(dst, new Point(corners.get(2).x,corners.get(2).y), 3, c3, 2);
        Core.circle(dst, new Point(corners.get(3).x,corners.get(3).y), 3, c4, 2);

        Scalar c5 = new Scalar(0,255,255,0);
        // Draw mass center
        Core.circle(dst, new Point(center.x,center.y), 3, c5, 2);

        Mat quad = Mat.zeros(300, 220, CvType.CV_8UC3);

        List<Point2f> quad_pts = new ArrayList<Point2f>();
        quad_pts.add(new Point2f(0, 0));
        quad_pts.add(new Point2f(quad.cols(), 0));
        quad_pts.add(new Point2f(quad.cols(), quad.rows()));
        quad_pts.add(new Point2f(0, quad.rows()));


        Mat transmtx = Imgproc.getPerspectiveTransform((Mat) corners, (Mat) quad_pts);
        Imgproc.warpPerspective(src, quad, transmtx, quad.size());

        MatOfByte matOfByte = new MatOfByte();

        Highgui.imencode(".jpg", dst, matOfByte); 
        byte[] byteArray = matOfByte.toArray();
        BufferedImage bufImage = null;
        try 
        {
            InputStream in = new ByteArrayInputStream(byteArray);
            bufImage = ImageIO.read(in);
            File outputfile = new File("Image.jpg");
            ImageIO.write(bufImage, "jpg", outputfile);
        } 
        catch (Exception e) {
            e.printStackTrace();
        }

        MatOfByte matOfByte2 = new MatOfByte();

        Highgui.imencode(".jpg", dst, matOfByte2); 
        byte[] byteArray2 = matOfByte2.toArray();
        BufferedImage bufImage2 = null;
        try 
        {
            InputStream in = new ByteArrayInputStream(byteArray2);
            bufImage2 = ImageIO.read(in);
            File outputfile2 = new File("Quadrilateral.jpg");
            ImageIO.write(bufImage, "jpg", outputfile2);
        } 
        catch (Exception e) {
            e.printStackTrace();
        }


}
static Point2f computeIntersect(Mat es, Mat es2)
{
    int size = (int) es.total() * es.channels();
    float[] buff = new float[size];
    es.get(0, 0, buff);

    int size1 = (int) es.total() * es.channels();
    float[] buff1 = new float[size1];
    es.get(0, 0, buff1);

    float x1=buff[0], y1 = buff[1], x2 = buff[2], y2 = buff[3];
    float x3 = buff1[0], y3 = buff1[1], x4 = buff1[2], y4 = buff1[3];
    float denom;
    float d;
    d = (Float) null;
    d = (float)((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4));
    if (d != (Float) null)
    {
        Point2f pt = new Point2f();
        pt.x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
        pt.y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
        return pt;
    }
    else
        return new Point2f(-1, -1);
}

static void sortCorners(List<Point2f> corners,Point2f center)
{
    List<Point2f> top = null, bot = null;

    for (int i = 0; i < corners.size(); i++)
    {
        if (corners.get(i).y < center.y)
            top.add(corners.get(i));
        else
            bot.add(corners.get(i));
    }

    Point2f tl = top.get(0).x > top.get(1).x ? top.get(1) : top.get(0);
    Point2f tr = top.get(0).x > top.get(1).x ? top.get(0) : top.get(1);
    Point2f bl = bot.get(0).x > bot.get(1).x ? bot.get(1) : bot.get(0);
    Point2f br = bot.get(0).x > bot.get(1).x ? bot.get(0) : bot.get(1);

    corners.clear();
    corners.add(tl);
    corners.add(tr);
    corners.add(br);
    corners.add(bl);
}



}

我遇到了无法转换列表< Point2f>到MatOfPoint2f。因此arcLength(..)函数不工作,代码似乎不工作。我希望有人可以帮助。

I'm having trouble converting List< Point2f > to MatOfPoint2f. The arcLength(..) function is therefore not working and the code doesn't seem to work. I'm hoping someone can help.

推荐答案

这是我在项目中使用的一部分实现。我已经使用algo i开发了确切的角点但其余的在这段代码中给出。不要使用point2fs。使用点数组,并将它们转换为matofpoint2fs。

This a part of the implementation that i used in my project.I already had the exact corner points using an algo i developed but the rest is given in this code.Do not use point2fs. Use point arrays and them convert them into matofpoint2fs.

包含Imshow的jarfile可以从这里下载。它是非常有效的测试你的o / p在任何时间点。将此程序包添加到您的程序中: https://github.com/master-atul/ImShow- Java-OpenCV

the jarfile containing Imshow can be downloaded from here.It is very effective in testing your o/p at any point of time. Add this package to your program: https://github.com/master-atul/ImShow-Java-OpenCV

关于approxpolydp的详细信息:
http://docs.opencv.org/java/org /opencv/imgproc/Imgproc.html#approxPolyDP%28org.opencv.core.MatOfPoint2f,org.opencv.core.MatOfPoint2f,double,boolean%29

Details regarding approxpolydp: http://docs.opencv.org/java/org/opencv/imgproc/Imgproc.html#approxPolyDP%28org.opencv.core.MatOfPoint2f,org.opencv.core.MatOfPoint2f,double,boolean%29

和u不必使用arclength。根据输入的清晰度(例如2.0或3.0 ..)给出epsilon的大约值。

And u don't have to use arclength. Just give an approx value for epsilon depending on the clarity of your input.(like 2.0 or 3.0..)

(sort是用于排序角的函数)。

(sort is the function used to sort the corners).

int a[][],imgarr[][];

Point p[];

BufferedImage img;

int w,h;
void sort()
{
int x = (a[0][0] + a[1][0] + a[2][0] + a[3][0])/4;
int y = (a[0][1] + a[1][1] + a[2][1] + a[3][1])/4;
int j = 0;
int order[] = new int[4];
double tans[] = new double[4];
double tans1[] = new double[4];
int tmpar[][] = new int[4][2];
p = new Point[4];       
for(int i = 0;i<4;i++)
{
tans1[i] = tans[i] = Math.atan2(a[i][1] - y , a[i][0] - x);//finding angles for sorting corners 
}
Arrays.sort(tans1);
for(int i = 0;i<2;i++)
{
double temp = tans1[i];
tans1[i]= tans1[3-i];
tans1[3-i] = temp;
}
for(int i=0;i<4;i++)
{
for(j = 0;j<4;j++)
{
    if(tans1[i]==tans[j])
        break;
}
order[i] = j;
}
for(int i = 0;i<4;i++)
{
for(j=0;j<2;j++)
{
    tmpar[i][j] = a[i][j];
}
}
for(int i = 0;i<4;i++)
{
for(j = 0;j<2;j++)
{
        a[i][j] = tmpar[order[i]][j];
        }
    }
    p[0] = new Point(a[0][1],a[0][0]);
    p[1] = new Point(a[1][1],a[1][0]);
    p[2] = new Point(a[2][1],a[2][0]);
    p[3] = new Point(a[3][1],a[3][0]);
}
void transform() throws Exception
{
    Point farray[] = new Point[4];      
    try
    {
        img = ImageIO.read(new File("C:/Users/Documents/a.jpg"));
    }
    catch(Exception r)
    {
        System.out.println("no file");
    }
    PixelGrabber pg;
    if(img==null)
    {
        return;
    }
    w = img.getWidth();
    h = img.getHeight();
    imgarr = new int[h][w];
    try
    {           
        for(int i = 0; i < h ; i++)
        {
            pg = new PixelGrabber(img,0,i,w,1,imgarr[i],0,w);               
            pg.grabPixels();    
        }
        changeto256();
    }
    catch(Exception e)
    {
        System.out.println("here "+e);
    }
    int m=0;        
    byte array[] = new byte[w*h];
    int iar[] = new int[w*h];
    for(int i = 0 ; i < h ; i++)
    {
        for(int j = 0 ; j < w ; j++)
        {
            array[m++]= (byte)imgarr[i][j];
        }
    }
    farray[3] = new Point(0,0);
    farray[0] = new Point(w,0);
    farray[1] = new Point(w,h);
    farray[2] = new Point(0,h);


    Mat mat = new Mat(h,w, CvType.CV_8U);
    mat.put(0, 0, array);
    Imshow is = new Imshow("try");
    MatOfPoint2f quad = new MatOfPoint2f(p);
    MatOfPoint2f rect = new MatOfPoint2f(farray);
    Mat transmtx = Imgproc.getPerspectiveTransform(quad,rect);
    Mat output = new Mat(w,h,CvType.CV_8U); 
    Imgproc.warpPerspective(mat, output, transmtx, new size(w,h),Imgproc.INTER_CUBIC);
    is.showImage(output);       
    MatOfByte matOfByte = new MatOfByte();
    Highgui.imencode(".jpg", output, matOfByte); 
    byte[] byteArray = matOfByte.toArray();
    File f = new File("retrieve1.jpg");
    BufferedImage img1 =null;
    InputStream in = new ByteArrayInputStream(byteArray);
    img1  = ImageIO.read(in);
    WritableRaster raster = (WritableRaster)img1.getData();
    raster.setDataElements(0,0,byteArray);
    img1.setData(raster);
    try
    {
        ImageIO.write(img1,"jpg",f);
    }
    catch(Exception e)
    {}
}

这篇关于JavaCV透视校正的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆