代码之家  ›  专栏  ›  技术社区  ›  Shahariar Rabby

如何使用python opencv裁剪图像中最大的对象?

  •  6
  • Shahariar Rabby  · 技术社区  · 7 年前

    我想裁剪图像中最大的对象(字符)。此代码仅在没有行(如第一幅图所示)时有效。但我需要忽略这条线,并制作第二幅图像的图像。仅裁剪最大的对象图像。

    import cv2
    x1, y1, w1, h1 = (0,0,0,0)
    points = 0
    
    # load image
    img = cv2.imread('Image.jpg') 
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert to grayscale
    # threshold to get just the signature
    retval, thresh_gray = cv2.threshold(gray, thresh=100, maxval=255, type=cv2.THRESH_BINARY)
    
    # find where the signature is and make a cropped region
    points = np.argwhere(thresh_gray==0) # find where the black pixels are
    points = np.fliplr(points) # store them in x,y coordinates instead of row,col indices
    x, y, w, h = cv2.boundingRect(points) # create a rectangle around those points
    crop = img[y:y+h, x:x+w]
    cv2.imshow('save.jpg', crop)
    cv2.waitkey(0)
    

    输入 Original Image

    输出: Output Image

    2 回复  |  直到 7 年前
        1
  •  11
  •   Andriy Makukha    4 年前

    您可以使用函数 findContours 这样做。

    例如,如下所示:

    #!/usr/bin/env python
    
    import cv2
    import numpy as np
    
    # load image
    img = cv2.imread('Image.jpg')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert to grayscale
    # threshold to get just the signature (INVERTED)
    retval, thresh_gray = cv2.threshold(gray, thresh=100, maxval=255, \
                                       type=cv2.THRESH_BINARY_INV)
    
    image, contours, hierarchy = cv2.findContours(thresh_gray,cv2.RETR_LIST, \
                                       cv2.CHAIN_APPROX_SIMPLE)
    
    # Find object with the biggest bounding box
    mx = (0,0,0,0)      # biggest bounding box so far
    mx_area = 0
    for cont in contours:
        x,y,w,h = cv2.boundingRect(cont)
        area = w*h
        if area > mx_area:
            mx = x,y,w,h
            mx_area = area
    x,y,w,h = mx
    
    # Output to files
    roi=img[y:y+h,x:x+w]
    cv2.imwrite('Image_crop.jpg', roi)
    
    cv2.rectangle(img,(x,y),(x+w,y+h),(200,0,0),2)
    cv2.imwrite('Image_cont.jpg', img)
    

    请注意,我使用了THRESH\u BINARY\u INV而不是THRESH\u BINARY。

    Image\u cont.jpg:

    Biggest contour: box around the sign

    Image\u裁剪。jpg:

    Sign cropped


    正如@Jello所指出的,您也可以将其用于倾斜的矩形。与上面更简单的解决方案不同,这将正确过滤掉对角线。

    例如:

    #!/usr/bin/env python
    
    import cv2
    import numpy as np
    
    # load image
    img = cv2.imread('Image2.png')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # convert to grayscale
    # threshold to get just the signature (INVERTED)
    retval, thresh_gray = cv2.threshold(gray, 100, maxval=255, \
                                       type=cv2.THRESH_BINARY_INV)
    
    image, contours, hierarchy = cv2.findContours(thresh_gray,cv2.RETR_LIST, \
                                       cv2.CHAIN_APPROX_SIMPLE)
    
    def crop_minAreaRect(img, rect):
        # Source: https://stackoverflow.com/questions/37177811/
    
        # rotate img
        angle = rect[2]
        rows,cols = img.shape[0], img.shape[1]
        matrix = cv2.getRotationMatrix2D((cols/2,rows/2),angle,1)
        img_rot = cv2.warpAffine(img,matrix,(cols,rows))
    
        # rotate bounding box
        rect0 = (rect[0], rect[1], 0.0)
        box = cv2.boxPoints(rect)
        pts = np.int0(cv2.transform(np.array([box]), matrix))[0]
        pts[pts < 0] = 0
    
        # crop and return
        return img_rot[pts[1][1]:pts[0][1], pts[1][0]:pts[2][0]]
    
    # Find object with the biggest bounding box
    mx_rect = (0,0,0,0)      # biggest skewed bounding box
    mx_area = 0
    for cont in contours:
        arect = cv2.minAreaRect(cont)
        area = arect[1][0]*arect[1][1]
        if area > mx_area:
            mx_rect, mx_area = arect, area
    
    # Output to files
    roi = crop_minAreaRect(img, mx_rect)
    cv2.imwrite('Image_crop.jpg', roi)
    
    box = cv2.boxPoints(mx_rect)
    box = np.int0(box)
    cv2.drawContours(img,[box],0,(200,0,0),2)
    cv2.imwrite('Image_cont.jpg', img)
    

    Image2.png(输入图像):

    Signature with a diagonal long line

    Image\u cont.jpg:

    Signature with a skewed bounding box

    Image\u裁剪。jpg:

    Skewed signature after cropping


    image, contours, hierarchy 只是 contours, hierarchy

        2
  •  -2
  •   whiteFang    7 年前

    Python的findContours是您的最佳选择

        #use this only on grayscaled image
        thresh = cv2.threshold(yourImage, 40, 255, cv2.THRESH_BINARY)[1]
    
        # dilate the thresholded image to fill in holes, then find contours
        # on thresholded image
        thresh = cv2.dilate(thresh, None, iterations=2)
        (_,cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
            cv2.CHAIN_APPROX_SIMPLE)
    
        largest = max(cnts)