如何使用Open CV从图像中获取极端的外部标志(最外面的盒子)?

时间:2019-02-25 04:12:26

标签: python opencv

所以我试图从这张图片Picture for reference中提取盒子。根据{{​​3}},RETR_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")

2 个答案:

答案 0 :(得分: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()

注意:您还可以将图像加载为灰度图像,并跳过创建图像的步骤,但是我在这里使用了它,因此可以绘制更多明显的红色框。

答案 1 :(得分:0)

对我有用的J.D.的更新代码

import numpy as np 
import cv2

img = cv2.imread("image_1.jpg") 

## create grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

## threshold image to remove noise and create an inverted mask with with OTSU
mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

## Find contours (external only):  
## Since the cv2.findContours has been updated to return only 2 parameters
contours, hierarchy= cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 

## draw contours on original image
cv2.drawContours(img, contours, -1, (255,0,0), thickness=2)

## show image
cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()