如何使用open cv从图像中获取极端外部标志(最外面的框)?

问题描述 投票:0回答:1

所以我试图从这张图片Picture for reference中提取框。根据open CV documentationRETR_EXTERNAL应该返回“只有极端的外部旗帜”。他们的话不是我的。根据他们返回的只返回每个家庭中最大的父母。因此,我假设使用RETR_EXTERNAL将提取参考图像中的表格和按钮。但是当我使用RETR_EXTERNAL时,它仅生成参考图像(我首先链接的图像)作为输出。这几乎就像整个图像周围都有一个看不见的盒子。 任何帮助表示赞赏


如果您需要,这是代码:

import cv2
import numpy as np
import argparse
import imutils
import nn 
from PIL import Image, ImageFont, ImageDraw, ImageEnhance
def sort_contours(cnts, method="left-to-right"):
    # initialize the reverse flag and sort index
    reverse = False
    i = 0

    # handle if we need to sort in reverse
    if method == "right-to-left" or method == "bottom-to-top":
        reverse = True

    # handle if we are sorting against the y-coordinate rather than
    # the x-coordinate of the bounding box
    if method == "top-to-bottom" or method == "bottom-to-top":
        i = 1

    # construct the list of bounding boxes and sort them from top to
    # bottom
    boundingBoxes = [cv2.boundingRect(c) for c in cnts]
    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
        key=lambda b:b[1][i], reverse=reverse))

    # return the list of sorted contours and bounding boxes
    return (cnts, boundingBoxes)
def box_extraction(img_for_box_extraction_path, cropped_dir_path):
    # Read the image
    img = cv2.imread('41.jpg', 0)
    (thresh, img_bin) = cv2.threshold(img, 128, 255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)
    #print len(img_bin)

    img_bin =255-img_bin 
    cv2.imwrite("Image_bin.jpg",img_bin)
    # Defining a kernel length
    kernel_length = np.array(img).shape[1]/80
    #print kernel_length
    verticle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_length))

    # A horizontal kernel of (kernel_length X 1), which will help to detect all the horizontal line from the image.
    hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length, 1))

    # A kernel of (3 X 3) ones.
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

    # Morphological operation to detect vertical lines from an image
    img_temp1 = cv2.erode(img_bin, verticle_kernel, iterations=7)
    verticle_lines_img = cv2.dilate(img_temp1, verticle_kernel, iterations=7)
    cv2.imwrite("verticle_lines.jpg",verticle_lines_img)
    # Morphological operation to detect horizontal lines from an image
    img_temp2 = cv2.erode(img_bin, hori_kernel, iterations=7)
    horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=7)
    cv2.imwrite("horizontal_lines.jpg",horizontal_lines_img)

    # Weighting parameters, this will decide the quantity of an image to be added to make a new image.
    alpha = 0.6
    beta = 1.0 - alpha


    # This function helps to add two image with specific weight parameter to get a third image as summation of two image.
    img_final_bin = cv2.addWeighted(verticle_lines_img, alpha, horizontal_lines_img, beta, 0.0)
    img_final_bin = cv2.erode(~img_final_bin, kernel, iterations=2)
    (thresh, img_final_bin) = cv2.threshold(img_final_bin, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)



    # Find contours for image, which will detect all the boxes
    im2, contours, hierarchy = cv2.findContours(img_final_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # Sort all the contours by top to bottom.
    #(contours, boundingBoxes) = sort_contours(contours, method="top-to-bottom")
python opencv
1个回答
0
投票

来自documentation

在OpenCV中,找到轮廓就像从黑色背景中找到白色物体。所以请记住,要找到的对象应该是白色,背景应该是黑色。

findContours首先搜索白色物体。因此,最外面的轮廓是白色背景。您可以通过在阈值处理时使用img = cv2.bitwise_not(img)或使用cv2.THRESH_BINARY_INV反转图像来轻松解决此问题:

结果:

enter image description here

示例代码:

    import numpy as np 
    import cv2
    #load the image:  
    img = cv2.imread("box.jpg") 
    # create grayscale
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # threshold image to remove noise and create an inverted mask
    ret,mask = cv2.threshold(gray,230,255,cv2.THRESH_BINARY_INV)
    #Find contours (external only):  
    im, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  
    #draw contours on original image
    cv2.drawContours(img, contours, -1, (0,0,255), thickness=2)
    # show image
    cv2.imshow("Image", img)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

注意:你也可以将图像加载为灰度并跳过创建一个,但我在这里使用它,所以我可以绘制更明显的红色框。

© www.soinside.com 2019 - 2024. All rights reserved.