简体   繁体   English

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

[英]How to crop the biggest object in image with python opencv?

I want to crop the biggest object in the image (Characters).我想裁剪图像中最大的对象(字符)。 This code only works if there is no line (shown in the first image).此代码仅在没有行(如第一张图片所示)时才有效。 But I need to ignore the line and make the image of the second image.但是我需要忽略该行并制作第二张图像的图像。 Only crop the biggest object image.只裁剪最大的对象图像。

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)

Input输入原图

Output:输出: 输出图像

You can use function findContours to do this.您可以使用函数findContours来执行此操作。

For example, like this:例如,像这样:

#!/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)

Note that I used THRESH_BINARY_INV instead of THRESH_BINARY.请注意,我使用了 THRESH_BINARY_INV 而不是 THRESH_BINARY。

Image_cont.jpg: Image_cont.jpg:

最大轮廓:标志周围的框

Image_crop.jpg: Image_crop.jpg:

标志裁剪


You can also use this with skewed rectangles as @Jello pointed out.正如@Jello 指出的那样,您也可以将其与倾斜的矩形一起使用。 Unlike simpler solution above, this will correctly filter out diagonal lines.与上面更简单的解决方案不同,这将正确过滤掉对角线。

For example:例如:

#!/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 (the input image): Image2.png(输入图像):

带有斜长线的签名

Image_cont.jpg: Image_cont.jpg:

带有倾斜边界框的签名

Image_crop.jpg: Image_crop.jpg:

裁剪后的偏斜签名


If you use opencv-python 4.x, change image, contours, hierarchy to just contours, hierarchy .如果您使用 opencv-python 4.x,请将image, contours, hierarchy更改为仅contours, hierarchy

Python's findContours is your best option 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM