所以我试图从这张图片Picture for reference中提取框。根据open CV documentation,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")
在OpenCV中,找到轮廓就像从黑色背景中找到白色物体。所以请记住,要找到的对象应该是白色,背景应该是黑色。
findContours首先搜索白色物体。因此,最外面的轮廓是白色背景。您可以通过在阈值处理时使用img = cv2.bitwise_not(img)
或使用cv2.THRESH_BINARY_INV
反转图像来轻松解决此问题:
结果:
示例代码:
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()
注意:你也可以将图像加载为灰度并跳过创建一个,但我在这里使用它,所以我可以绘制更明显的红色框。