有什么办法可以裁剪盒子内的图像?

时间:2020-05-12 14:32:51

标签: python image numpy opencv image-processing

Image

我只想裁剪框或矩形内的图像。我尝试了很多方法,但是没有用。

import cv2
import numpy as np

img  = cv2.imread("C:/Users/hp/Desktop/segmentation/add.jpeg", 0);
h, w = img.shape[:2]
# print(img.shape)
kernel = np.ones((3,3),np.uint8)

img2 = img.copy()

img2 = cv2.medianBlur(img2,5)
img2 = cv2.adaptiveThreshold(img2,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY,11,2)

img2 = 255 - img2
img2 = cv2.dilate(img2, kernel)
img2 = cv2.medianBlur(img2, 9)
img2 = cv2.medianBlur(img2, 9)

cv2.imshow('anything', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()


position = np.where(img2 !=0)
x0 = position[0].min()
x1 = position[0].max()
y0 = position[1].min()
y1 = position[1].max()

print(x0,x1,y0,y1)

result = img[x0:x1,y0:y1]

cv2.imshow('anything', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出应为方形内的图像。

2 个答案:

答案 0 :(得分:4)

您可以为此使用轮廓检测​​。如果您的图像中基本上只有一个手绘矩形,那么我认为假定它是图像中最大的闭合轮廓就足够了。根据该轮廓,我们可以找出多边形/四边形的近似值,然后最终得到一个近似的矩形。我将在开始时定义一些实用程序,这些实用程序通常使我在弄乱图像时更加轻松:

def load_image(filename):
    return cv2.imread(filename)

def bnw(image):
    return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

def col(image):
    return cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)

def fixrgb(image):
    return cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

def show_image(image, figsize=(7,7), cmap=None):
    cmap = cmap if len(image.shape)==3 else 'gray'
    plt.figure(figsize=figsize)
    plt.imshow(image, cmap=cmap)
    plt.show()

def AdaptiveThresh(gray):
    blur = cv2.medianBlur(gray, 5)
    adapt_type = cv2.ADAPTIVE_THRESH_GAUSSIAN_C
    thresh_type = cv2.THRESH_BINARY_INV
    return cv2.adaptiveThreshold(blur, 255, adapt_type, thresh_type, 11, 2)

def get_rect(pts):
    xmin = pts[:,0,1].min()
    ymin = pts[:,0,0].min()
    xmax = pts[:,0,1].max()
    ymax = pts[:,0,0].max()
    return (ymin,xmin), (ymax,xmax)

让我们加载图像并将其转换为灰度:

image_name = 'test.jpg'
image_original = fixrgb(load_image(image_name))
image_gray = 255-bnw(image_original)
show_image(image_gray)

grayscale

使用一些变形操作来增强图像:

kernel = np.ones((3,3),np.uint8)
d = 255-cv2.dilate(image_gray,kernel,iterations = 1)
show_image(d)    

d

找到边缘并增强/降噪

e = AdaptiveThresh(d)
show_image(e)

e

m = cv2.dilate(e,kernel,iterations = 1)
m = cv2.medianBlur(m,11)
m = cv2.dilate(m,kernel,iterations = 1)
show_image(m)

enter image description here

轮廓检测:

contours, hierarchy = cv2.findContours(m, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

total_area = np.prod(image_gray.shape)
max_area = 0
for cnt in contours:
    # Simplify contour
    perimeter = cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, 0.03 * perimeter, True)
    area = cv2.contourArea(approx)

    # Shape is recrangular, so 4 points approximately and it's convex
    if (len(approx) == 4 and cv2.isContourConvex(approx) and max_area<area<total_area):
        max_area = cv2.contourArea(approx)
        quad_polygon = approx

img1 = image_original.copy()
img2 = image_original.copy()

cv2.polylines(img1,[quad_polygon],True,(0,255,0),10)
show_image(img1)
tl, br = get_rect(quad_polygon)
cv2.rectangle(img2, tl, br, (0,255,0), 10)
show_image(img2)

img1 img2

因此,您可以看到近似的多边形和相应的矩形,使用它们可以获取您的作物。我建议您使用中值模糊和形态学操作(例如腐蚀,膨胀,打开,关闭等),并查看哪组操作最适合您的图像;我不能仅凭一张图像就说出什么有好处。您可以使用左上角和右下角坐标进行裁剪:

show_image(image_original[tl[1]:br[1],tl[0]:br[0],:])

enter image description here

答案 1 :(得分:1)

用不同的颜色(例如红色)绘制正方形,以便可以与其他文字和背景区分开。然后对其进行阈值处理,以便获得黑白图像:该图像中的红线将为白色。获取白色像素的坐标:从该集合中,仅选择两对(minX,minY)(maxX,maxY)。它们是框的左上角和右下角(请记住,在图像中,0,0点位于图像的左上角),您可以将它们用于crop the image