如何使用python opencv裁剪图像中最大的对象?
我想裁剪图像中最大的对象(字符)。此代码仅在没有行的情况下才有效(如第一幅图像所示)。但是我需要忽略这条线并制作第二张图像。仅裁剪最大的对象图像。
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)
-
您可以使用function
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_BINARY_INV代替THRESH_BINARY。
Image_cont.jpg:
图片_crop.jpg:
您也可以将其与@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(输入图像):
Image_cont.jpg:
图片_crop.jpg:
如果您使用opencv-python 4.x,请更改
image, contours, hierarchy
为justcontours, hierarchy
。