0

I want to detect the quadrilateral area (i.e. find 4 points best describing the border of the area) corresponding to the projected presentation slide, in order to correct the skewed perspective: test image I'm using the approach which is described in many sources: detect areas by using grayscale -> blur -> bin threshold -> findContours(), then take the largest area and call approxPolyDP():

#!/usr/bin/env python3
import cv2

def maxl(l): return l.index(max(l))

def find_rect(i_inp):
    i_gray = cv2.cvtColor(i_inp, cv2.COLOR_BGR2GRAY)
    i_blur = cv2.GaussianBlur(i_gray, (11, 11), 0)
    i_bin = cv2.threshold(i_blur, 60, 255, cv2.THRESH_BINARY)[1]

    i_2, contours, hierarchy = cv2.findContours(i_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnt_largest_i = maxl(list(cv2.contourArea(c) for c in contours))
    cnt_largest = contours[cnt_largest_i]

    cv2.polylines(i_inp, pts=[cnt_largest], isClosed=False, color=(255, 0, 0), thickness=3)

    epsilon = 0.02 * cv2.arcLength(cnt_largest, True)
    approx = cv2.approxPolyDP(cnt_largest, epsilon, True)

    cv2.polylines(i_inp, pts=[approx], isClosed=False, color=(0, 255, 0), thickness=1)

    cv2.imshow('img', i_inp)
    cv2.waitKey(0)

    return approx


img = cv2.imread('test.jpg')
quad = find_rect(img)

Most typical problem is shown below: (thick blue line shows the largest area before applying approxPolyDP(), and thin green line is what approxPolyDP() gives) epsilon with 0.02
As you can see, with default parameters (multiplier of epsilon = 0.02) upper border is not detected correctly. I tried to play with the multiplier of epsilon, here is the result with 0.01: epsilon with 0.01
in this case upper border is correct but left and lower borders are not. What would you recommend to do here? give up this approach and try Hough Tranform instead?

Vasily A
  • 8,256
  • 10
  • 42
  • 76

1 Answers1

0

Ok, if the PPT's background keeps the same, then I'll choose HSV colorspace and color detection for your task.

enter image description here

I'll choose H(80,100), S(20, 255), v(20, 220) for PPT region.

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, (80, 20, 20), (100, 255, 220))

Then findContours and filter by area, I get this:

enter image description here

It will be better without the white mosaic.

Some links:

  1. Edge detection on colored background using OpenCV

  2. Choosing the correct upper and lower HSV boundaries for color detection with`cv::inRange` (OpenCV)

Kinght 金
  • 17,681
  • 4
  • 60
  • 74