从图像中裁剪掉部分(findContours?){opencv,java}

时间:2014-04-17 13:20:04

标签: java opencv crop

我的这张图片的框中包含字母,如下所示:

Original

我已经能够裁掉每个盒子了,像这样:

Picture of a cropped box containing a letter

现在回答我的问题。我怎样才能从每个盒子中裁剪掉字母?期望的结果如下所示

desired result

我想使用findContours,但我不确定如何实现这一点,因为它会检测噪音和周围的一切。

1 个答案:

答案 0 :(得分:14)

<强>方法 我根据这个事实建议你采用以下方法,你可以提取盒子。如果你按照步骤给出方框,我认为这样可行:

  1. 找到图像中心
  2. 查找图像中的轮廓 - 可以是候选人
  3. 找到每个轮廓的边界矩形
  4. 找到每个边界矩形的中心
  5. 从图像中心找到每个边界矩形的距离
  6. 找到最小距离 - 您的答案
  7. 注意:有一个名为pad的var控制结果数字的填充! 为你的所有盒子做这个。我希望这会有所帮助!

    祝你好运:)


    Python代码

    # reading image in grayscale
    image = cv2.imread('testing2.jpg',cv2.CV_LOAD_IMAGE_GRAYSCALE)
    # thresholding to get a binary one
    ret, image = cv2.threshold(image, 100,255,cv2.THRESH_BINARY_INV)
    # finding the center of image
    image_center = (image.shape[0]/2, image.shape[1]/2)
    
    if image is None:
        print 'can not read the image data'
    # finding image contours
    contours, hier = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # finding distance of each contour from the center of image
    d_min = 1000
    for contour in contours:
        # finding bounding rect
        rect = cv2.boundingRect(contour)
        # skipping the outliers
        if rect[3] > image.shape[1]/2 and rect[2] > image.shape[0]/2:
            continue
        pt1 = (rect[0], rect[1])
        # finding the center of bounding rect-digit
        c = (rect[0]+rect[2]*1/2, rect[1]+rect[3]*1/2)
        d = np.sqrt((c[0] - image_center[0])**2 + (c[1]-image_center[1])**2)
        # finding the minimum distance from the center
        if d < d_min:
            d_min = d
            rect_min = [pt1, (rect[2],rect[3])]
    # fetching the image with desired padding
    pad = 5
    result = image[rect_min[0][1]-pad:rect_min[0][1]+rect_min[1][1]+pad, rect_min[0][0]-pad:rect_min[0][0]+rect_min[1][0]+pad]
    
    plt.imshow(result*255, 'gray')
    plt.show()
    

    Java代码

        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        // reading image 
        Mat image = Highgui.imread(".\\testing2.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE);
        // clone the image 
        Mat original = image.clone();
        // thresholding the image to make a binary image
        Imgproc.threshold(image, image, 100, 128, Imgproc.THRESH_BINARY_INV);
        // find the center of the image
        double[] centers = {(double)image.width()/2, (double)image.height()/2};
        Point image_center = new Point(centers);
    
        // finding the contours
        ArrayList<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Mat hierarchy = new Mat();
        Imgproc.findContours(image, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
    
        // finding best bounding rectangle for a contour whose distance is closer to the image center that other ones
        double d_min = Double.MAX_VALUE;
        Rect rect_min = new Rect();
        for (MatOfPoint contour : contours) {
            Rect rec = Imgproc.boundingRect(contour);
            // find the best candidates
            if (rec.height > image.height()/2 & rec.width > image.width()/2)            
                continue;
            Point pt1 = new Point((double)rec.x, (double)rec.y);
            Point center = new Point(rec.x+(double)(rec.width)/2, rec.y + (double)(rec.height)/2);
            double d = Math.sqrt(Math.pow((double)(pt1.x-image_center.x),2) + Math.pow((double)(pt1.y -image_center.y), 2));            
            if (d < d_min)
            {
                d_min = d;
                rect_min = rec;
            }                   
        }
        // slicing the image for result region
        int pad = 5;        
        rect_min.x = rect_min.x - pad;
        rect_min.y = rect_min.y - pad;
    
        rect_min.width = rect_min.width + 2*pad;
        rect_min.height = rect_min.height + 2*pad;
    
        Mat result = original.submat(rect_min);     
        Highgui.imwrite("result.png", result);
    

    修改 添加了Java代码!

    <强>结果

    enter image description here