Crop black edges with OpenCV

后端 未结 7 1462
遥遥无期
遥遥无期 2020-12-01 01:08

I think it should be a very simple problem, but I cannot find a solution or an effective keyword for search.

I just have this image.

相关标签:
7条回答
  • 2020-12-01 01:16

    I am not sure whether all your images are like this. But for this image, below is a simple python-opencv code to crop it.

    first import libraries :

    import cv2
    import numpy as np
    

    Read the image, convert it into grayscale, and make in binary image for threshold value of 1.

    img = cv2.imread('sofwin.png')
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    _,thresh = cv2.threshold(gray,1,255,cv2.THRESH_BINARY)
    

    Now find contours in it. There will be only one object, so find bounding rectangle for it.

    contours,hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    cnt = contours[0]
    x,y,w,h = cv2.boundingRect(cnt)
    

    Now crop the image, and save it into another file.

    crop = img[y:y+h,x:x+w]
    cv2.imwrite('sofwinres.png',crop)
    

    Below is the result :

    enter image description here

    0 讨论(0)
  • 2020-12-01 01:19

    I thought this answer is much more succinct:

    def crop(image):
        y_nonzero, x_nonzero, _ = np.nonzero(image)
        return image[np.min(y_nonzero):np.max(y_nonzero), np.min(x_nonzero):np.max(x_nonzero)]
    
    0 讨论(0)
  • 2020-12-01 01:25

    In case it helps anyone, I went with this tweak of @wordsforthewise's replacement for a PIL-based solution:

    bw = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    rows, cols = bw.shape
    
    non_empty_columns = np.where(bw.max(axis=0) > 0)[0]
    non_empty_rows = np.where(bw.max(axis=1) > 0)[0]
    cropBox = (min(non_empty_rows) * (1 - padding),
                min(max(non_empty_rows) * (1 + padding), rows),
                min(non_empty_columns) * (1 - padding),
                min(max(non_empty_columns) * (1 + padding), cols))
    
    return img[cropBox[0]:cropBox[1]+1, cropBox[2]:cropBox[3]+1 , :]
    

    (It's a tweak in that the original code expects to crop away a white background rather than a black one.)

    0 讨论(0)
  • 2020-12-01 01:30

    Python Version 3.6


    Crop images and insert into a 'CropedImages' folder

    import cv2
    import os
    
    arr = os.listdir('./OriginalImages')
    
    for itr in arr:
        img = cv2.imread(itr)
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        _,thresh = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY)
        _, contours, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
        cnt = contours[0]
        x,y,w,h = cv2.boundingRect(cnt)
        crop = img[y:y+h,x:x+w]
        cv2.imwrite('CropedImages/'+itr,crop)
    

    Change the number 120 to other in 9th line and try for your images, It will work

    0 讨论(0)
  • 2020-12-01 01:31

    How about a slick little recursive function?

    import cv2
    import numpy as np
    def trim(frame):
        #crop top
        if not np.sum(frame[0]):
            return trim(frame[1:])
        #crop bottom
        elif not np.sum(frame[-1]):
            return trim(frame[:-2])
        #crop left
        elif not np.sum(frame[:,0]):
            return trim(frame[:,1:]) 
        #crop right
        elif not np.sum(frame[:,-1]):
            return trim(frame[:,:-2])    
        return frame
    

    Load and threshold the image to ensure the dark areas are black:

    img = cv2.imread("path_to_image.png")   
    thold = (img>120)*img
    

    Then call the recursive function

    trimmedImage = trim(thold)
    
    0 讨论(0)
  • 2020-12-01 01:35
    import numpy as np
    
    def autocrop(image, threshold=0):
        """Crops any edges below or equal to threshold
    
        Crops blank image to 1x1.
    
        Returns cropped image.
    
        """
        if len(image.shape) == 3:
            flatImage = np.max(image, 2)
        else:
            flatImage = image
        assert len(flatImage.shape) == 2
    
        rows = np.where(np.max(flatImage, 0) > threshold)[0]
        if rows.size:
            cols = np.where(np.max(flatImage, 1) > threshold)[0]
            image = image[cols[0]: cols[-1] + 1, rows[0]: rows[-1] + 1]
        else:
            image = image[:1, :1]
    
        return image
    
    0 讨论(0)
提交回复
热议问题