Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
opencvjava:从图像中提取卡片_Java_Opencv_Image Processing - Fatal编程技术网

opencvjava:从图像中提取卡片

opencvjava:从图像中提取卡片,java,opencv,image-processing,Java,Opencv,Image Processing,我正在尝试使用OpenCV和Java实现一些图像处理,以从图像中提取卡片 我的做法如下: 转换为BGR图像 转换为灰度图像 应用高斯模糊 应用Canny边缘检测 扩张 寻找轮廓 找到最大的轮廓 使用APROXPOLYDP查找最大轮廓的角点 沿最大轮廓获取裁剪图像的自顶向下视图 在步骤8中,我面临一些问题,因为我没有获得适当的角点/顶点。以下示例图像显示了该场景: 原始图像 经过边缘检测和膨胀(如何获得适当的边?这里我有断裂的边。无法使Hough变换工作) 在找到顶点之后。(以绿色显示) 代

我正在尝试使用OpenCV和Java实现一些图像处理,以从图像中提取卡片

我的做法如下:

  • 转换为BGR图像
  • 转换为灰度图像
  • 应用高斯模糊
  • 应用Canny边缘检测
  • 扩张
  • 寻找轮廓
  • 找到最大的轮廓
  • 使用APROXPOLYDP查找最大轮廓的角点
  • 沿最大轮廓获取裁剪图像的自顶向下视图
  • 在步骤8中,我面临一些问题,因为我没有获得适当的角点/顶点。以下示例图像显示了该场景:

    原始图像

    经过边缘检测和膨胀(如何获得适当的边?这里我有断裂的边。无法使Hough变换工作)

    在找到顶点之后。(以绿色显示)

    代码如下:

    System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
    
             //load Image
             File input = new File("card4.png");
             BufferedImage image = ImageIO.read(input); 
             byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
    
             //put read image to Mat
             mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); //original Mat
             mat.put(0, 0, data);
             mat_f = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); //for storing manipulated Mat
    
             //conversion to grayscale, blurring and edge detection
             Imgproc.cvtColor(mat, mat_f, Imgproc.COLOR_RGB2BGR);
             Imgproc.cvtColor(mat_f, mat_f, Imgproc.COLOR_RGB2GRAY);
             Imgproc.GaussianBlur(mat_f, mat_f, new Size(13,13), 0);             
             Imgproc.Canny(mat_f, mat_f, 300, 600, 5, true);
             Imgproc.dilate(mat_f, mat_f, new Mat(), new Point(-1, -1), 2);
             Imgcodecs.imwrite("D:\\JAVA\\Image_Proc\\CVTest1.jpg",mat_f);
    
             //finding contours
             List<MatOfPoint> contours = new ArrayList<MatOfPoint>();    
             Mat hierarchy = new Mat();
             Imgproc.findContours(mat_f, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
             double maxArea=0;
             int maxAreaIdx=0;
    
             //finding largest contour
             for (int idx = 0; idx != contours.size(); ++idx)
             {
                   Mat contour = contours.get(idx);
                   double contourarea = Imgproc.contourArea(contour);
                   if (contourarea > maxArea)
                   {
                       maxArea = contourarea;
                       maxAreaIdx = idx;
                   }
    
              }
    
                //Rect rect = Imgproc.boundingRect(contours.get(maxAreaIdx));
                //Imgproc.rectangle(mat, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar(0,0,255),7);
               // mat = mat.submat(rect.y, rect.y + rect.height, rect.x, rect.x + rect.width);
    
    
              //Polygon approximation
              MatOfPoint2f approxCurve = new MatOfPoint2f();
              MatOfPoint2f oriCurve = new MatOfPoint2f(contours.get(maxAreaIdx).toArray());
              Imgproc.approxPolyDP(oriCurve, approxCurve, 6.0, true);
    
              //drawing red markers at vertices
              Point [] array = approxCurve.toArray();
              for(int i=0; i < array.length;i++) {
                 Imgproc.circle(mat, array[i], 2, new Scalar(0, 255, 0), 5);
              }
              Imgcodecs.imwrite("D:\\JAVA\\Image_Proc\\CVTest.jpg",mat);
    
    System.loadLibrary(Core.NATIVE\u LIBRARY\u NAME);
    //加载图像
    文件输入=新文件(“card4.png”);
    BuffereImage image=ImageIO.read(输入);
    字节[]数据=((DataBufferByte)image.getRaster().getDataBuffer()).getData();
    //将读取的图像放到垫子上
    mat=新mat(image.getHeight()、image.getWidth()、CvType.CV_8UC3)//原垫
    材料放置(0,0,数据);
    mat_f=新mat(image.getHeight()、image.getWidth()、CvType.CV_8UC3)//用于存放被操纵的垫子
    //转换为灰度、模糊和边缘检测
    Imgproc.cvt颜色(mat,mat_f,Imgproc.COLOR_RGB2BGR);
    Imgproc.cvt颜色(mat\u f、mat\u f、Imgproc.COLOR\u RGB2GRAY);
    GaussianBlur(mat_f,mat_f,新尺寸(13,13),0);
    Imgproc.Canny(mat_f,mat_f,300600,5,true);
    Imgproc.deplate(mat_f,mat_f,new mat(),new Point(-1,-1),2);
    Imgcodecs.imwrite(“D:\\JAVA\\Image\u Proc\\CVTest1.jpg”,mat\u f);
    //寻找等高线
    列表等高线=新的ArrayList();
    Mat层次结构=新Mat();
    Imgproc.findContours(材质、轮廓、层次、Imgproc.RETR\u外部、Imgproc.CHAIN\u近似\u简单);
    双最大面积=0;
    int maxAreaIdx=0;
    //寻找最大等高线
    对于(int idx=0;idx!=courts.size();++idx)
    {
    Mat contour=contours.get(idx);
    双轮廓面积=Imgproc.轮廓面积(轮廓);
    如果(轮廓面积>最大面积)
    {
    最大面积=轮廓面积;
    maxAreaIdx=idx;
    }
    }
    //Rect Rect=Imgproc.boundingRect(contours.get(maxAreaIdx));
    //Imgproc.矩形(mat,新点(rect.x,rect.y),新点(rect.x+rect.width,rect.y+rect.height),新标量(0,0255),7);
    //mat=mat.submat(矩形y,矩形y+矩形高度,矩形x,矩形x+矩形宽度);
    //多边形近似
    MatOfPoint2f approxCurve=新的MatOfPoint2f();
    MatOfPoint2f oriCurve=新的MatOfPoint2f(courts.get(maxAreaIdx.toArray());
    Imgproc.approxPolyDP(oriCurve,approxCurve,6.0,true);
    //在顶点处绘制红色标记
    点[]数组=approxCurve.toArray();
    for(int i=0;i
    正在寻求帮助以获取适当的角点顶点。。。
    提前感谢。

    为了使用您的方法归档好的结果,您的卡必须包含4个角。但我更喜欢使用HoughLine方法完成此任务。
    步骤1:调整图像大小以获得更高的性能

    步骤2:边缘检测
    • 将图像转换为灰度
    • 模糊图像以清除噪声
    • 基于Canny滤波器的边缘检测
    在下一步中,您可以使用放大使白色变大

    第三步:找到卡片的角落
    • 寻找图像的轮廓
    • 从轮廓列表中获得最大轮廓
    • 抓住它
    • 使用APROXPOLYDP简化凸面外壳(这将给出一个四边形)
    • 从现在开始,您可以绘制等高线,以获得恢复比例后的矩形
    • 从四边形可以得到4个角
    • 查找单应性
    • 使用计算的单应矩阵扭曲输入图像
    下面是Java中的示例代码

        // STEP 1: Resize input image to img_proc to reduce computation
        double ratio = DOWNSCALE_IMAGE_SIZE / Math.max(frame.width(), frame.height());
        Size downscaledSize = new Size(frame.width() * ratio, frame.height() * ratio);
        Mat dst = new Mat(downscaledSize, frame.type());
        Imgproc.resize(frame, dst, downscaledSize);
        Mat grayImage = new Mat();
        Mat detectedEdges = new Mat();
        // STEP 2: convert to grayscale
        Imgproc.cvtColor(dst, grayImage, Imgproc.COLOR_BGR2GRAY);
        // STEP 3: try to filter text inside document
        Imgproc.medianBlur(grayImage, detectedEdges, 9);
        // STEP 4: Edge detection
        Mat edges = new Mat();
        // Imgproc.erode(edges, edges, new Mat());
        // Imgproc.dilate(edges, edges, new Mat(), new Point(-1, -1), 1); // 1
        // canny detector, with ratio of lower:upper threshold of 3:1
        Imgproc.Canny(detectedEdges, edges, this.threshold.getValue(), this.threshold.getValue() * 3, 3, true);
        // STEP 5: makes the object in white bigger to join nearby lines
        Imgproc.dilate(edges, edges, new Mat(), new Point(-1, -1), 1); // 1
        Image imageToShow = Utils.mat2Image(edges);
        updateImageView(cannyFrame, imageToShow);
        // STEP 6: Compute the contours
        List<MatOfPoint> contours = new ArrayList<>();
        Imgproc.findContours(edges, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
        // STEP 7: Sort the contours by length and only keep the largest one
        MatOfPoint largestContour = getMaxContour(contours);
        // STEP 8: Generate the convex hull of this contour
        Mat convexHullMask = Mat.zeros(frame.rows(), frame.cols(), frame.type());
        MatOfInt hullInt = new MatOfInt();
        Imgproc.convexHull(largestContour, hullInt);
        MatOfPoint hullPoint = OpenCVUtil.getNewContourFromIndices(largestContour, hullInt);
        // STEP 9: Use approxPolyDP to simplify the convex hull (this should give a quadrilateral)
        MatOfPoint2f polygon = new MatOfPoint2f();
        Imgproc.approxPolyDP(OpenCVUtil.convert(hullPoint), polygon, 20, true);
        List<MatOfPoint> tmp = new ArrayList<>();
        tmp.add(OpenCVUtil.convert(polygon));
        restoreScaleMatOfPoint(tmp, ratio);
        Imgproc.drawContours(convexHullMask, tmp, 0, new Scalar(25, 25, 255), 2);
        // Image extractImageToShow = Utils.mat2Image(convexHullMask);
        // updateImageView(extractFrame, extractImageToShow);
        MatOfPoint2f finalCorners = new MatOfPoint2f();
        Point[] tmpPoints = polygon.toArray();
        for (Point point : tmpPoints) {
            point.x = point.x / ratio;
            point.y = point.y / ratio;
        }
        finalCorners.fromArray(tmpPoints);
        boolean clockwise = true;
        double currentThreshold = this.threshold.getValue();
        if (finalCorners.toArray().length == 4) {
            Size size = getRectangleSize(finalCorners);
            Mat result = Mat.zeros(size, frame.type());
            // STEP 10: Homography: Use findHomography to find the affine transformation of your paper sheet
            Mat homography = new Mat();
            MatOfPoint2f dstPoints = new MatOfPoint2f();
            Point[] arrDstPoints = { new Point(result.cols(), result.rows()), new Point(0, result.rows()), new Point(0, 0), new Point(result.cols(), 0) };
            dstPoints.fromArray(arrDstPoints);
            homography = Calib3d.findHomography(finalCorners, dstPoints);
    
            // STEP 11: Warp the input image using the computed homography matrix
            Imgproc.warpPerspective(frame, result, homography, size);
        }
    
    //步骤1:将输入图像调整为img_proc以减少计算量
    双倍比率=缩尺\图像\大小/Math.max(frame.width(),frame.height());
    尺寸缩小尺寸=新尺寸(框宽()*比率,框高()*比率);
    Mat dst=新Mat(缩小尺寸,frame.type());
    Imgproc.resize(帧、dst、缩小尺寸);
    Mat grayImage=新Mat();
    Mat DetectedEdge=新Mat();
    //步骤2:转换为灰度
    Imgproc.cvt颜色(dst、灰度图像、Imgproc.COLOR_bgr2灰度);
    //步骤3:尝试筛选文档中的文本
    Imgproc.medianBlur(灰度图像,检测到的边缘,9);
    //步骤4:边缘检测
    垫边=新垫();
    //侵蚀(边缘,边缘,新垫());
    //Imgproc.deflate(边,边,新垫(),新点(-1,-1),1);//1.
    //canny检测器,下限与上限阈值之比为3:1
    Canny(detectedEdges,edges,this.threshold.getValue(),this.threshold.getValue()*3,3,true);
    //步骤5:使白色的对象变大以连接附近的线
    Imgproc.deflate(边,边,新垫(),新点(-1,-1),1);//1.
    Image imagestoshow=Utils.mat2Image(边缘);
    更新图像视图(cannyFrame,imageToShow);
    //步骤6:计算轮廓
    列表等高线=新的ArrayList();
    Imgproc.findContours(边、轮廓、新垫()、Imgproc.RETR\u列表、Imgproc.CHAIN\u近似值\u简单值);
    //步骤7:按长度对轮廓进行排序,只保留最大的轮廓
    最大轮廓点=g