'Unable to get accurate contour of Images

I'm attempting to accurately get the contour of the bounding box around the comic book cover in the attached example images.

enter image description hereenter image description here

This is the code that I currently have.

from pyimagesearch import imutils
from skimage import exposure
import numpy as np
import argparse
import cv2

ap = argparse.ArgumentParser()
ap.add_argument("-q", "--query", required = True,
    help = "Path to the query image")
args = vars(ap.parse_args())


print(args["query"])
# load the query image, compute the ratio of the old height
# to the new height, clone it, and resize it
image = cv2.imread(args["query"])
ratio = image.shape[0] / 300.0
orig = image.copy()
image = imutils.resize(image, height = 300)
# convert the image to grayscale, blur it, and find edges
# in the image
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.bilateralFilter(gray, 11, 17, 17)
edged = cv2.Canny(gray, 30, 200)


#find contours in the edged image, keep only the largest
# ones, and initialize our screen contour
cnts = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:4]
screenCnt = None

# loop over our contours

rect_cnts = []
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.04 * peri, True)
    if len(approx) == 4: # shape filtering condition
        screenCnt = approx
        break

print(screenCnt)
cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 3) 
cv2.imshow("Book Image", image) 
cv2.waitKey(0)


The problem arises when I try to do the shape filtering.

rect_cnts = []
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.04 * peri, True)
    if len(approx) == 4: # shape filtering condition
        screenCnt = approx
        break

It appears as if the contours returned are not qualifying as a rectangle. I'm not sure how to fine-tune this so that the contour is better. These are the results I'm currently getting.

enter image description hereenter image description here



Solution 1:[1]

You can use an attribute = value css selector with * contains operator

from bs4 import BeautifulSoup as bs

html = '''
<input data-reactid=".0.1.2.0.0.0.0.$=2fields.0.2.0.0.1.0:$90.0:$=2edit.0.0.0" type="checkbox"/>
<input data-reactid=".0.1.2.0.0.0.0.$=2fields.0.2.0.0.1.0:$100.0:$=2edit.0.0.0" type="checkbox"/>
<input data-reactid=".0.1.2.0.0.0.0.$=2fields.0.2.0.0.1.0:$110.0:$=2default.0.0.2.0.0" type="checkbox"/>
<input data-reactid=".0.1.2.0.0.0.0.$=2fields.0.2.0.0.1.0:$110.0:$=2edit.0.0.0" type="checkbox"/>'''

soup = bs(html, 'lxml')
soup.select('input[data-reactid*=edit][type=checkbox]')

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 QHarr