2014-02-05 159 views
2

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

,以获得在Java实现以下的OpenCV代码:

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(..)函数因此不起作用,代码似乎不起作用。我希望有人能帮忙。

+0

BufferedImage无法解析为类型? –

回答

1

这是我在项目中使用的实现的一部分。我已经有了使用算法开发的确切角点,但其余部分在此代码中给出。请勿使用point2fs。使用点阵列并将它们转换为matofpoint2fs。

包含Imshow的jar文件可以从这里下载。它在任何时间点测试你的o/p非常有效。这个包添加到您的程序: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

和u不必使用弧长。只要根据输入的清晰度给出epsilon的近似值(如2.0或3.0 ..)

(排序是用于对角落进行排序的函数)。

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) 
    {} 
} 
+0

我得到这个“BufferedImage不能解析为类型”? –