what's rules for cv2.approxPolyDP to detect point?

Viewed 2344

I have below two input images:

First:

enter image description here

Second:

enter image description here

Now I wanna detect the square area.

And here is my code:

#!/usr/bin/env python
# coding: utf-8

import numpy as np
import cv2
import argparse
import math
import sys

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image")
args = vars(ap.parse_args())

img = cv2.imread(args["image"])
# img = cv2.bitwise_not(img,img)
# gray = cv2.imread(args["image"],0)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

gray = cv2.GaussianBlur(gray, (5, 5), 0)
cv2.imshow('gray', gray)
cv2.waitKey(0)

gray = cv2.normalize(gray, gray, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8UC1)
cv2.imshow('normalized', gray)
cv2.waitKey(0)
# sys.exit()

ret, thresh = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('thresh', thresh)
# cv2.imwrite('./wni230.png',thresh)
cv2.waitKey(0)

square_cnts = []

thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, np.ones((5, 5), np.uint8))
cv2.imshow('dilated', thresh)
cv2.waitKey(0)
# sys.exit()

tmpimage, contours, h = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt0 = contours[0]

tmp_h = h[::-1]
for index, cnt in enumerate(contours[::-1]):
    print '!!!!!!!!!!! new round !!!!!!!!!!'
    print cv2.arcLength(cnt, True)
    # print cnt
    approx = cv2.approxPolyDP(cnt, 0.1*cv2.arcLength(cnt, True), True)
    print '**********approx*****'
    print approx
    print len(approx)
    print '**********approx end*****'

    if len(approx) == 4:
        print 'h[i][2]:%s' % tmp_h[0][index][2]
        print 'h[i][3]:%s' % tmp_h[0][index][3]
        if ret > 0.5:
            print "Parallelogram"
        elif 0.3 < ret < 0.5:
            print "Rectangle"
        elif 0 < ret < 0.3:
            print "Rhombus"
        else:
            print "square"
        print cv2.arcLength(cnt, True)
        print approx
        cv2.drawContours(img, [cnt], 0, (0, 0, 255), 2)
        cv2.imshow('tmpsquare', img)
        cv2.waitKey(0)
        if int(cv2.arcLength(cnt, True)) >= 96:

            x, y, w, h = cv2.boundingRect(approx)
            for j in approx:
                cv2.circle(img, (int(j[0][0]), int(j[0][1])), 1, (0, 255, 0), 2)
            cv2.imshow('final', img[y:y+h, x:x+w])
            cv2.waitKey(0)
            print 'target but long squere detected...'
            cv2.waitKey(0)

cv2.imshow('img', img)
cv2.imwrite('tmp.png', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

So, I got the two output images:

First:

enter image description here

Second:

enter image description here

Line in red is contour, point in green is points detected by approxPolyDP.

So, the first one is what I wanna.

However, how approxPolyDP locate the up most point for the second one?

Could anyone please explain the rules?

Env:

Python: 2.7.10

Opencv: 3.2.0

Thanks.

Wesley

0 Answers
Related